SOP Write Up | BuckeyeCTF

Abdo Farwan
6 min readOct 25, 2021

--

As a CTF noob coming from solving the Web challenge “Canary” that was worth just 70 points, I thought SOP that gave 453 points would be a bit hard. But it turns out pretty simple to some extent.

Anyway before I start I would like to thank qxxxb and ath0 for their responsive replies through out the CTF.

The application

We should always start by taking a general look around before we start testing and just use the application as a “Normal” user. And so there are two given web pages.

1. The flag page

When visiting the flag page at http://18.225.2.140/ you are represented with the following… which turns out to be the source code of the current php file.

Lets go through the code and analyze it.

Request to http://18.225.2.140/

Seems simple, if we visit this page with the parameter ?message=flag it would display the flag …. well at least the fake flag for us.

Request to http://18.225.2.140/?message=flag

What if we set it to something else other than flag like ?message=banana for example.

Request to http://18.225.2.140/?message=banana

The first thing which obviously comes to mind when seeing our text being injected to a web page is XSS. We know that this challenge is about SOP and we are looking for a SOP bypass and when we google SOP bypass some of the first results are bypasses using XSS since if we have an XSS it is essentially a full and easy SOP bypass.

Ok cool, lets try XSS

Never mind definitely not XSS.

Any way lets move on to analyze the second given web page.

2. The BOT page

On visiting the Admin Bot page at http://18.225.2.140:8000/ you are represented with the following

Pretty straight forward, we give the bot a URL , the bot visits the URL and tells us what happened.

Lets try different URLs:

Our own web hook
https://webhook.site
  • So the bot can request external URLs.
Admin bot 127.0.0.1 request
  • It can’t request localhost or 127.0.0.1.

As a complete CTF newbie I stopped here and didn’t know what to do next, the frustration kinda kicked in and I felt lost for some reason.

Time to take a break.

So in this section I am here to give a quick lesson on hacking and life in general, when you feel frustration kicking in, leave what ever you are doing and take a break. Go to the gym, a store, walk around the house and just come back later.

Fast Forward 5 hours later, I realised that I haven’t really looked up ways to bypass SOP or even read about SOP itself.

Quick research time:

https://hackerone.com/reports/761726
https://resources.infosecinstitute.com/topic/bypassing-same-origin-policy-sop/
https://medium.com/swlh/hacking-the-same-origin-policy-f9f49ad592fc
https://dev.to/th3lazykid/day-3-bypassing-the-sop-4a8j
https://thesecurityvault.com/appsec/understanding-cors-and-sop-bypass-techniques/
https://portswigger.net/web-security/cors/same-origin-policy
https://www.hahwul.com/2020/01/12/json-hijacking-sop-bypass-technic-with-cache/
https://github.com/mpgn/ByP-SOP
https://medium.com/datamindedbe/cors-and-the-sop-explained-f59de3a5078
...

If you haven’t solved the challenge yet, try solving it now while its still online.

So …. things we understand for now

  1. Flag page only displays the flag for servers/clients? with the IP addresses of 172.16.0.10 and 172.16.0.11
  2. The bot has no restrictions and can visit any page.
  3. There is no XSS in the main application.

Lets do some more poking around

I have read a write up where the author simply made a request to an endpoint with sensitive information through JavaScript and simple got back the data.

His POC looks like this:

<script>const Http = new XMLHttpRequest();
const url = "http://18.225.2.140/?message=flag";
Http.open("GET", url);
Http.send();
Http.onreadystatechange = (e) => {
console.log(Http.responseText);
};
</script>

I tried it but knew for a fact this would not work for us because of ….. drum rolls ….. SOP.

Loading http://18.225.2.140/?message=flag using a XMLHttpRequest (Failed)

JSONP SOP Bypass

While researching I found a SOP bypass method using JSONP.

https://medium.com/@minosagap/same-origin-policy-and-ways-to-bypass-250effdc4a12 (More about JSONP)

JSONP = JSON with Padding

JSONP is a technique that works around SOP and enables the sharing of data.

And so the <script> element is allowed to execute JavaScript code that is retrieved from foreign origins which means that SOP doesn’t block <script> element from retrieving content from another origin.

I tried adding the flag page to my html using a script element and it worked!

<script src="http://18.225.2.140/?message=flag"></script>
Loading http://18.225.2.140/?message=flag using a script element (Worked)
Loading http://18.225.2.140/?message=flag using a script element(Worked)

The script loaded and I now kinda have access to the flag. I say kinda because I didn’t know how to leak it to my web hook.

Str_replace in flag page

Going through the flag page again I realised that I can enter text before and after the flag and php code would just replace the string “Flag”.

str_replace being used

So giving the ?message parameter “the flag” would result in “the buckeye{not_the_flag}” being printed out.

At this point I knew I solved the challenge, using the method above I could easily change the file imported by our script element to valid javascript.

Payload used : http://18.225.2.140/?message=var%20a%20=%22flag%22;
set the flag to a JavaScript variable “a”

I now made my exploit html page which had a script element with the source set to the flag page with our payload and an image element with source set to “http://webhookURL.com/secret/+ a” to leak the flag to my web hook.

exploit html page

Sent the exploit to the Admin Bot:

exploit worked on Admin BOT but the real flag not leaked

Somehow this works but doesn’t steal the real flag.

Going through the source code given to us I found this docker-compose file which states that the flag page runs on “172.16.0.10” port 80 and the admin bot page runs on “172.16.0.11” port 8000

I quickly check if http://172.16.0.10:80 and http://172.16.0.11:8000 are accessible by the admin bot and ….. they are.

Admin bot request to http://172.16.0.11:8000 (Success: 200 ok)
Admin bot request to http://172.16.0.10:80 (Success: 200 ok)

Same exploit but using http://172.16.0.10 as the host:

Final exploit

We send the exploit and we quickly get a hit in our web hook with the flag.

The flag finally
Flag => buckeye{th3_l3tt3r5_0f_S0P_Ar3_1n_JS0NP}

This would have been really easy if I didn’t over think stuff.

Thanks for reading.

--

--

Abdo Farwan
Abdo Farwan

Written by Abdo Farwan

I still don't know what I am

No responses yet