Monday, November 3, 2008

Daemon02 is a classic example of command injection vulnerability. It is a daemon listening on five ports from 2221 to 2225 which receives input from users, parse it into command, then execute that command on the host system. Available commands are:

* help: print help banner

* status : print system uptime

* procs : print list of running processes

The interesting one is procs. When receiving "procs " command, daemon02 will first perform various checks for dangerous metacharacters such as ";", "|", and "&". If any of them found, daemon02 will replace it with an empty space. Then the command line string is built as "proc ax | grep -v root | grep -v nobody | grep -v apache | grep -v args". Finally it calls popen(3) with the command line string described in the last sentence as the first argument. The result of popen(3) will be returned to the user.

Vulnerability

As you can see, part of the input string is used at the end of the command line string, so there's maybe a chance for command injection here, if somehow we can bypass the metacharacters checking. Indeed we can ;).

daemon02 checks for metacharacters using strchr(3) whose prototype is "char *strchr(const char *s, int c);". Basically it returns a pointer to the first occurrence of the character c in the string s. As you may already know, strchr(3) performs on NULL-terminated string which means it stops processing if it encounters a NULL byte in the input string s.

daemon02 got its input from the network by calling fgets(3) which means we can throw NULL bytes to it. What if we gives it something like "procs\x00;id"? ;). strchr(3) will fail to see ";" which eventually allows us to execute something like this in the host system: "proc ax | grep -v root | grep -v nobody | grep -v apache | grep -v ;id". How about changing "id" to something more relevant like reading a flag?