Introduction
After tackling the “Raise the Dead” challenge, I was ready for the next spooky adventure. This time, I found myself diving into the mysterious Brew4u challenge. With the Haunted Brewery’s annual contest in full swing, this challenge hinted at secrets hidden within the brewery’s system. The goal? Submit a custom brew description while staying alert for any clues that might lead to the legendary BrewMaster’s secret recipe. Let’s see what mysteries lie behind this web exploit!
Challenge Description and Clues:
The Haunted Brewery Brew4u Contest is open to patrons who can design the best custom brew! Participants submit descriptions of their dream beer to the BrewMaster for a chance to have it featured in the taproom.
However, this year, something feels off. Rumors suggest the brewery's submission system is hiding a secret. Some say the legendary BrewMaster's secret-ingredient recipe is buried within the system, accessible only to those with a keen eye for detail.
Your mission: Submit a description for your custom brew, but be on the lookout—hidden within the system’s responses could be the clues you need to uncover the BrewMaster's secret recipe. The right approach might reveal more than just a drinkable masterpiece.
Connect to the challenge: https://hackersnhops-stop-changing-the-flag.chals.io/
Investigating
First, I started by investigating where the “secret ingredients” could be hiding. It turns out there’s a flag text file located within the app or brewery files, holding the information we need.
Next, I decided to test the example brew submission. After entering it, the page redirected me to:
https://hackersnhops-stop-changing-the-flag.chals.io/ssti
This endpoint responded by returning the description of the recipe I had just submitted.
Understanding SSTI (Server-Side Template Injection)
The URL endpoint I was redirected to, /ssti
, gave me a clear hint that the challenge involves a Server-Side Template Injection (SSTI). SSTI occurs when user input is improperly handled by a template engine on the server side. This allows attackers to inject malicious code into the template, which can then be executed by the server.
In this case, the page was returning the description I submitted, but there’s a possibility that we can manipulate the input field to execute code on the server and extract sensitive data, like the hidden flag. By exploiting SSTI, attackers could potentially access environment variables, files, or even execute arbitrary code if the template engine is vulnerable.
Knowing this, I decided to test different payloads to see if I could inject something that would reveal more than just the description.
Investigating the Response Header
Next, I focused on analyzing the response headers received after submitting my brew recipe. One detail that caught my attention was the Server header:
Server: Werkzeug/2.0.3 Python/3.9.19
This indicated that the application was running on Werkzeug, a WSGI utility library for Python, and specifically, version 2.0.3 with Python 3.9.19.
Werkzeug is often used in web frameworks like Flask, which could give me an insight into the underlying framework and help me identify potential weaknesses or misconfigurations. Knowing the server version could also help me in finding specific exploits related to this software.
Template Injection Attempt with {{ config }}
I decided to try injecting a simple payload into the template engine to see if I could access any useful server-side information. I used the {{ config }}
payload, which is commonly used in Flask (since it’s powered by Werkzeug) to access the application’s configuration settings.
To my surprise, the response returned a detailed dictionary of the app’s configuration, which included various settings like:
<Config {'ENV': 'production', 'DEBUG': False, 'TESTING': False, 'PROPAGATE_EXCEPTIONS': None, 'SECRET_KEY': None, 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(days=31), 'SESSION_COOKIE_NAME': 'session', ...}>
This exposed a range of useful information about the server environment, including the environment mode (production), session settings, and more. Notably, the SECRET_KEY field was None, which could be a potential weak spot for further exploitation.
At this point, I realized that the app might not be handling user input properly, making it vulnerable to further SSTI attacks.
More Exploit
Encouraged by the results of injecting {{ config }}
, I decided to push further by trying additional payloads to see what else I could uncover. I started by injecting {{ request }}
to check for any information about the current HTTP request. This returned useful details about the request object.
Next, I attempted {{ request.application }}
, which is another common payload used in Flask applications to access more specific server-side details. The result was:
<bound method Request.application of <class 'flask.wrappers.Request'>>
This output indicated that the request.application method was exposed. Although it wasn’t directly revealing any immediate sensitive data, it did show that the Flask request object had exposed server-side methods that could potentially be leveraged in further attacks.
At this point, it was clear that the app was highly vulnerable to Server-Side Template Injection (SSTI), and it was possible to continue exploring for ways to extract more critical information or trigger further vulnerabilities.
As I was looking for ways to access more sensitive information, I realized that I might be able to view the contents of the current working directory. To achieve this, I injected the following payload:
{{ request.application.__globals__.__builtins__.__import__('os').listdir('.') }}
This payload exploited the os module (which is part of Python’s standard library) by accessing it through the import function. The result was an array containing the names of files and directories in the current working directory.
This allowed me to see what files were present on the server, which could be useful for further exploration. This step confirmed that the server’s security was severely compromised, as I had full access to potentially sensitive directories and files on the system.
['flag.txt', 'app.py', 'requirements.txt', 'Dockerfile', 'static', 'templates']
Among these files, flag.txt immediately stood out as a potential candidate for containing the flag. This was a crucial find, as it directly pointed to a file that likely held the secret flag we were hunting for.
With this discovery, my next step was clear: investigate the flag.txt file to uncover the hidden flag and complete the challenge.
Finisher
Since I had already located flag.txt in the directory, I decided to take the next step and try to read its contents. Using another injection, I attempted to open and read the file directly from the server by injecting the following payload:
{{ request.application.__globals__.__builtins__.open('flag.txt').read() }}
This payload used Python’s built-in open() function to access the file and read() to get its content. The result returned the contents of flag.txt, revealing the hidden flag:
HnH{j1njA2_t3mpl4t3_1nj3cT}
With this, I had successfully retrieved the flag and completed the challenge.
Conclusion
In this challenge, I was able to exploit a Server-Side Template Injection (SSTI) vulnerability to access sensitive server-side information, ultimately leading to the discovery of the hidden flag. By systematically exploring the application’s configuration, performing directory listing, and reading the contents of the flag.txt file, I was able to complete the challenge successfully. This exercise reinforced the importance of carefully handling user input and the potential risks of exposing internal application components in web applications.
A big thank you to my colleague @sulthanullah_haqqihidaya for the valuable explanation about SSTI, which greatly helped in solving this challenge.
Top comments (0)