OWASP WebGoat XSS lessons

I recently installed WebGoat, a deliberately vulnerable web app with built-in lessons. While some of the lessons are very easy, they quickly rise to a much higher difficulty. Even though the app does explain the basic concepts, the explanations are nowhere good enough to solve the exercises provided.

In this post I’ll focus on the Cross-Site Scripting (XSS) lessons, which I was recently able to solve.

After having installed WebGoat, you may want to access it from another client. You can do this by launching it with the –server.address=x.x.x.x parameter. Also, if you don’t want to reconfigure Burp or ZAP, –server.port=8081 allows you to run WebGoat on a different port from the default 8080 which these proxies normally use.

The first 2 XSS lessons are pretty straight-forward and I won’t talk about them (however, see here). However, on lesson 10 I started having difficulties: I didn’t really understand what they were asking for (“what is the route for the test code that stayed in the app during production”)? Turns out you have to dig through the javascript source code and look for some kind of test code. The first time you answer incorrectly you’ll get a hint on where to look. The difficulty for me was in finding out exactly the answer they wanted. Looking in GoatRouter.js (as the hint suggests), you’ll find the following key/value pairs:

routes: {
‘welcome’: ‘welcomeRoute’,
‘lesson/:name’: ‘lessonRoute’,
‘lesson/:name/:pageNum’: ‘lessonPageRoute’,
‘test/:param’: ‘testRoute’,
‘reportCard’: ‘reportCard’

Try playing around with these routes; as the lesson suggests, the base route for the lesson is start.mvc#lesson/. What is the route for reportCard? Try accessing start.mvc#reportCard.
Now for the test code: Of the 5 routes we have in the above code, it’s obviously the ‘test/:param’:’testRoute’ part we are interested in. How does this translate as a base route? If the lesson base route is start.mvc#lesson/, it should follow the same premise. Forget about the :param and testRoute part, we won’t need that until later.

Lesson 11 is where things start to get really interesting. Having identified the base route for the test code, we are now asked to run the code. Try accessing the test code in the browser (base route + parameters as seen in GoatRouter.js).

Now that’s interesting. It seems as if what we wrote in the URL gets reflected in the page. Try writing something else after test/, like the classic <script>alert(1)</script>:

Remember to URL-encode the / in </script>, or it won’t work (as %2F).

So we now know that the parameters after the base route get reflected in the page. Since the reflected part never gets sent to the server, this is DOM-based XSS. However, in this mission we are not interested in getting a pop-up, but in running the phoneHome test code and getting its output from the browser console (Firefox: right-click -> Inspect Element -> Console). So how do we run the code? If <script>alert()… allow us to get a pop-up box, which tags allow us to run javascript code (stop reading here if you want to figure out the rest yourself)?

One possible way is:

start.mvc#test/<script>webgoat.customjs.phoneHome();<%2Fscript>

Run this, and look in the console.log:

‘phone home said {“lessonCompleted”:true,”feedback”:”Congratulations. You have successfully completed the assignment.”,”output”:”phoneHome Response is -1798806219″}’

The ‘Response’ is obviously the answer to the mission.

Lesson 13 is a continuation of what we learned in lesson 11. This time you are the evil hacker trying to steal everyone else’s session on a message board. Or rather, you want to insert a stored bit of XSS that other potential users will inadvertently execute. I had a lot of trouble with this mission, and even though I believe I’ve solved it the way they want me to, it still shows as unsolved in the stats.
After a lot of trial and error I tried inserting the base javascript webgoat.customjs.phoneHome() into a message using the <embed src=””> tag. There are other ways to execute it, like <script src=”javascript:webgoat.customjs.phoneHome();”></script>. They all pretty much do the same thing, execute the javascript and generate a new mission Response code.

As I said, even though I input the code in the mission and the page says “Yes, that is the correct value”, it still shows as unsolved in the mission stats. The lesson link however is green, as in a solved mission. A bug?

 

This YouTube video by Lim Jet Wee might be helpful for lesson 10. 

Leave a Reply

Your email address will not be published.