Good job to my team for obtaining 7th place! And also thanks to the challenge creators and organizers of course :)
🎵 Nicky Romero & MARF ft. Wulf - Okay🎵
Web
Space Station
Where do you want to go?
http://20.198.209.142:55047
The flag is in the flag format: STC{…}
Author: zeyu2001
If we visit the site, we just get a blank page with a one-line message.
|
|
Running a Burp Suite ‘Discover content’ scan, we find /app
and /flag.txt
.
/flag.txt
gives 403 Forbidden
, so let’s check out /app
.
At the bottom of the page we can enter URLs into an input bar powered by something called ‘PHP-Proxy’.
|
|
I went to the Github repository of this tool and found an open issue regarding a LFI vulnerability: https://github.com/Athlon1600/php-proxy-app/issues/161
Essentially, we just have to host our own page with the below contents and then submit it into the input bar.
|
|
To do this, we can spin up a publicly-accessible server real quick with php -S localhost:8000
and ngrok http 8000
. ngrok creates a tunnel to localhost and after that we can submit the ngrok-generated public URL into PHP-Proxy:
|
|
After a few 302 Found
redirects, we are greeted with the contents of /etc/passwd
.
Now, we can retrieve the flag.txt
we couldn’t access previously by modifying our payload:
|
|
Submitting our URL again and following the redirects gives us the contents of flag.txt
:
|
|
Flag: STC{l0cal_f1l3_1nclus10n_328d47c2ac5b2389ddc47e5500d30e04}
Specimens
Collected a bunch of specimens on our last run, wonder if there is more we misplaced.
http://20.198.209.142:55042
The flag is in the flag format: STC{…}
Author: LegPains
Checking the site out and looking at its source code reveals an obvious possible LFI / Path Traversal vulnerability in /?specimen=
.
|
|
Burp Suite’s ‘active scan’ feature marked this as a successful payload:
|
|
Confirmed retrieval of file contents:
After a bit of guesswork which I dislike, we find flag.txt
in /var/www/
:
|
|
Response:
|
|
Flag: STC{StRINg_r3PLace_I5_n0T_ReCUR5ive}
Star Cereal
Have you heard of Star Cereal? It’s a new brand of cereal that’s been rapidly gaining popularity amongst astronauts - so much so that their devs had to scramble to piece together a website for their business! The stress must have really gotten to them though, because a junior >dev accidentally leaked part of the source code…
http://20.198.209.142:55043
The flag is in the flag format: STC{…}
Author: zeyu2001
Hint: **Note: This is NOT required for solving but may have caused some of your payloads to fail. **
In line 11 of process_login.php:
$this->query = "SELECT email, password FROM admins WHERE email=? AND password=?";
Should be
$this->query = "SELECT email, password FROM starcereal.admins WHERE email=? AND password=?";
Additional hint: Think about what the code is checking. Your solution should work regardless of the contents of the database.
Attached: process_login.php
The login page of Star Cereal at /login.php
requires an email address, password, and MFA token.
Looking at the source code provided in the attached file process_login.php
,
|
|
we can understand that the:
- email address, password, and MFA token are sent as POST parameters
- email address and password used to create a
User
object User
object and MFA token used to make aLogin
object.- Final
Login
object is then serialized, base64-encoded, url-encoded, and then used as alogin
cookie.
To verify this login
cookie, it is decoded and unserialized back into a Login
object. verifyLogin()
method of the Login
object is then called as seen below:
|
|
Bypassing verifyLogin (MFA)
In verifyLogin()
, our input mfa_token
is checked with randomly-generated _correctValue
.
The source code on lines 16 and 17 tells us that:
_correctValue
is securely generated withrandom_int
, so we are not supposed to try to guess_correctValue
.mfa_token
and_correctValue
is compared strictly with===
, so we are not looking at a type juggling vulnerability either.
|
|
Instead, the vulnerability lies in the fact that untrusted user input (login
cookie) is unserialized back into objects (Login
, User
) without any prior validation or verification. This means that we can craft and modify our own serialized Login
and User
objects and attributes, encode it as a login
cookie, submit it to the website’s login, and it will just be happily deserialized.
To bypass the MFA check, we can change the mfa_token
attribute to be a reference to _correctValue
so that they will always be strictly equal to each other. In code, it will look like this:
|
|
But how would the corresponding objects and serialized objects look like?
First, this is the unmodified Login
object shown with print_r
in a local testing environment:
|
|
And this is the serialized unmodified Login
object with some newline formatting. Do also note that the \0
s are supposed to be actual null bytes.
|
|
Now, by modifying $this->mfa_token = $mfa_token;
to be $this->mfa_token = &$this->_correctValue;
and printing the serialized object, we observe that
|
|
will be changed to
|
|
mfa_token
no longer has a string value s
but a null value N
. _correctValue
is also being referenced as evident by the R
.
That’s great! But after bypassing this MFA check we still have a is_admin()
method being called on the User
object.
Bypassing is_admin (SQL)
In is_admin()
, an SQL query is executed, rows are retrieved and checked to have non-empty email
and password
column values. An SQL
object is also first created on line 12.
|
|
Looking into the SQL
object created, we see that prepared statements are used to bind query parameters so SQL injection is not possible. However, we can instead exploit the PHP deserialization vulnerability again to modify query
to whatever we like, as long as we ensure that our new query returns rows that have non-empty email
and password
fields.
|
|
Initially, I thought of using SELECT email, password FROM starcereal.admins WHERE email=? AND password=? OR 1=1
to return all existing rows in the database, but it did not work. I hypothesized that this could be because the existing database was empty and contained no rows to fetch.
As such, I modified the query
to be:
|
|
which will definitely return a row with email
value 'a'
and password
value 'a'
even if the existing database was empty. Note that admins
is changed to starcereal.admins
as suggested by the challenge’s hint.
Final payload
To easily edit encoded serialized data to modify the query
attribute to our new payload, we can use Hackvertor which is a Burp Suite extension.
- Paste the base64-encoded
login
cookie into Input. - Use
auto_decode_no_decrypt
on the Input and we can see the serialized objects in the Output. - Swap Output with Input
After swapping, you can now edit the serialized object string as Input and it will be automatically converted into the appropriate login
cookie format in the Output!
So now, this is how our final serialized payload looks like with additional newline formatting. Note that query";s:63
on line 4 also needs to be changed to query";s:96
to reflect the new length of the query string.
|
|
Encoding it via Hackvertor and submitting it as a login
cookie to /login.php
:
|
|
we get a flag in the HTML response:
|
|
Flag: STC{1ns3cur3_d3s3r14l1z4t10n_7b20b860e23a128688cffc07a5b7e898}
Star Cereal 2
Ha, that was sneaky! But I’ve patched the login so that people like you can’t gain access anymore. Stop hacking us!
http://20.198.209.142:55045
The flag is in the flag format: STC{…}
Author: zeyu2001
The website has interesting HTML comments that suggests there is a login vulnerability, but the login page is only accessible internally. 172.16.2.155 is also revealed to be one of the internal endpoints.
|
|
Checking the login page at /login.php
gives us a 403 Forbidden
and a message that says only admins are allowed to login.
|
|
This seems like a routing-based SSRF challenge via HTTP headers so I used Burp Intruder to place IP address payloads from the internal 172.16.2.0/24
subnet in various headers.
Filtering out 4xx
responses, we see that our 172.16.2.24
payload responded with a 200 OK
and a login page!
As seen from the source code, we need to send a POST request to /login.php
with email
and pass
parameters to login. I narrowed down the exploitable HTTP header to be X-Forwarded-For
so we just need to include X-Forwarded-For: 172.16.2.24
in our request.
|
|
I assumed that the login vulnerability mentioned in the HTML comments was an SQL injection and the affected query statement was something similar to that of Star Cereal except that it does not use prepared statements. Thus, I tried using ' UNION SELECT "a", "a"#
in the pass
field:
|
|
Flag in HTML response:
|
|
Flag: STC{w0w_you'r3_r3lly_a_l33t_h4x0r_bc1d4611be52117c9a8bb99bf572d6a7}
Thanks for reading :)