A write-up for BugPoC XSS Challenge

4 years ago 171
BOOK THIS SPACE FOR AD
ARTICLE AD

Phuriphat Boontanon

Step-by-step of how I solve XSS Challenge from BugPoC

Image for post

Image for post

Hello there! I’m @nnez (https://hackerone.com/nnez)
This is my write-up for latest XSS challenge from @bugpoc_official

It was a fun challenge to solve, I have learnt new things and techniques from this challenge. Kudo! to @bugpoc_official

The challenge is located at http://calc.buggywebsite.com/ for those who wanna try breaking it.

What I always do in first visit of a new target is get to know it wholly. Considering from its UI and HTML source code, this is basically an AngularJS calculator application.

There are 2 html, 4 js files. index.html, frame.html, angular.min.js, jquery.min.js, script.js, frame.js

index.html is calculator UI script.js contains all functions of this calculator frame.html is a frame to show current equation frame.js contains functions to show current equation on frame.html

Now that we know what we are dealing with, let’s reread the rules of this challenge.

1. You must pop an alert(domain) showing calc.buggywebsite.com
2. You must bypass CSP
3. It must be reproducible using the latest version of Chrome
4. You must provide a working proof-of-concept on bugpoc.com

So, we need to somehow execute alert(domain) under restricted CSP rules. There are 2 tasks at hand:

We need to find a vector for XSSWe need to bypass CSP

Basic component of literally every XSS is user-controllable input that later transforms into output. So, if you want to find your vector for XSS, go look at where you can control the input.

For this calculator, the only input we can control is the equation and this is a made up puzzle, not real world scenario, we can assume that this must be our vector for XSS. Let’s start from that by looking into script.js. The interesting function is

because…

It is at the end of every other functions concatOperator, command, addDecimal, updateCurrNum, calculate.It sends our equation to another sink to be processed. and theiframe is a referrence to frame.html, so let's move on to frame.html and frame.js

This is a code from frame.js

To translate this into human language, this frame.html receives MessageEvent from postMessage function, checks if the origin is valid, then decides what to do with the message depending on its data. The interesting part is the last condition, which results in document.body.innerHTML=msg; This is a straightforward XSS vector because there is no sanitization of the input.

We’ve now completed the circle of XSS, user-controllable input that later transforms into output with no sanitization. So, if we can bypass the origin check (which is easy) then we can do XSS on this frame.html

Consider regex rule of this origin check

Can you see its flaw? it only checks whether the origin starts with http://calc.buggywebsite.com. This is weak protection because http://calc.buggywebsite.com.attacker.com also starts with http://calc.buggywebsite.com. And that's how to bypass it, a malicious attacker can send a malicious payload via postMessage from attacker.com

You can try this, go to http://calc.buggywebsite.com/frame.html then bring up your js console and use this payload window.postMessage('<img src=x onerror=alert() >', '*') The browser will try to execute our XSS payload but get stuck because of CSP violations.

Image for post

Image for post

CSP directives are declared in <meta> tag

This is a short one, which is easy to comprehend, but it can get messy. I always use CSP Evaulator from Google ( https://csp-evaluator.withgoogle.com/). It helps translate CSP directives to human language and sometimes tell you the bypass.

Image for post

Image for post

For this challenge, these directives mean, you can only execute javascript code from eval or <script> tag that references to js files hosted on this domain. So the core idea of how to bypass these directives is, we need to somehow include an existing js files with use of eval function and then somehow trigger it.

From information we’ve gathered at the start, there are 4 js files: angular.min.js, jquery.min.js, script.js, frame.js. Looking into those files (I only looked into script.js and frame.js), I found one use of eval function in script.js.

We could make use of this function to trigger XSS for us. This is a technique called code-reuse attack. Reference: https://www.blackhat.com/docs/us-17/thursday/us-17-Lekies-Dont-Trust-The-DOM-Bypassing-XSS-Mitigations-Via-Script-Gadgets.pdf

So the idea to exploit is

Include a script from angular.min.js and script.js to get our hands on $scope.calculate function.Execute calculate function using ng-init directives

From the idea, The payload should look something like this:

For those who are curious about the code in ng-init directive, c=this.updateCurrNum.toString();this.equation=c[53]+c[98]+c[26]+c[69]+c[4]+c[8]+c[148]+c[6]+c[3]+c[1]+c[11]+c[26]+c[2]+c[4]+c[27]+c[148]+c[6]+c[11]+c[53]+c[5]+c[2]+c[12];calculate() This is just a way to circumvent quotes filter, you can see that I did not use' or ".

To prove that it actually works, try below payload in js console window.postMessage('<iframe srcdoc="<script src=angular.min.js></script><script src=script.js></script><div ng-app=Calculator><div ng-controller=ArthmeticController ng-init=c=this.updateCurrNum.toString();this.equation=c[53]+c[98]+c[26]+c[69]+c[4]+c[8]+c[148]+c[6]+c[3]+c[1]+c[11]+c[26]+c[2]+c[4]+c[27]+c[148]+c[6]+c[11]+c[53]+c[5]+c[2]+c[12];calculate()>"></iframe>')

Image for post

Image for post

You can easily create PoC on https://bugpoc.com as well. They even allow you to specify the subdomain name, very handy.

Here is the one I created for this challenge:
https://bugpoc.com/poc#bp-Hpg5UpD5
Password: biGgeRKiWI56

And that’s a step by step of how I solve this challenge.

Start from basics, to get XSS you need user-controllable input, and vulnerable transform function.Form an idea of how to exploit your target before diving in.Read other hackers’ techniques!
Read Entire Article