Monday, December 10, 2012

Attacking Multipart Requests

I was recently in the process of testing a Wordpress Plugin for exploits when I came across a request that I don't see very often.

Here is a snippet:


======================================================
POST /wordpress/security-services/ HTTP/1.1
Host: 192.168.0.200
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:16.0) Gecko/20100101 Firefox/16.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Proxy-Connection: keep-alive
Referer: http://192.168.0.200/wordpress/security-services/
Content-Type: multipart/form-data; boundary=---------------------------680132334639
Content-Length: 1987

-----------------------------680132334639
Content-Disposition: form-data; name="user_email"

test@test.com
-----------------------------680132334639

-----------------------------680132334639
Content-Disposition: form-data; name="image_file"; filename=""
Content-Type: application/octet-stream


-----------------------------680132334639
 



As you can see from the highlighted portion, the Content-Type is "multipart/form-data" with a boundary declared.


RFC 2388 defines the boundary as:

As with other multipart types, a boundary is selected that does not occur in any of the data. Each field of the form is sent, in the order defined by the sending appliction and form, as a part of the multipart stream. Each part identifies the INPUT name within the original form. Each part should be labelled with an appropriate content-type if the media type is known (e.g., inferred from the file extension or operating system typing information) or as "application/octet-stream". 
[Taken from http://tools.ietf.org/html/rfc2388]


   In this case, the boundary is "-----------------------------680132334639" and you can see how it encapsulates every data element that it's transmitting.  Notice that each element has a "Content-Disposition" set to "form-data" and a name describing that element.

   In the second data element, and the primary reason for this particular Content-Type, is the ability to send files along with form data.  The particular plugin allowed for the submission of an image file as shown above.  Notice the "Content-Type" attribute set to "application/octet-stream" and there is a new field to specify the "filename."


More Information:

If the contents of a file are submitted with a form, the file input should be identified by the appropriate content type (e.g., "application/octet-stream"). If multiple files are to be returned as the result of a single form entry, they should be returned as "multipart/mixed" embedded within the "multipart/form-data".
[Taken from http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4]


   Manual attacks for text should be relatively straight forward as you would still be using the same techniques as a standard POST request.  One must identify where the actual data resides, in this case between the boundaries, and after the "name" field.  Your payload then becomes placed within the body between the two boundaries.


-----------------------------680132334639
Content-Disposition: form-data; name="user"

alert(xss)
-----------------------------680132334639


  This type of request also adds an additional attack vector.  With the file upload capabilities, you can also try to upload a malicious file to see if you can reference it somehow through the application and/or get it to execute.

   In this particular case, I also wanted to try an automated SQL injection attack.  I wanted to know if any of the tools I use support these request.  Luckily sqlmap had just added support for multipart requests.  I tested this out by doing a dump of the output and verified that it automatically detected the type of request I was passing to it (via a file exported from burp), detected the boundary, and then properly attacked the form data I was sending it.

   You could also write a script for customized attacks.  Make sure the script looks at the request, identifies the boundary after the "Content-Type" field looking at whatever "boundary=" is set to and then parse the request for the content between any place where it finds the 'opening' and 'closing' boundaries.