Tag Archives: security

flash socket policies update

I’ve been getting a lot of positive feedback recently on the post I made last December on this topic, so it’s probably time to post an update.

Last week, Adobe finally released some help for people who need to provide socket policy services. They’ve got python and perl versions of the socket policy daemon that look like they can run either standalone or through xinetd. They don’t claim that the code is production quality yet… but it’s at least something.

Of course, I released sample PHP code 5 months ago… shrug.

My confederates and I have spent the intervening months sniffing packets, yelling at flash, rewriting daemons, etc… until settling upon a version of the service that appears to function reliably now. I am currently running it on 6 different servers and have seen it successfully handle requests from >100 simultaneous users during stress tests.

The biggest problem with my previous versions of the code was how I handled closing of connections. Previously, I had simply accepted connections and fired off the policy xml without waiting for a request from the client.

This worked 95% of the time over a good net connection, and more like 80% of the time over a poor connection.

The reason it didn’t work consistently was because of weird tcp ordering issues. Connections would be closed out of order, the response would be received before the request was dispatched, etc..

My new version is much more robust and actually waits for flash to submit the request before sending the XML. I consider it release candidate beta quality code and hope to be able to release it later today.

update

Version 0.9.b is available now.

shared key gotchas

This is something that has kept coming back to bite me recently.

When you are setting up public-key authentication on OpenSSH, you must be very careful of file ownerships and permissions. In many stock unix setups, this isn’t a problem. But in any environment where you are relying on a lot of group access to files, it is easy to slip up and earn yourself a system that will silently fail to authenticate (unless you turn on debug level verbosity).

  1. The private key must be readable only by the user initiating the connection.
  2. The authorized_hosts file must be writable only by the account accepting the connection.

Sounds simple enough, ne?

The real trick is that group write permission anywhere up the directory tree can render these precautions meaningless. Who cares if I can’t see into .ssh in your home directory if I can manipulate your home dir itself?

  1. $HOME and $HOME/.ssh must be locked down on the destination host.

A general good rule of thumb for permissions might be something like this:

Obviously, this gets kind of tricksy if you want to do something like allow SCP file transfers to the Apache user on a system… and their home dir is /var/www… and your web developers have group write access to this dir.

In situations like that, you have two options. First, you could disable the permissions checks (by turning off StrictModes in the sshd_config), but that’s not advisable. Second, you could make a separate home dir for the apache user with the restrictions in a place where they won’t interfere with anyone’s work.

new flash security policies

So… I am not happy with Adobe right now. With the push of Flash Player 9,0,115,0 “moviestar”, which included such awesome features as H.264 and AAC codec support and improvements to fullscreen mode, they kind of ambushed me with some sweeping changes to their security policy.

I’d been running pre-release nightly builds of the player since 9,0,60,x… and had noticed some strange warnings. Mysterious “Socket Security Error #2048” exceptions that were being thrown at random – even though I was serving an appropriate (for the time) crossdomain.xml file, unexplained timeouts attempting to talk to an xml socket server when I was very clearly not attempting to do any such thing, etc… My regularly repeated attempts to find documentation on what the warnings actually meant proved fruitless. I believe that is because the appropriate document was not actually released to the public until 9,0,115,0 was released.

Now, the bit where they improved the format for crossdomain.xml files doesn’t really affect me one way or the other. I approve of the improvements but could really care less in this case. They don’t really affect anything I’m doing.

The part that really chaps my hide is the fact that they’ve completely redone the way that socket security policies are handled. The important parts:

  • A SWF file may no longer make a socket connection to its own domain without a socket policy file. Prior to version 9,0,115,0, a SWF file was permitted to make socket connections to ports 1024 or greater in its own domain without a policy file.
  • HTTP policy files may no longer be used to authorize socket connections. Prior to version 9,0,115,0, an HTTP policy file, served from the master location of /crossdomain.xml on port 80, could be used to authorize a socket connection to any port 1024 or greater on the same host.

