Tag: security

 

sandbox(7)

Like a lot of people, most of my Unix knowledge comes from an early reading of Advanced Programming in the UNIX Environment. This is an excellent tome on the interfaces provided by the kernel to programs on a Unix system.

Unfortunately, it’s over 15 years old now, and things have moved on. Naturally, I haven’t quite kept up. So I’ve just been pleasantly surprised to see that OS X has grown a sandbox system (via). There is scant documentation available:

Also, if you poke around, you’ll find /usr/include/sandbox.h and /usr/share/sandbox. The latter is interesting — it contains lisp-like definitions of access control lists for various processes.

What’s interesting to me is sandbox-exec though. This can be used with one of the builtin profiles to easily restrict access. For example:

$ sandbox-exec -n nowrite touch /tmp/foo
touch: /tmp/foo: Operation not permitted

After using strings(1) on apple’s libc (/usr/lib/libSystem.dylib), I managed to get these builtin profile names out:

nointernet
TCP/IP networking is prohibited
nonet
All sockets-based networking is prohibited.
pure-computation
All operating system services are prohibited.
nowrite
File system writes are prohibited.
write-tmp-only
File system writes are restricted to the temporary folder /var/tmp and the folder specified by the confstr(3) configuration variable _CS_DARWIN_USER_TEMP_DIR.

They’re only documented as internal constants for C programs, but it’s quite handy to have them available for sandbox-exec. It would be nice to know in more detail what they actually did, though.

Of course, this still isn’t really getting down to how the sandbox is implemented. Is it done inside the kernel or on the userland side? I don’t really know. And I don’t yet have enough dtrace-fu to figure it out.

See also:

Anyway, this seems like a fun toy. And of course, it’s reminded me that I need to try out chromium on the mac… Drat, no PPC support. 🙁

Cross Site Scripting, again

Twitter all clear after worm wave

Twitter has been given the all clear after a worm infected “tens of thousands of users”. But experts say the attack could have been much worse.

Another day, another XSS hole. It reminds me of something (probably apocryphal) that I heard about lung cancer research. There’s no real need for it. We know what causes lung cancer — smoking.

True or not, we know what causes XSS holes. It’s poor tools. Now given a choice between:

<p><c:out value="${userName}"/></p>

And

<p>${userName}</p>

Guess which one is going to be picked, every single time. And guess which one doesn’t escape HTML properly. Lest you think I’m picking on JSPs, most templating systems have the same flaw.

This is why I was immensely pleased to see Reducing XSS by way of Automatic Context-Aware Escaping in Template Systems from Google. Unfortunately, their solution isn’t universally available yet, but it really serves the purpose of showing how this can be done correctly.

Jasypt++

Once again, jasypt (“Java Simplified Encryption”) makes me smile.

Java comes with a comprehensive set of encryption utilities: JCE. I had to do some decryption the other day and ended up with this code.

public class Decryptor {
    private static final String ALGORITHM = "PBEWithMD5AndDES";
 
    private final Base64 base64 = new Base64();
    private final Cipher cipher;
 
    public Decryptor(String password) {
        try {
            cipher = Cipher.getInstance(ALGORITHM);
 
            // Just generate an empty salt as we don't want to use one.
            byte[] salt = new byte[cipher.getBlockSize()];
            Arrays.fill(salt, (byte) 0);
 
            // Set up the cipher.
            PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
            SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);
            SecretKey key = factory.generateSecret(pbeKeySpec);
            PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, 1000);
            cipher.init(Cipher.DECRYPT_MODE, key, parameterSpec);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        } catch (NoSuchPaddingException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        } catch (InvalidAlgorithmParameterException e) {
            throw new RuntimeException(e);
        }
    }
 
    public String decrypt(String cipherText) {
        try {
            // cipherText is base64, so will always be ASCII.
            byte[] cipherBytes = base64.decode(cipherText.getBytes("US-ASCII"));
            byte[] decryptedMessage = cipher.doFinal(cipherBytes);
            // Assume encrypted text is UTF-8.
            return new String(decryptedMessage, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        } catch (IllegalBlockSizeException e) {
            throw new RuntimeException(e);
        } catch (BadPaddingException e) {
            throw new RuntimeException(e);
        }
    }
}

