Use the above command injection vulnerability to chmod and execute our uploaded file

We know we can do #1, but #2 is actually trickier than it sounds. For starters, there’s no chmod on the system, so we can’t change file attributes via the shell. To make matters worse, the use of forward slash characters in our command injection is severely limited. This is a common problem, as ‘/’ is not allowed in file names on Linux systems. You can’t, for example, run the following:

$ tfcp foo 192.168.2.13:';ls /etc'

This will cause the TFTP server to attempt to create a file name ‘/tmp/;ls /etc’, which of course will fail since ‘;ls ‘ is not a directory, and if the file write fails then the system call never gets invoked.

We can get around the chmod issue fairly easily by overwriting an existing file on the system that already has the executable attribute. Of course, we don’t just want to go around overwriting system files willy-nilly, so we’ll probably want to copy the system file to the /tmp directory first, and overwrite it there.

We effectively want to do something like the following, which will result in an executable file named ‘/tmp/a’ that contains content of our choosing (in this example, a simple shell script):

The problem is that there are a lot of forward slashes in those commands, which our method of command injection won’t allow. There is a solution however, and it’s found in the system’s environment variables.

It turns out that the TFTP server’s working directory is ‘/’, so it’s $PWD environment variable is, you guessed it, ‘/’. This is common, as most processes that daemonize themselves change their working directory to ‘/’; processes executed via system() by the TFTP server will inherit this environment variable.

On this particular system, the $HOME environment variable is also set to ‘/’ for the root user, and all processes run as root.

Substituting forward slashes with either of these environment variables allows the use forward slashes in our command injection exploit without violating the file naming rules in Linux:

$ tfcp foo 192.168.2.13:';ls "$HOME"etc'

This causes a file named ‘;ls “$HOME”etc’ to be created inside of /tmp, but when the system call is made, the $HOME environment variable is expanded to ‘/’, ultimately resulting in the command ‘ls /etc’ being executed as root.

To test this, we’ll try to upload and execute a simple shell script:

#!/bin/sh
echo "Dante is my hero."

We will attempt to upload this file, make it executable, then execute it using the following script on our attack machine:

The root shell is over a serial port on the circuit board, which requires physical access to the device. This allows you to remotely execute code over the network, without any authentication. The tfcp commands shown above are all run on the attacking system, not on the WMB54G.

And yes, you could provide a valid firmware image, but without an existing firmware update to use as an example, you would have to reverse engineer the fwupdate binary in order to determine the expected file format, then hope you didn’t screw it up because if you did you could brick the device. Not to mention that the device will reboot whenever to you upload a new firmware image, which is probably not what you want if you are attempting to surreptitiously exploit the device.

Yes, there is always more than one way to skin a cat, and any of them work just fine. 🙂 You could do the same thing with sed as well.

I like the use environment variables though, because there is usually at least one environment variable that is set to “/”, making it a bit more of a generic solution to this problem. While both tr and sed are present on this particular system, that is not guaranteed – the developers could have easily left these out of their busybox build. Heck, I’ve dealt with systems that didn’t even have an ls command. 😛

I only have two questions about this. I have been a Windows user for most of my computer life and I want top know how did you pull off the tfcp binary off the device and exactly what do you do when you replace a system binary with a shell script.

The reason I overwrote an existing binary with the shell script was so that the script would inherit the permissions of the binary (in Unix environments, you can’t execute a file unless it has the execute permission flag set). What happens is that the file itself is not overwritten, but rather the contents of the file are overwritten; this way, the file contents are changed but its executable permissions remain