That’s right. Your socket policy data can’t live in the sitewide crossdomain.xml file that Apache serves any more.

Flash Player 9,0,115,0 introduces a concept of socket master policy files, which are served from the fixed TCP port number 843.

Socket policy files may be obtained from the same port as a main connection (the socket connection being made by ActionScript, which is authorized by a socket policy file), or from a different port, separate from the main connection. If you opt to serve a socket policy file from the same port as a main connection, the server listening on that port must understand socket policy file requests (which are indicated by a transmission of from Flash Player), and must respond differently for policy file requests and main connection requests.

  • When a SWF file attempts to make a socket connection, even to its own domain, Flash Player will first attempt to contact port 843 to see if the host is serving a socket master policy file.

So… regardless of whether you’re even using a custom port 843 client, the Flash Player is going to try to hit it. What if your firewall doesn’t allow/route traffic to sub-1024 ports w/o special configuration? What if you don’t have the access to bind to a sub-1024 port and can’t rewrite your other server process to serve the policy data on its port?

  • Socket meta-policies can only be declared in a socket master policy file. The syntax is the same as for declaring a meta-policy in an URL master policy file, using the <site-control> tag. Socket meta-policies cannot be declared in HTTP response headers, as HTTP is not involved.

This implies that you can’t even tell apache to listen to port 843 and serve up the data. You HAVE to either maintain a separate server process specifically for the purpose of serving this policy data, or you have to edit the process that SWF’s are connecting to and make them serve the data..

As of the time of this writing (10 days after moviestar’s release), they have yet to release promised help on how to deploy a solution to these new changes. Granted, the one article they did release explains what needs to be done in high level terms. It was sufficient to help me out. I wrote a server that simply listens on port 843 and spews the required xml. But… I’d have really appreciated specific examples, and I suspect plenty of people would appreciate drop-in solutions to the issue.

A 5-minute skeleton implementation (not recommended for production use by any means) written as a PHP cli script might look something like this:

I’ll try to make my production version of this a bit more suitable for public consumption and release it as soon as I can.

The random #2048 security errors continue, despite having deployed my port 843 policy xml server. Granted, they happen less than before… but they still happen. And even when my policy server isn’t running, the errors aren’t thrown 100% of the time. This just baffles me. If they were consistent, that would be one thing. But when you get a security error 1 time in 20… that’s not security, that’s not even a lame deterrent. It’s just incentive to hammer the same port over and over again until something finally gives.

Now, I admit that I could be wrong here… but I’ve re-re-read the documentation on these policies a few times now, and cannot find any reason for the behaviors I’m seeing.

update

On April 22nd, 2008, I released a much better, much more reliable version of this daemon. Head over there for more details and source code.

optional http auth

Today I encountered an interesting problem. (And please excuse any incoherent rambling right now, I’m writing this from a pretty loud office building where everyone’s getting ready to take off for lunch…)

A site I’m working on is currently restricted from public access (largely because we don’t want the client poking around while it’s in a particularly ugly stage of development :P). We’re restricting this access via the standard issue apache http basic auth system with an .htaccess file that looks something like this:

[code]
AuthType basic
AuthUserFile /not/in/var/www/mars_passwd
AuthGroupFile /dev/null
AuthName "MARS Password Required"
Require valid-user
[/code]

This is all well and good. I have a secure password that the three people working on the site can use to access the pages in question and everything is good.

Until they tell me that they want me to make searches work – searches involving both static and dynamic content. Ie, searches that can only be indexed via some sort of spider application. But, the spider must run over http… and it’s too dumb to both authenticate connections AND leave the passwords out of the url’s it saves in its index…

Now, if I were only developing this site internally, I might want to change my .htaccess file to read something more like this:

[code]
Order allow,deny
Allow from localhost
Allow from xx.yy.zz.com
Deny from all
[/code]

This would let the server do it’s thing w/o worries about the