This does also include conversion from base64 using Apache commons-codec, but it’s a lot of code. Even though I’ve tried to make things simpler (attempting to not use a salt [and I am aware of the consequences]), there’s still a lot of baggage.

Which is why I’m so grateful to have found jasypt. Essentially, all the above code is wrapped up for you in a nice little API. The above comes down to:

  SimplePBEConfig config = new SimplePBEConfig();
  config.setPassword(password);
  config.setSaltGenerator(new ZeroSaltGenerator());
  StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
  encryptor.decrypt(cipherText);

So why did I have to write the code in the first place? Well, we need to get a 3rd party to implement it, and I can’t enforce dependencies upon them. But the difference in the amount of code is shocking.

Postfix 2.5.1 TLS on FreeBSD

This is one of those things that I have to put up there in case anybody else has the same obscure setup that I do…

I run postfix on FreeBSD, using the ports system. This means I have a tendency to just use portupgrade to upgrade to the latest version of anything I happen to have installed. Normally, this works just fine. I usually check the output to see if any warnings about upgrading pop out and that’s about it. Slightly seat-of-the-pants, I know.

Anyway, I recently upgraded to postfix 2.5.1 and started seeing these messages in the logs.

Jul 26 21:29:44 gimli postfix/tlsmgr[7789]: fatal: tls_prng_exch_open: cannot open PRNG exchange file /var/lib/postfix/prng_exch: Permission denied

tlsmgr is the bit of postfix that handles SMTP over SSL.

The first port of call is to look through the postfix release notes. This seemed relevant.

[Incompat 20071206] The tlsmgr(8) and verify(8) servers no longer use root privileges when opening the address_verify_map, *_tls_session_cache_database, and tls_random_exchange_name cache files. This avoids a potential security loophole where the ownership of a file (or directory) does not match the trust level of the content of that file (or directory).

So, what’s the problem?

  % sudo -u postfix ls -l /var/lib/postfix
  Password:
  ls: /var/lib/postfix: Permission denied
  % sudo -u postfix ls -l /var/lib
  total 0
  ls: lib: Permission denied
  % sudo -u postfix ls -ld /var/lib
  drwxr-x---  5 root  wheel  512 26 Jul 08:14 /var/lib

So, it’s basically a permissions problem. Postfix can’t see the directory it’s trying to use. Previously it wasn’t a problem, as postfix was doing things as root, and root sidesteps permissions checks.

What to do? The simplest is to change the permissions. But I don’t particularly like doing that on systems directories, as they may well get reset in the future (e.g. nightly runs of mtree). So the simplest option is probably to reconfigure postfix to use a different directory. One that it actually has permission to access, like /var/db/postfix.

