A Smaller, Better JSP Web Shell

by | Jul 25, 2017

A better and smaller JSP web shell


In recent external pen tests, we have come across several Apache Struts instances that are vulnerable to a remote code execution (RCE) vulnerability. Our usual procedure for any RCE vulnerability that we are going to exploit is to upload a small web shell which allows us to run OS commands and receive the output. In the case of Apache Struts, that’d be a JSP web shell. From this web shell, we can download and execute any tools we want to run.

Super small JSP web shells have existed for a while, so it’s no issue to find one that can fit in a URL parameter for the Struts exploit. Where we ran into trouble was a Struts instance running on a Solaris server without outbound internet access.


The Scenario

  • No outbound internet access
  • No output to files from web shell (>, >>, |, etc. didn’t work)
  • Very limited Java libraries
  • Very limited upload size of web shell or other files

Without internet access, we couldn’t run commands to download reconnaissance or escalation tools (like port scanners, memory dumpers, or port forwarders). Without being able to echo to files we couldn’t easily upload scripts or tools chunk by chunk. With limited Java libraries and upload size for the web shell, we were unable to find a JSP file that supported file uploading.


Solution #1

The first solution we had some success with was to use native Java commands with the RCE vulnerability to output and append text to a file. We were not able to write many special characters (URL encoding wasn’t enough), so we resorted to base64 encoding our upload file, splitting it into chunks to append together, and then base64 decoding it on the server. This worked, but was slow and tedious, and if one of many requests didn’t succeed, then the entire uploaded file was junk.


Solution #2

The next and much better solution was to create a smaller, more powerful JSP web shell. Here were our requirements:

  • Command execution and output
  • File upload capability without size limits
  • Less than 1kb
  • No Java libraries outside of the core of 1.6

The first step was to move as much code as possible from the JSP file to a JavaScript file that could be loaded locally or hosted elsewhere. This meant nearly all of the html and JavaScript we were going to use.

Next we needed file upload capabilities. The normal multi-part POST request format for file uploads requires special Java libraries that we couldn’t count on. Using Java to parse a parameterized POST request invokes request size limits on many servers that were going to be prohibitive. This means we had to read and parse the POST data ourselves. We needed a simple encoding that would turn even binary data into something safe to send in a POST. We had to be able to encode the file using client side JavaScript and decode it server side with Java. Base64 it was!

Keeping the file small involved changing everything to 1 letter variables, writing functions for anything long that got called more than once, removing absolutely any whitespace we could, and finding the shortest syntax for every single task. The file was essentially unreadable at this point, so we kept 2 running copies for testing any changes: the shortened one, and one with proper whitespace and variable names.


The New cmd.jsp

In the end, we created a JSP web shell with file upload and command execution/output abilities that totaled only 976 bytes. Packaged as a .war file, it is only 662 bytes.

  • Command output is properly html encoded so there is none of the wonky formatting that we often get.
  • Files to be uploaded are base64 encoded client side and decoded server side so file format or contents is no issue.
  • Uploaded files are read in as a byte stream by the JSP page which circumvents most server defined maximum request sizes.
  • All JavaScript and html are loaded into window.localStorage client side via a bookmarklet, and window.localStorage is called in the JSP file via a single script tag.



The web shell and JavaScript can be found on our github page here: https://github.com/SecurityRiskAdvisors/cmd.jsp

Happy hacking!