VI - You will pay for this !

Once we are logged in using Mårten Mickos credentials we can finally see some transactions to process for the month of may.

Sadly clicking on pay does not show us the final flag but a new 2FA screen that cannot be as easily bypassed as the first one...

Let's look at the request:

Something stands out here, there is an app_style parameter containing the URL of a CSS file: https://www.bountypay.h1ctf.com/css/uni_2fa_style.css

... and we only have 2 minutes to send the 2FA code.

In the response we can see that the max length of the 2FA is seven characters:

The idea here, while not really realist, is that the CSS file that is sent, is then included in the page that the 2FA app is using to generate the 2FA code. If this is true, this means that we will probably need to use a CSS injection attack to leak the 2FA code. We can confirm this by sending the request with an app_style that point to a server in our control. For this, I used Burp Collaboratorarrow-up-right:

The request was received from IP address 3.21.98.146, the same IP used by all the applications.

The User-Agent tells us that the browser used is HeadlessChromearrow-up-right which is common in CTF. At this point, I had some idea on how to proceed since I knew you could exfiltrate data using CSSarrow-up-right but there was something I was missing.

The general CSS injection data exfiltration method is to use CSS like:

Then, attacker.com would load an iframe with this css injection on it on target.com . attacker.com would then wait for a request to https://attacker.com/exfil/<data>. The iframe trick is useful since we can guess one character at a time.

In our case, we cannot do this since there is no way to iframe the app. The thing is, bruteforcing a 7 character 2FA code is not doable if the alphabet is a-zA-Z0-9 since this represent 1,028,071,702,528 combinations.

After some trials and errorsarrow-up-right I realized that there are actually 7 inputs in the page, one for each character ! This makes the challenge way easier since this requires 364 (52*7) combinations only !

I wrote a small Ruby script to generate all the combinations:

circle-info

We are using nth-child()arrow-up-right to matches the inputs element based on their position since the first character should be the first input.

The output looks like this:

To host the final payload I used GitHub Gistarrow-up-right and raw.githack.comarrow-up-right to set the proper Content-Type headers:

This is how it looks like in Burp after we submit our payload (here I'm using Taboratorarrow-up-right):

Based on the requests made to the collaborator we can easily extract the 2FA code.

For this request, the 2FA code is TVu7Y1W , once submitted we get the final FLAG !

I hope you enjoyed reading this writeup, if so you can follow me on Twitter at @TechbrunchFRarrow-up-right.

Last updated