Wednesday, October 31, 2012

Automating Web Services Communication and Attacks

Web services "describes a standardized way of integrating Web-based applications using the XML, SOAP, Web Services Description Language (WSDL) and UDDI open standards over an Internet protocol backbone." The description of a web service can be found in a file which describes how the service can be called, expected parameters, and what it returns.

In this post I will be showing how to use Burp, WebScarab, and soapUI to communicate with and test a web service. Topics include:

  • Create a valid SOAP request and receive a response
  • Automate a process to request and receive data
  • Fuzz and look for more common web vulnerabilities such as injection

As an example I will be using WebGoat which is a vulnerable application I set up locally.

Steps:

1. Find the WSDL file which will end in ?WSDL or ?wsdl. It will look like this:

example wsdl file

2. Create a SOAP request of your desired operation (get person's name, credit card, etc.) using WebScarab or soapUI. I will show how to use either one.

Using soapUI:
  • Create a new project, enter the soap request URL ending in ?wsdl
  • soapui example
  • If authentication is required, enter credentials
  • soapui example 2
  • Choose which operation you want to use in your soap request and save the entire request for later
  • soapui example 3
Using WebScarab:
  • Click on the WebServices tab and load the WSDL URL. Enter credentials if prompted
  • webscarab example 1
  • Choose which operation to request and execute it
  • webscarab example 2
  • Click the Summary tab and open up (double click) your POST request
  • webscarab example 3
  • In the request section, click the Text tab and save the entire request for later
  • webscarab example 4

3. Now that we have the request open up a web proxy which can automate attacks such as Burp or ZAP and intercept the ?wsdl request. Replace the GET with POST and paste EITHER request in the body area. If you get an error back you may need to modify the header. For example, if you get "no SOAPAction header!" add "SOAPAction: " in the header.

burp example
The final request looks like this:
POST /WebGoat/services/WSDLScanning?WSDL HTTP/1.1
Host: 192.168.80.134:8080
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:10.0.8) Gecko/20100101 Firefox/10.0.8
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
SOAPAction: 
DNT: 1
Proxy-Connection: keep-alive
Authorization: Basic Z3Vlc3Q6Z3Vlc3Q=
Content-Length: 591

<?xml version='1.0' encoding='UTF-8'?>
<wsns0:Envelope
  xmlns:wsns1='http://www.w3.org/2001/XMLSchema-instance'
  xmlns:xsd='http://www.w3.org/2001/XMLSchema'
  xmlns:wsns0='http://schemas.xmlsoap.org/soap/envelope/'
>

  <wsns0:Body
    wsns0:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'
  >
    <wsns2:getFirstName
          xmlns:wsns2='http://lessons.webgoat.owasp.org'
    >
      <id
        xsi:type='xsd:int'
              xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
      >?</id>
    </wsns2:getFirstName>
  </wsns0:Body>
</wsns0:Envelope>

4. Send this request to Burp Intruder

request in burp intruder

5. Find the item you are requesting and which parameter it takes. soapUI will put a question mark '?' where this is, while webscarab will have whatever value was originally entered to get the request. Mark this as the only payload position.

burp payload positions

6. Choose your payload set based on the type of data you are requesting. In this example I am requesting a first name based on an ID I send, so I am using intruder to send numbers 1-200 to see if any of those IDs are valid and return a first name.

burp payload set

7. Look at the Intruder results and find any outliers which usually indicate a good response or at least something which will give more information to work off of. In this example we see 3 valid responses, so the IDs 101, 102, and 103 correlate to a specific database entry.

burp intruder responses

Now that we have successfully communicated the same thing can be done for other operations to collect as much data as possible.

The next step is to do some fuzzing to look for injection or other attack vectors. This example shows sql injection being performed.

sql injection example

Friday, October 26, 2012

Checking read and write access to an FTP server

Having an FTP server which others can access is a dangerous thing. Allowing others to have write access is even worse. In most situations, whether anonymous FTP is enabled or not, only a small number of people should actually be able to write to the server. If you want to check if you have read and write access to a particular server I came up with a simple way in Ubuntu 12.04. This is a simple task but I go into detail because I want to definitively find out what kind of access I have, therefore I will be attempting to create a 'test' directory in every directory and based on the results will know my access

I created an FTP server locally using VSFTPD (http://en.wikipedia.org/wiki/Vsftpd). Most of the servers will not be local, so I will use FTPFS (http://en.wikipedia.org/wiki/FTPFS) to mount it locally to make things easier to work with. To do this I installed CurlFtpFS with the command 'sudo apt-get install curlftpfs.' This is the listing of the ftp server before we try writing to it:

ftp tree
Assuming that the FTP server is somewhere else, first we'll mount the server locally:
curlftpfs x.x.x.x ~/local-mount-folder

x.x.x.x is the address of the FTP server, and ~/local-mount-folder is a folder YOU create on your local file system, this is where you will access the FTP server. If you get an ERROR such as "bad mount point : permission denied" try running the command as root.

mount ftp local

At this point I can check permissions but what I really want to know is if I have write access in any directory. Additionally I have seen cases where an anonymous ftp server said I had write access everywhere but would deny any write attempts.

For loop to create directory 'created-test-dir' in every existing directory on the server:

cd ftpmount
for k in $(ls -R | grep / | cut -d ":" -f 1); do mkdir $k/created-test-dir; done;

This uses 'ls -R' which gives a recursive listing of all subdirectories and contents, and so on. You will probably see output similar to "mkdir: cannot create directory './ftpmount/created-test-dir': Operation not permitted." This is ok because we know it is attempting to write to the ftp server. With a large ftp server this may take a while but much better than manually checking permissions.

create directories

The final step is to check if/where your 'test' directory was created:

cd ftpmount
find . -name created-test-dir

output

This will find any directories we may have created and also give you a list of where you have write access!

This sort of thing can be very helpful during a penetration test.