Hilltop CTF 2020 - Memoir
On this page
Given a website where you can enter any URL, the web will visit them and display the response.

Fast examination in the Network tab from the Developer Console Window indicates that the URL will be sent to /snapshot endpoint along with another parameter called timeout, which has a default value of 0 (since I didn’t provide any value for the timeout parameter).


The challenge title: “Deer Nova Startup” indicates that this challenge might be related to a DNS or Domain Name System. DNS is used to resolves the names of internet sites (domain names) with their underlying IP addresses.
Furthermore, examining the HTML source code of the website shows that the timeout parameter is located inside a hidden input value in the #url-form form. And we can control this hidden parameter.

And from the challenge description, there’s an indication that the goal is to gain access to their private network (or local network, perhaps). But, trying to provide http://localhost/ or http://127.0.0.1/ as the URL is not allowed. The web might do some checking to make sure that the supplied URL didn’t point to the local network.

With that information, there are at least two ways to solve this challenge.
First Way
The first option is a faster way to solve this challenge. To understand how this first option works, we need to understand the syntax of an URL.
Every HTTP URL conforms to the syntax of a generic URI. The URI generic syntax consists of a hierarchical sequence of five components:
scheme:[//authority]path[?query][#fragment]
Where the authority component divides into three subcomponents:
[userinfo@]host[:port]
So if we tend to visit a URL like this:
http://example.com/
The HTTP specification supports a URL like this:
http://username:password@example.com/
By submitting that instead of the default URL, it might trick the checking mechanism of the website and gave up access to the local network.
So here’s the payload:
http://:admin@localhost/
And here’s the result:

After gaining access to the local network, the server gives information about /action/hello endpoint, which only prints “hello”.

But if we tried to access different words other than “hello”, it simply just mirrored the word. For example, visiting /action/harambayombabo (its a random word, which by common sense is not possible to exist as a static endpoint) result in the web printed “harambayombabo”.

We know that the server will print everything we supplied. So the endpoint structure might be looked like this:
http://:admin@localhost/action/<user-input>
We also know that the webserver is running gunicorn, a Python WSGI HTTP Server, by examining the response header of any request we send to the server.

That means SSTI (Server Side Template Injection) is a possibility since it’s a bit common in Python websites.
To test the theory, we can simply send this payload:
http://:admin@localhost/action/{{7*7}}
And see if the template expression (curly braces, {{ }}) is evaluated. If so, the website is likely to be vulnerable to SSTI. And it is.

One of the commonplace to examine is inside the config variable, but this time it is blacklisted, since sending this payload:
http://:admin@localhost/action/{{config}}
Made the server responded with:

So the idea is to get into config by using another method. Flask has an interesting function named url_for, which when we accessed its __globals__ attribute, it has an interesting variable called current_app.
By sending this payload:
http://:admin@localhost/action/{{url_for.__globals__.current_app}}
The server responded with:

Which means we’re back to the app object where the config attribute is. From there, simply access the config variable like this:
http://:admin@localhost/action/{{url_for.__globals__.current_app.config}}
And voila flag:

Second Way
The other, maybe-longer way to solve this is by using DNS Rebinding attack, where we trick the web by sending a domain that points to some non-localhost IPs, and then use timeout parameter to create a delay until the domain’s TTL expired and we changed it into local IPs (127.0.0.1). Once we managed to gain access to the local website, the SSTI exploit is the same. I’ll finish the writeup for this attack in a few days. Stay tuned!
The Flag
Flag is HilltopCTF{d0n’t_Scr3w_w1th_:Divergence-Novelty-System_lm40}