Published on: February 6, 2025
5 min read · Posted by Baba is Dead
Baba loves polluting the environment so much! Everyday, he throws straws into the Ocean, he burns orphanages simply to contribute to the environmental pollution, and even takes showers of mor
This challenge involves earning as much pollution points as possible to get the flag. Normally, this is impossible, as there is a 24 hour cooldown for polluting.
This challenge involves two parts: exploiting the token system and leveraging parameter pollution to bypass restrictions.
Each user is assigned a unique token, and the system is designed to prevent users from requesting another token within a 24-hour period. The relevant code is as follows:
def has_polluted(uuid):
# Pollution has a cooldown of a day!
if last_polluted.get(uuid) is None:
return False
if time.time() - last_polluted[uuid] > 86400:
return False
return True
...
if has_polluted(uuid):
return Response("You have already polluted today!", status=400)
response = requests.get(f"{PHP_SERVER}/get_token.php?uuid={uuid}")
...
def pollute():
...
last_polluted[uuid] = time.time()
The has_polluted
function checks if a user (identified by uuid
) has already polluted in the past 24 hours. However, this check can be bypassed by passing a modified uuid
like {your_uuid}&
into the has_polluted
function. This creates a different key in Python, but when sent as a request to the PHP server, it looks like:
{PHP_SERVER}/get_token.php?uuid={your_uuid}&
This still retrieves a token for the provided uuid
, bypassing the cooldown period.
The second part of the challenge involves parameter pollution to manipulate the pollute
function.
@app.route("/pollute", methods = ["POST"])
def pollute():
data = request.get_data()
uuid = request.form.get("uuid")
if has_polluted(uuid):
return jsonify({"success":False,"error":"You've already polluted today!"})
last_polluted[uuid] = time.time()
response = requests.post(f"{PHP_SERVER}/pollute.php", headers={"content-type": request.headers.get("content-type")},data = data)
return response.text
The pollute
function checks if the uuid
has already polluted by using request.form.get('uuid')
. In Flask, this retrieves the first instance of the uuid
key in the parameters. However, when the data is sent to the PHP server, PHP uses the last instance of the uuid
parameter.
This discrepancy allows us to craft a payload like:
uuid={vary_this}&uuid={your_uuid}&token={your_token}&amount=10000
This payload allows your account's uuid
to be updated while still passing the checks in the Python code.
uuid
to bypass the token cooldown.uuid
in the PHP server.I thought i made this challenge too difficult at first, but more people were able to solve it than anticipated. A few solution found other ways to bypass the token check.
Please login to comment
No comments yet