Software, technology, sysadmin war stories, and more. Feed
Wednesday, September 28, 2011

Insecure by design and ridiculously powerful too

Ever had root on everything? You will. And the coding that will bring it to you? Horrible, broken stuff like this...

I have the strangest luck when it comes to discovering badness in software. I've discovered the kind of design holes which would allow you to basically destroy an entire organization. It's absolutely amazing what kind of stuff can just lurk out there undetected for years. This is a story about one of my findings.

So there was this outfit with a bunch of Unix boxes. They needed to take care of them in an automated fashion, so they drafted some coders to hack something up. It was set up as a bunch of processes which used proprietary encodings to talk to each other. One of them was the "boss", and others were asked to do stuff, or asked the boss to do stuff on their behalf.

The auxiliary processes had to ask the "boss" process to do things because they lacked the SSH keys required to actually log in to the machines in their care. These SSH keys granted root access, so the programs could do anything they wanted on the target machines. Obviously, this is the sort of thing you'd want to secure.

Anyway, by the time I started working on it, they had "retired" SSH. All of the root-granting keys were dead, and they had switched to some other method to do privileged stuff on the target machines. I was given the task of chopping out all of the old SSH code since it obviously wasn't doing anything.

This task was large but simple. I'd just grep for references to SSH in bits of the code, then pick one to clean, and go to it. Once that was finished and committed, I'd pick another and start over. Things were going well.

Then, one day, I found a reference to SSH in the file which handled their proprietary inter-module communications. That looked interesting, so I decided to investigate in order to clean it up just like I had cleaned up so many other parts. What I found was rather disturbing.

These geniuses had created a remote procedure call which could be hooked by clients over the network to run commands on the target machines. This is how the auxiliary processes could do things as root on those systems. That's why I got a hit in my grep: this handler called the SSH code.

Trouble is, there was absolutely no checking of the incoming request to see who had asked for it, or if they were even allowed to do it! That's right, for however long this code had been there, if someone came along and said "hey, run 'rm -rf /' on the machine called bovine1", it would have done it for them!

Oh, but they had an excuse: the SSH keys are no longer valid! Okay, so, assuming that nobody exploited this hole up to that point, then you got away with it. Or did you?

I looked at the code again. The handler took a couple of arguments, like "host" and "command". You might say host is "bovine1" and command is "rm -rf /". Well, another bright spark had added something to that chunk of code at one point which just made my jaw drop.

Here it is, more or less (from memory):

if host == 'localhost':
  exec_command = '/bin/sh ' + command
  exec_command = '/usr/bin/ssh root@' + host + ' ' + command

Translated into English, that says "yeah, use SSH most of the time, but if someone asks for something to run on localhost, just go ahead and run it directly".

This, right here, is the hole you could fly a 747 through!

Think about this. Just by asking, you could make the "boss" process run ANY command you wanted as itself. Want to install a bind shell? No problem. Want to start an xterm and have it call out to you? Sure thing. Want to install your own trojan horse binary in place of the "boss"? Go for it.

Somehow, I apparently managed to put the genie back in the bottle before anyone else discovered it. Of course, if someone had exploited it, they would have had sufficient access to cover up their tracks by editing the log files, so we may never know for sure who managed to use it.