Command Injection In Java on Windows: 100% Proven that it is 100% Possible (in Certain Cases)

So Alex Smolen’s blog post about command injection in Java and .NET has had me writing some little test cases over the past couple of days (Java command injection, .NET command injection).  When I ran some tests in Java on OS X it looked like simple approaches to command injection weren’t effective.  Fantastic!

But wait a minute.  WebGoat has a command injection lesson.  And it is written in Java.  What gives?

So I went and dug through the WebGoat 5.2 code and found that they’re playing a little bit of dirty pool – they look through the attack payloads passed in and run some checks and do some other stuff.  Oh, and they make calls to cmd.exe which can chain further calls.  So you actually can inject commands in Java on Windows if you’re calling the right original executable.  Not good!

So I updated the previous test code to check for the operating system and run different commands on UNIX versus Windows.  And after some tweaking of the intended.bat and exploit.bat batch files I got new results that did allow me to run multiple commands via a single call to System.getRuntime().exec().  Yikes!  Batch files and commands using cmd.exe can be command injected.

I’ve uploaded updated test code here:

http://www.dancornell.com/files/JavaCommandInjection_v1_1.zip

So:

  • Command injection in Java on OS X: seemingly hard and merits further testing, but be careful if you are making calls to shells like /bin/sh
  • Command injection in Java on Windows: not hard if you are running a command that can load other commands – like cmd.exe or batch files (which run via cmd.exe)

The reason I got into Java in the first place was “write once, run anywhere”  That might never have worked as well as Sun had promised, but it was a great goal and Java does it much better than C/C++.  Seeing the results of this testing makes for a great lesson: “Do the right thing – even if you think you don’t have to.”  Also known as: “Defense in depth.”

As is often the case, “Doing the right thing” in this case means:

  • Positively validate inputs – type, length, composition, business rules
  • Properly encode outputs when they get sent to interpreters

Successful testing finds bugs, but cannot prove a lack of bugs.  In this case the test code demonstrates that you can cause command injection by including “&” and perhaps “&&” characters in your commands if the original executable supports chaining other calls.

The test system is running Windows XP SP2 and the Java environment is Java SE Runtime Environment (build 1.6.0_11-b03) Java HotSpot(TM) VM (build 11.0-b-16, mixed mode, sharing)

Next up: more testing.

–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

2 Responses to “Command Injection In Java on Windows: 100% Proven that it is 100% Possible (in Certain Cases)”

  1. Jeff Williams

    Dan, there are many other programs that allow injection besides cmd.exe. We see sendmail used pretty frequently like this. Anything with an interpreter is potentially injectable and may or may not have an escape syntax.

    Also, don’t forget injection into the executable path! Even without using cmd.exe there are a number of dangers here. Many applications allow the file to be executed to be specified by the attacker (crazy I know). Validation is difficult because Java passes a lot of strange characters through to Windows. For example, on Windows, adding trailing , space, period, slash, and backslash characters still allow the file to be accessed. Of these, the null byte is the worst, as it allows you to specify a completely different name, like ?file=malicious.exe%00innocent.txt. Then when the developer checks file.endsWith(“.txt”) it passes, but Windows returns the .exe file.

    ESAPI has a SafeFile class to protect against this and an Executor class that requires you to specify the allowed executables in a whitelist. You can also use the WindowsCodec (Unix codec is there too) to properly escape user input for use on the command like. You can prevent some forms of injection by escaping characters with the caret ^.

  2. sven

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

Leave a Reply

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