By Dan Cornell
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:
- 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 _at_ denimgroup.com