Enter the Satisfy directive.

See, Apache is smart enough to accept any possible combination of these two methods of authentication. It is possible to require both a valid password and a valid ip OR to require only one of the two.

Satisfy takes one of two arguments, ‘all’ or ‘any’. But saying ‘Satisfy all’ is kind of redundant, as that’s the default behavior.

The final auth file looks something like this:

[code]
AuthType basic
AuthUserFile /not/in/var/www/mars_passwd
AuthGroupFile /dev/null
AuthName "MARS Password Required"
Require valid-user

Order allow,deny
Allow from localhost
Allow from xx.yy.zz.com

Satisfy any
[/code]

So, now we get the desired behavior. If connecting from one of the authorized hosts, it lets you in w/o asking for a password. Otherwise, the password is required to continue.

shared key ssh authentication

SSH supports a number of different methods of authenticating connections. The two most common are password and shared key (and I’m not going to talk about the others, since they’re for rather specific applications). By default, and in almost every case where people use SSH, they’re probably entering a password. This is generally good for security, but bad for convenience, scripting, and a number of other things.

When setting up shared keys between two accounts, there is only really one big decision to be made – do you want to require a password or not? If you do so, that password is independant of either the source or destination accounts’ passwords. If you don’t set a password on the key, you effectively merge the two accounts into one – making transitions between them very transparent in deed.

I tend not to set passwords on my ssh keys. This means that I can scp files between machines without having to type the password every time, which in turn means that I can run backup scripts over an encrypted connection or use gvim to edit a remote file securely without having to tunnel an entire X session. There are lots of uses.

But I digress. You just want to set it up, eh?

Suppose I am setting up passwordless stuff between two servers, Bender and Fry. The basic procedure for creating my key pair looks like this:

Obviously, your username & hostname are probably going to be different, as is the generated fingerprint. This creates two files, ~/.ssh/id_rsa and ~/.ssh/id_rsa.pub. These are your private and public keys (respectively). And, because you didn’t type in a password when creating them, they’re not going to ask you for a password when you want to use them.

In addition to creating an RSA key, you could also create a DSA key, but RSA keys work with both SSH1 and SSH2 (not that you’re using SSH1, right?). For our application, there’s no real reason to choose one over the other.

Now that we have our keys, you need to send the public key to the other server. The SSH daemon looks for public keys of friendly accounts in ~/.ssh/authorized_keys, so the process is probably going to be something like this:

Now, if the universe is right, when I try to ssh over to Fry, I won’t be prompted for a password. To make things happy the other way around (to allow Fry to log in to Bender w/o a password), you just repeat the process the other way around. That is, create a key pair on Fry, copy the public key over to Bender.

If we were to add another server (Zoidberg) to the list, you’d repeat the process by creating a keypair over there and copying the public key to both Fry and Bender, and making sure Zoidberg’s authorized_keys file contains a copy of both Fry’s and Bender’s public keys. The more machines you add to the mix, the easier it is to forget to update one.

I find it helpful to make a copy of the public key in the form hostname.pub when generating a new key and copy it everywhere. Then, on the remote machines I execute a cat *.pub > authorized_keys to regenerate the index.

warning

And, just because I am such a good citizen, I figure I’ll close out with a warning. Be careful with this, if one machine in your little family of key-sharing happiness is compromised, the rest are. Also, it is healthy to keep track of which accounts can talk to which other accounts in order to track down/make changes in the future.

Case study:

At a previous job of mine, I had set up passwordless shared key ssh into the root account of one of the (non-mission critical) servers from my desktop, since that was the only place I was logging in from, and I was doing it a lot.

Well, 9 months after I quit, I typoed an ssh command – and wound up with root privs on the box. My brief examination of the machine showed that while the guy who replaced me was bright enough to change the root password itself when I left, he didn’t check for ssh keys. I discovered three other accounts that were similarly accessible by keys created by users who were no longer with the organization.

Yeah.