Command Injection In Java: 80% Proven that it is 100% Impossible (Sometimes)

IF YOU ARE USING JAVA ON WINDOWS PLEASE SEE THIS FOLLOW UP POST ON COMMAND INJECTION IN JAVA ON WINDOWS.  HECK, SEE THE FOLLOW UP POST REGARDLESS.

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

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.

–Dan
dan _at_ denimgroup.com

About Dan Cornell

A globally recognized application security expert, Dan Cornell holds over 15 years of experience architecting, developing and securing web-based software systems. As the Chief Technology Officer and a Principal at Denim Group, Ltd., he leads the technology team to help Fortune 500 companies and government organizations integrate security throughout the development process. He is also the original creator of ThreadFix, Denim Group's industry leading application vulnerability management platform.
More Posts by Dan Cornell

3 Responses to “Command Injection In Java: 80% Proven that it is 100% Impossible (Sometimes)”

  1. Jordan

    One quick way to verify Java isn’t vulnerable is to see which native functions it’s using. On Linux, use strace -f java […]/Main on your test app and look for exec or system. Yup, we see execve — safe calls.

  2. Jordan

    Whoops, I realized I should clarify/correct that. system() will still use the exec syscall, but it will pass the string to the shell to execute rather than execute directly.

  3. sven

    hi!
    the link to your demo code is dead. can you fix it please?
    thanx sven

Leave a Reply

Your email address will not be published. Required fields are marked *