Google CTF 2023 — Under-Construction Writeup
Under-Construction was a web challenge in 2023’s Google CTF involving PHP, Python and HTTP parameter pollution.
When you start any challenge at the Google CTF 2023, the first things you will usually look at are the challenge description, attachments and in case of a web challenge the web pages.
Under-Construction challenge description.
Curiously, Under-Construction contains two web pages, one written in Python, the other on in PHP. That might come in handy!
Getting an overview
Now that we know what we can work with, let’s look at everything we got. Starting with the web pages.
The PHP page is quite simple. A login form asking for username and password.
The Python page gets more interesting. Here we have this home page, as well as pages for login and sign-up.
Python login page.
Python sign-up page.
The attached archive contains the source of the challenge. So did all challenges in this years Google CTF (which I prefer to having to tap in the dark).
Under-Construction source files.
So what does the application do
The premise for Under-Construction is that a company developed a Python Flask application in the past. The application is relatively simple. You can register accounts and log in with them. When registering, you can select one of the four tiers “BLUE”, “RED”, “GREEN” and “GOLD”. The tiers don’t actually do anything on the Python side. The only difference is that users can’t register “GOLD” accounts.
Some time after that, management decided to migrate from Python to PHP however. So now the company is in the process of building a separate PHP application and facing out the Python application. To get the flag in Under-Construction, you have to log in on the PHP site with a “GOLD” account. Once you do that, PHP will echo back the flag to you.
Searching for an exploit
Looking through the code, we find two sections of particular interest. Those being the Python and PHP registration logic. Registration is only possible in the Python application. Whenever a user registers there, however, a call is made to the PHP application to also register the user there.
When a user registers using the Python endpoint, after checks are made and registration is done, the request is forwarded to the PHP account_migrator.php endpoint. One thing of note here is that checks for whether a user registers as “GOLD” or not only happen in Python. The PHP endpoint does however check for the MIGRATOR_TOKEN before registering a new user. Otherwise we could directly address the endpoint and register a “GOLD” user that way.
The exploit
To register a “GOLD” user, we can exploit a difference in parameter parsing behavior between Python and PHP and the fact that the Python endpoint forwards the raw request to PHP instead of the values it reads from the request.
Say a request contained a POST parameter multiple times: curl -X POST https://example.com -d "a=foobar&b=foo&b=bar"
. Would we get “foo” or “bar” for the value of b
? The answer is that it depends on the programming language and framework. Python Flask takes the first occurrence, so b
would have the value “foo”. PHP however takes the last value, so b
would have the value “bar”. We can exploit that!
Crafting a registration request containing an allowed tier first and the “GOLD” tier second for the tier parameter will create a “GOLD” user for us.
We can now log into the PHP application using the credentials we specified (username “kukhofhacker” and “pwnd” as password). Once we do that, we got our flag!
Entering the credentials of our newly minted GOLD user.
There we go! Here we have our flag. I won’t show it here though :)
Summing up
For my first time participating in the Google CTF, I am content with my results. We almost got our hands on a second flag on the Biohazard challenge. I later found out that while we didn’t do the intended solution there, our approach was possible and we were just one URL encoding away from getting our hands on Biohazards flag. We will definitely participate in CTFs more often from now on!