on CVE-2010-3435

When logging in, Ubuntu shows (admin?) users some useful information, such as

70 packages can be updated.
35 updates are security updates.

I recently ran into an issue where this information popped up twice on each login – one up-to-date entry and one outdated entry. Some investigation showed that somehow /etc/motd.tail had gained these lines too. The fix (rm -f /etc/motd.tail) was simple enough.

However, in the course of this investigation I noticed that /etc/update-motd.d is basically a bunch of shell scripts that get run as root on every ssh login by any user. Scary, no?

Remembering that being able to inject some environment variables was always a great way to break out of ‘restricted’ shells that were written in (ba)sh, I set out to look at methods of influencing the environment these scripts would be run in. .ssh/environment, .pam_environment and OpenSSH’s SendEnv all turned out to be smart enough to only do their work after update-motd was done, sadly. I was out of ideas.

The code of pam_env.so did tell me another interesting thing – ~/.pam_environment is opened and read as root, without any dropping of privileges. This suggested that symlinking it to some unreadable file (of the right format, i.e. consisting of VAR=value lines) would compromise the data in that file.

A proof of concept was simple enough (newline inserted because my blog layout is too narrow):

root@vps6001:~# cat /etc/env2
peter@vps6001:~$ ls -al .pam_environment 
lrwxrwxrwx 1 peter peter 9 May 12 22:13                   .pam_environment -> /etc/env2
peter@vps6001:~$ ls -al /etc/env2
---------- 1 root root 9 May 12 22:13 /etc/env2
peter@vps6001:~$ set | grep -i env

It works! This means that any file that has lines containing = (without whitespace around it) would be fair game. My first thought was /etc/mysql/debian.cnf, but that one has whitespace around the = characters.

Effective targets for this trick do exist. DirectAdmin (a commercial control panel) stores MySQL login information in a suitable file, and many daemons that support LDAP expect a password stored in a similar way. Also, base64-encoded files (like SSL and ssh keys) that happen to need padding such that they end in == expose their last line this way. I don’t know what the mathematical implications of having the last few bits of a private key are, but it can’t be good.

Some internet searching turned out that this issue was previously discovered by other people. Ubuntu 10.04 and Debian 6 are still vulnerable to this issue. Debian has a report on file but has not acted on it yet. Ubuntu doesn’t seem to know at all.

I emailed security@ for both distributions, Debian responded within minutes pointing me to the report they already had. I’m waiting for a response from Ubuntu.

Workaround: add user_readenv=0 to every pam_env.so listing in /etc/pam.d.

Please read my followup.