As a pen-tester, there are going to be situations where you will be asked to provide evidence of the seriousness of a vulnerability that has been identified. There is ample documentation on how to do this for the more common vulnerabilities such as Cross Site Scripting (XSS) or SQL Injection. But what if you need to gauge the gravity of other, less common, vulnerabilities?
In this article, I will provide details on how a Server Side Request Forgery (SSRF) vulnerability can be used to gain knowledge of the server and the internal network where the web server is hosted, including information on the services hosted on the network. Such information is very useful for a hacker, and can be used to escalate the attack further.
I started off by running a scan against one of the Acunetix vulnerable test websites – http://testphp.vulnweb.com. Amongst the ton of vulnerabilities identified, I noticed a SSRF vulnerability on http://testphp.vulnweb.com/showimage.php. For this vulnerability, the scanner asked the test website to make a connection to another server which is monitored by the AcuMonitor Service.
This is all well and good. I can probably think of a few interesting ways that I can use this vulnerability to proxy my connection to 3rd party servers and web sites. However my goal is to gain more information about the web server. I need to be able to edit the HTTP request sent by the scanner. From within the vulnerability alert, I select “Launch the attack with HTTP Editor’, which takes me to the HTTP Editor with the HTTP request pre-loaded.
I will first try to identify if the website allows connections to the localhost by changing the URL to:
Clicking ‘Start’ submits the modified HTTP request. The HTTP response contains an HTML body of the same page; indicating that the web server is not restricted from making connections to itself. I can proceed with confirming this, using ports which are commonly open on a web server such as port 22 (SSH) and port 25 (SMTP):
The above requests produce an error, but also include a port banner which indicates that a server is running on the specified port, and gives away information on the server running on the web server. Here is the response I got for port 25 showing that a Postfix mail server is running on the same machine.
Warning: fopen(HTTP://127.0.0.1:25): failed to open stream: HTTP request failed! 220 rs202995.rs.hosteurope.de ESMTP Postfix (Ubuntu) in /hj/var/www/showimage.php on line 7
I always like to take note of the response that I receive when a port is not open. An example of such a request would be (nothing ever seems to be running on port 16):
The response that I get for the above is:
Warning: fopen(http://127.0.0.1:16): failed to open stream: Connection refused in /hj/var/www/showimage.php on line 7 Warning: fpassthru() expects parameter 1 to be resource, boolean given in /hj/var/www/showimage.php on line 13
Anything which does not include this response would indicate that a service is most likely running on this port.
Using the HTTP Editor to check a bunch of ports manually is lame and tedious. The HTTP Fuzzer can be easily used to automate this. Back in Acunetix WVS > Web Scanner, I right click on the SSRF vulnerability alert and select to “Export to HTTP Fuzzer”.
I start off by configuring a Number Generator which iterates through the numbers between 1 and 100. This will be used for the port number (as an example, let’s assume I only want to check for the first 100 ports). I then amended the GET request to make requests to the localhost and insert the Number Generator instead of the port. This can be done by clicking where you want the number generator to be inserted and selecting the Number Generator and clicking on Insert into Request.
Click Start and the Fuzzer will start iterating through the port numbers and making the requests. While this is being done, I proceeded to configure a Fuzzer Filter which only shows the results for ports which are deemed to be open, i.e. did not return the response identified for closed ports.
I started off by removing all the default rules. I then:
- Gave a description (name) to my new Filtering Rule,
- Selected that the Rule Type should be Exclude,
- Selected to apply the rule on the Response.
- Where the following Regular Expression is matched. The text is taken from the response received for a closed port.
failed to open stream: Connection refused in /hj/var/www/showimage.php on line 7
Click Ok, and only responses where an open port has been identified are shown. Note that in some cases, no response might also indicate that an open port has been identified. The below screenshot shows that ports 21 and 53 might be open on the test server.
This technique can easily be taken a step further to scan for additional ports on the local machine, or to scan for other machines on the LAN of the web server.
You might be asking yourself – how is this different than a port scan on the external interface of the web site. Often there are situations where the firewall restricts connections to a specific server running on the web server (or on the LAN of the web server), however connections from the same machine are not. SSRF vulnerabilities make it possible to identify such servers, and possibly probe them further using specially crafted requests.