Annoyingly, when I look at the port to understand this problem (PR#121236), it was fixed in April. I wonder why I didn’t get the fix?

As it turns out a reinstall of postfix (portupgrade -f postfix-2.5.1_2,1) completely fixes the problem, and the directory it uses is now /var/db/postfix by default. I wonder what caused it to go wrong in the first place though?

Jasypt

One more little library that I’ve come to love: jasypt. It’s a simplified veneer over the top of the gargantuan java security apparatus. All I wanted to do was encrypt a String before putting it in a Cookie.

  BasicTextEncryptor encryptor = new BasicTextEncryptor();
  encryptor.setPassword(key);
  String cipherText = encryptor.encrypt(clearText);

It nicely base64 encodes the result, which is ideal for Cookie stuffing.

The reverse operation is just as simple.

  BasicTextEncryptor encryptor = new BasicTextEncryptor();
  encryptor.setPassword(key);
  String recoveredText = encryptor.decrypt(cipherText);

Cross Site Scripting

I’ve just been listening to Security Now about Cross-Site Scripting. It makes my blood boil. No, not all the ads and endless, aimless waffling. The talk about Cross-Site Scripting (aka XSS) being a problem because code and data can be intermingled in the page.

No, it’s not.

XSS is a problem because we have dumb programmers using even dumber tools1.

I’ve railed before about the fact that if you’re outputting HTML, then your tool should do HTML escaping for you by default.

It’s kind of understandable in systems like Template Toolkit, which are not specifically aimed at the web, but it’s completely inexcusable in PHP. It’s designed to create web pages. You’d think it’d be able to do it safely and easily. No chance.

But lest you think I rant at PHP, most other systems I’ve seen (in Java, Perl and Ruby) make it nearly as hard to do correctly. Let me rephrase:

If you have to think about where to apply escaping, then your tool is letting you down.

This isn’t to say XSS is the only problem. There are plenty of other problems to be aware of. CSRF appears to be garnering lots of attention these days.

One really useful link did come out of the Security Now show: OWASP (Open Web Application Security Project). It’s really worth checking out the OWASP Guide in order to educate yourself about security on the web.

1 Before you start to feel offended about being called a “dumb programmer”, I most certainly include myself in this category too.

mod_security now switched off

Last night, I spent a long while trying to get mod_security working on this web server. Installation was simple, thanks to the FreeBSD ports system. Configuration was another matter entirely.

Not having much experience of web application firewalls, I opted for the ModSecurity Core Rules to give me a head start. These are essentially some pre-provided Apache configs that you can include into your existing config files. It seems like a good idea, although some of the rules are questionable—I don’t really think that “googlebot visited” is a security event.

After configuring minor details like the audit log file, I deployed it. Hmmm, front page still comes up, so let’s commit the configs to subversion. Booom.

It turns out that the Core Rules don’t interact well with subversion in a number of minor, but irritating ways. For example, they expect every request to come with an Accept header. And only certain Content-Types can be submitted to the web server. It’s all minor stuff, and relatively easy to work out how to fix. This gave me a good feel for what’s involved in properly customizing mod_security.

This afternoon, I came back and inspected the logs. There are nearly 400 events from mod_security. Quite a lot of these were people trying to spam my trac instance (which I’ve now finally gotten under control) and blog. Importantly however, I noticed that it had blocked a legitimate user of an RSS feed.

At this point, I realised the problem. mod_security needs a lot of work to set up and maintain. You customize it towards a specific purpose—your application. But I’m running lots of applications. So it becomes harder and harder to customize correctly (particularly as I’m not running everything on it’s own virtualhost), because a rule that’s correct for subversion might well not be correct for trac. Or more to the point, it’s going to take me a very long time to get it configured correctly. So I’ve switched off mod_security for now.

Don’t take this as a slur on mod_security. It’s a useful tool, and I will be using it again. But it’s far easier to configure when you’re covering a single application running inside that Apache. And you’ll still need to invest a good chunk of time to get it set up correctly (a very iterative process).

System Keychain

This morning I was trying to add a new machine to my wireless network. Unfortunately, I’d forgotten the password… To the Keychain Access batcave!

Unfortunately, the “Airport network password” is stored in the system keychain, instead of my login keychain. Whilst I can unlock the system keychain, when I ask it to show me the password for my wireless network, it prompts for a password. Not my password, as it happens. Oh no. System keychain is protected by a 48 random bytes stored in /var/db/SystemKey. It’s created by the systemkeychain utility the first time your mac is booted. More to the point, there’s absolutely no way I can type those bytes.

So, let’s be cunning I thought. I dropped down to the command line and ran:

  % sudo cat /var/db/SystekMey | pbcopy

Then went back to keychain access only to discover that you can’t paste passwords in OS X.

A bit more googling turned up the security command. In particular, the dump-keychain command. Finally, running this spat out the password I was after:

  % security dump-keychain -d ~/Library/Keychains/login.keychain

At this point, I found out that it was the password for my old wireless network, which I’d just stopped using. A closer inspection of my login keychain revealed another “AirPort network password” which just happened to be for the new network. Ah well, at least it surrendered itself willingly.

From googling, it appears that many other people have been unable to recover stuff in their system keychain. So this is good stuff to know.

Rails Security Hole

Working round the Rails showstopper.

  • (pdcawley)++
  • (svk)++

I now have the fixed version of typo (soon to be 4.0.2), around an hour after it was committed.

As to the whole “full disclosure” thing by the rails team? They handled it pretty badly. As somebody else commented, it didn’t work for OpenBSD a while back and if anybody could do that, OpenBSD could.

Rails gets sane

Some time ago, I wrote about The Wrong Defaults, explaining how nearly all templating systems for the web default to “insecure”.

Well, it looks like some rails people are paying attention: Auto sanitized templates with Erubis