Thursday, October 30, 2014

Detecting and Exploiting the HTTP PUT Method

I recently found a web server which allowed the HTTP PUT Method. This was detected and proven vulnerable by a Nessus vulnerability scan which actually uploaded it's own page at /savpgr1.html with the text “A quick brown fox jumps over the lazy dog.” My first thought was to see if I could upload a shell (php, asp, jsp) which you can make in metasploit or find online. Unfortunately this didn't work as none of them were being interpreted by the server. Another possible attack scenario could have been a phishing attack where we created our own page within the web application.

During this test I didn't have much time and there wasn't a lot of information online about the HTTP PUT method from a penetration testing perspective. This blog post will be going over various ways to detect if a web server accepts the PUT method, how to successfully complete a PUT request, and how to set up a test web server which accepts PUT.

Detecting the HTTP PUT Method

  • OPTIONS method via Netcat, Burp, etc.:
    nc www.victim.com 80
    OPTIONS / HTTP/1.1
    Host: www.victim.com
    
  • Nmap: The http-methods.nse script checks each HTTP method and outputs the response. This can be really nice for quickly checking multiple servers/ports at a time. Example usage would be:
    nmap --script=http-methods.nse -p80,443 
  • Nessus: One of the ways Nessus reports on detected HTTP methods is through plugin 43111 "HTTP Methods Allowed (per directory)". The plugin file used is "web_directory_options.nasl" which can usually be found in /opt/nessus/lib/nessus/plugins.

Make a PUT Request / Upload Data

  • Request with Netcat, Burp, etc.:
    nc www.victim.com 80
    PUT /hello.htm HTTP/1.1
    User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
    Host: www.victim.com
    Accept-Language: en-us
    Connection: Keep-Alive
    Content-type: text/html
    Content-Length: 182
    
    <html>
    <body>
    <h1>Hello, World!</h1>
    </body>
    </html>
    
  • cURL:
    curl -i -X PUT -H "Content-Type: application/xml; charset=utf-8" -d @"/tmp/some-file.xml" http://www.victim.com/newpage
    
    curl -X PUT -d "text or data to put" http://www.victim.com/destination_page
    
    curl -i -H "Accept: application/json" -X PUT -d "text or data to put" http://victim.com/new_page
    
  • Quickput.py: I found this old python script which PUTs a local file onto a target web server. The script takes two arguments: a local file and the destination url. There are optional arguments for authentication. The content-length of the local file is automatically calculated and updated in the PUT request. I had pretty good success with using this script, which can be downloaded here.
  • Nmap: The http-put.nse script uploads a local file to a web server via PUT request. I have not personally used it but it might be a good option. Example usage would be: nmap -p 80 --script http-put --script-args http-put.url='/uploads/rootme.php',http-put.file='/tmp/rootme.php'.
  • Nessus: Nessus has an interesting plugin which actually makes the PUT request with its own data. This is done by plugin 10498 "Web Server HTTP Dangerous Method Detection." I have not tried this but am fairly certain it would work: edit the "http_methods.nasl" with your own data and run the Nessus scan with that plugin enabled. Just a quick update to the data and content length should be it.
  • Metasploit: Metasploit also gives you the ability to PUT a file with auxiliary/scanner/http/http_put. I haven't tried this but it seems straight forward.

Example PUT Python Web Server

To test some of the techniques discussed I originally tried to configure an Apache server but had issues getting it to successfully accept my PUT requests, so I found and modified a couple of python scripts to set up a quick web server for testing. Here it is working with the Quickput.py script I mentioned earlier:
The python PUT server script can be downloaded here but it may be sensitive to how the requests are formatted and not accept requests using the methods mentioned above.

Hopefully this is enough to get started with making PUT requests. It's a really interesting attack vector and should not be allowed by application developers and owners in most circumstances. If you you have any other ideas or suggestions based on this post please comment!

Resources:

https://www.owasp.org/index.php/Testing_for_HTTP_Methods_and_XST
http://www.tutorialspoint.com/http/http_methods.htm
https://gist.githubusercontent.com/codification/1393204/raw/3fd4a4...429f/server.py
http://www.acmesystems.it/python_httpserver