Cybersecurity
Command Injection in Java: 80% Proven That it is 100% Impossible (Sometimes)
This content is provided "as is" and is more than a year old. No representations are made that the content is up-to date or error-free. Please see the latest on this topic here.
I was reading Alex Smolen’s blog the other day and ran across the post “Command Injection Impossible in Java and .NET?” Interesting stuff! In an effort to avoid doing work I should actually be doing, I decided to look into it a bit more.
So I put together a tiny little program to try a bunch of different permutations to try and test this out. This is by no means an exhaustive fuzzing but I did run a number of command lines through Java that should have resulted in multiple commands being executed (cut and paste them from the Java System.out output). I zipped up the code and binaries and uploaded it here: http://www.dancornell.com/files/JavaCommandInjection_v1_1.zip
Update: The zip file is no longer accessible, but you can still see the implications of the JVM using safe "execve" calls here. It shows that the Java String sent to Runtime.getRuntime().exec(command) gets split on ' ', the first resulting String is the executable that gets run and the remaining Strings in the array are passed along as the arguments so even if they contain control characters or other commands those are just sent to the executable as the argv parameters.
If you go into the bin/ directory and run “java denimgroup.fuzzer.commandline.Main” it will try to run a bunch of commands. I have two scripts in the directory: intended and exploit. “intended” appends its command line arguments to intended_shell_results.txt and “exploit” appends its command line arguments to exploit_shell_results.txt. On Mac OS X 10.5.6 with Eclipse 3.4.0 using JDK 1.5.0 it runs the following commands through “Runtime.getRuntime().exec(command);”
./intended ; ./exploit
./intended : ./exploit
./intended | ./exploit
./intended && ./exploit
./intended & ./exploit
./intended ! ./exploit
./intended >> ./exploit
./intended << ./exploit
./intended > ./exploit
./intended < ./exploit
./intended :: ./exploit
./intended ;; ./exploit
./intended ;: ./exploit
./intended :; ./exploit
./intended || ./exploit
Assuming that “exploit” was executed, you would expect to see something in the “exploit_shell_results.txt” For example, if you manually run “./intended ; ./exploit” from the shell (as Java tried and failed to do via exec()) it will put some info in the file. But – wait – there’s nothing there when Java tries to run it! Perhaps Alex and the OWASP site are right (!).
Clearly this merits further study. My list of payloads is, by no means, exhaustive. But this is certainly interesting. To the degree that the standard Java libraries seem to prevent at least the most boneheaded attempts at command injection – bravo! There is a long way to go before declaring victory, but this is at least encouraging. I’d want to spend a lot of compute cycles trying to fiddle with combinations of Unicode characters on different OSes and different JDKs, but these days I am kind of busy. The code is available under an Apache 2.0 license so anyone can feel free to make this happen.
And hey – maybe I’ll fire up VS.NET 2008 and make a C# version. Otherwise I might accidentally do some real work.