- When dealing with web service security, accessing the WSDL is the first step;
- This give us the full list of operations and types allowed by the server as well as the correct syntax to use, inputs, outputs and all the useful information we may need to run successful attacks
- Before we can enumerate the WSDL file for the SOAP web service, we need to identify the SOAP web service and endpoints.
Identifying Web Service Definition Language.
Append the following in end of the URL that you've identified the SOAP service that we found.
- ?wsdl
- .wsdl
- ?disco
- /js
- SOAP/XML Web Services: Utilize the WSDL format for documentation, typically found at
?wsdlpaths. Tools like SOAPUI and WSDLer (Burp Suite Extension) are instrumental for parsing and generating requests. Example documentation is accessible at DNE Online.
Login Checks
- Try to login twice
- Try to login with the same cookie and check whether or not the old cookie is killed and other cookie is generated in the response.
Lockout service:
Understand and analyse the service with prompting with requests.
Bruteforce password and check whether or not the application has soft or hard mechanisim or even if it's locking users with increasingly time.
Check if the lockout mechanisim increases within failure attempts.
Element Duplication
Web Service double elements confusion.
Try to send dobule elements in XML structure with the same values for example :
<login>
<username> sami</username>
<password> s0ApU1R0ck5</password>
<password> s0ApU1R0sck5</password>
</login>You might get a response like this
<loginresponse>
<error>password is allowed only once and must be at least 6 characters and at most 20 characters.</error>
</loginresponse>Also try that in several permutations:
<login>
<username> sami</username>
<username> sami</username>
<password> s0ApU1R0ck5</password>
<password> s0ApU1R0ck5</password>
</login>Or:
<login>
<username> sami</username>
<username> sami</username>
<username> sami</username>
<password> s0ApU1R0ck5</password>
</login>Don't stop there! It is just a matter of cloning a TestStep and then changing it to be a new test. Try the unexpected. And Improvise!
Element Omission
element Omission is quite similar to Element Duplication, but the opposite. Instead of having extra elements, we enter less elements in the request:
remove elements in the XML entities passed towards the web service and check how the web service is acting upon the commissioned request.
For example :
<login>
<username> sami</username>
</login>To your surprise, you might be getting:
<loginresponse>
<errror>element password is expected.</error>
</loginresponse>You should do clone and change here as well, we'll try the orther way around:
<login>
<password>s0ApU1R0ck5</password>
</login>and without any elements at all:
<login>
</login>Malformed XML
This one is fun; try different variations of the elements in the request:
<login>
<user_name> sami</username>
<pass_word> s0ApU1R0ck5</password>
</login>or like this:
<login>
<user> sami</username>
<pass> s0ApU1R0ck5</password>
</login>You might be surprised by the answer:
<loginresponse>
<errror>element username is expected.</error>
</loginresponse>also, send requests where the end elements afre missing
<login>
<username>sami<username>
<pass> s0ApU1R0ck5</password>
</login>and the opposite; requests with missing start elements:
<login>
<user> sami</username>
s0ApU1R0ck5</password>
</login>Something to also malform is the namespaces. Let's look at how the pseudo code we've been using earlier actually would look:
<soapenv:Envelope xmlns:soapenv="<http://schemas.xmlsoap.org/soap/envelope/>" xmlns:demo="<http://demo.sami.com>">
<soapenv:Header/>
<soapenv:Body>
<demo :login>
<demo:username> sami</demo:username>
<demo:password> s0ApU1R0ck5</demo:password>
<demo :/login>
</soapenv:Body>
</soapenv:Envelope>Now, let's change omit one of the name spaces:
<soapenv:Envelope xmlns:soapenv="<http://schemas.xmlsoap.org/soap/envelope/>" xmlns:demo="<http://demo.sami.com>">
<soapenv:Header/>
<soapenv:Body>
<demo :login>
<username> sami</demo:username>
<demo:password> s0ApU1R0ck5</demo:password>
<demo :/login>
</soapenv:Body>
</soapenv:Envelope>as well as the reference to the namespace and have one quote to many
<soapenv:Envelope xmlns:soapenv="<http://schemas.xmlsoap.org/soap/envelope/>"">
<soapenv:Header/>
<soapenv:Body>
<demo :login>
<username> sami</demo:username>
<demo:password> s0ApU1R0ck5</demo:password>
<demo :/login>
</soapenv:Body>
</soapenv:Envelope>Boom goes the Payload!
The basis for this test is simple; "The weirdest things happens with the weirdest content". Basically, what we'll do is simple, we'll fill up the contents of an element with a huge payload. But first do this slightly, let's assume you know that the user name is allowed to be 25 characters. try what happens with 26;
<login>
<username>sami sami sami e</username>
<password>s0ApU1R0ck5</password>
</login>We should also try 24 and 25 just for interest sake, we'll do the usual, clone a test and then change the message.
That really should be handled correctly, but what happens when we enter a huge number of characters, a payload overload?
<login>
<username>
samimsamissamiisamiasami samimsamissamiasami samimsamissamii ssamiisamiasami
samissamiisamiasami samimsamissamiisami samimi samimsamissamiisamiasami samimsamiisamiasami samimsamissamii ssamiisami samimsamissamiisamiasami samimsamissamiasami samimi samimsamissamiisamiasami
samissamiisamiasami samimsamissamii ssamiasami samimsamissamiisamiasami samimsamiisamiasami samimi samimsamissamiisami samimsamissamiisamiasami samimsamissamiamisamiasami samimsamissamiisamiasami
samissamiisamiasami samimi samimsamissamiasami samimsamissamiisamiasami samimsamiisamiamisamiasami samimsamissamiisami samimsamissamiisamiasami samimi samimsamiisamiasami samimsamissamiisamiasami
samissamiisamiamisamiasami samimsamissamiasami samimsamissamiisamiasami samimi
samissamiisamiasami samimsamissamiisami samimsamissamiisamiamisamiasami samimsamiisamiasami samimsamissamiisamiasami
samisamsamissamiisamiasami samimsamissamiasami samimsamissamiisamiamisamiasami
samissamiisamiasami samimsamissamiisami samimsamisamsamissamiisamiasami samimsamiisamiasami samimsamissamiisamiamisami samimsamissamiisamiasami samimsamissamiasami samimsamisamsamissamiisamiasami
samissamiisamiasami samimsamissamiisami sasami samimsamissamiisamiasami samimsamiisamiasami samimsamisamsamissamiisami samimsamissamiisamiasami samimsamissamiasami sasami samimsamissamiisamiasami
samissamiisamiasami samimsamisamsamissamiasami samimsamissamiisamiasami samimsamiisamiasami sasami samimsamissamiisami samimsamissamiisamiasami samimsamisamsamiisamiasami samimsamissamiisamiasami
samissamiisamiasami sasami samimsamissamiasami samimsamissamiisamiasami samimsamii ssamiisamiasami samimsamissamiisami samiasamipsami>samiRsamiasssami/samiFor demonstration purposes I kept the payload small, make the content of usernameHUGEand see what happens:
2007-12-03 13:54:21,706 [Servlet.Engine.Transports : 0] FATAL WebService.CustomerService.
Login - Description: java.rmi.ServerException: RemoteException occurred in server thread;
nested exception is:
java.rmi.RemoteException: Error; nested exception is:
java.rmi.RemoteException: Problem with Query; nested exception is:
java.sql.SQLException: Could not insert new row into the table. Context:
DataBaseRemote.getCusstomerData, customer=456789 Identity: samitails: java.rmi.ServerException: RemoteException occurred in server thread; nested exception
is: To Long UserName, must be Maximum 24 BytesThe above is a slightly modified response in tests from a user in the community (with their permission of course). The actual response contained information about both the database and the application server as well as information about the ERP system built on top of it and the name of the Stored Procedure used. The test also had the nice effect that it ground the application server to a halt, making it vulnerable for attacks.
XPath injection
- Now for the final tip, we're we'll end up where we started; XPath Injection. soapUI users probably knows about XPath since this is what we use for XPath assertions, when we transfer content and more. The reason why we use Xpath is because this the standard (and a very powerful) way to access and and query XML documents, "SQL for XML".
- XPath injection then basically is like SQL injection in XML documents. Now, user data, for example, is seldom stored in XML Documents, so you might believe you are safe, but often the system you're testing is communicating with another system over Web Services. And what do we use to communicate, what do we send back and forth? XML documents…
Now, when we know why, let's look at how.
<login>
string(//user[username/text()='' or '1' = '1' and password/text()='' or '1' = '1'])
</login>We know that from the SQL Injection example, we're trying to let the system log us in. It might not work, but it is very interesting to see how the error has been handled.
We can also try to tease the XPath processor in the target system;
<login>
string(//user[user_name/text()='' or '1' = '1' and password/text()='' or '1' = '1'])
</login>What happens when the XPath processor gets a faulty node? Will we get an error message directly from Xalan, Saxon, Microsoft's XPathNavigator?
You should of course fuzz around with the XPath expressions some more and try to coax out as much information as possible about the target system.