First I used arp-scan to determine what IP address the target got:
Then I simply ran nmap (with the default settings) against the target:
Only ports 22 and 80 open. 22 was confirmed to be SSH and 80 was a web server. Here's the default web-page:
I ran nikto and dirb against the target, but they didn't really reveal anything interesting, so I then focused on the file upload for, right in the front page. The service checked the contents of the file and a simple file extension manipulation didn't do the trick. Luckily the front page already told us what is accepted: Mime-types application/x-executable and application/-sharedlib. I made a simple Hello World -application for upload:
When the file was uploaded, the service shows a simple analysis of the file (results of the commands "strings" and "objdump":
Both of the commands are command line utilities, which take the file name as the parameter. Perhaps the file name can be used for os command injection. And sure enough, here's what I sent:
And here's an excerpt of the response:
When I then tried to execute something more complex, the command injection failed. After some probing and prodding, I came to the conclusion that slashes (/) and periods (.) break the command injection. So what could be done without either?
To have unlimited command execution on the target box, I used the following information:
- you can provide IP-address for applications (such as curl and wget) in the decimal notation, so you don't need periods and
- pythons SimpleHTTPServer module serves the contents of index.html by default
I first calculated the decimal notation of my IP:
Then I modified my payload as follows:
My index.html only contained a simple "cat /etc/passwd" and here are the results:
Great, now I was able to execute a remote shell. I chose the python reverse shell:
And I had a much more comfortable shell. I then proceeded to fire up a pseudo tty with python (python -c "import pty;pty.spawn('/bin/bash')") and started examining the server.
I eventually found a file called admin_login_request.js
The file comments say that the file is used to impersonate admin, but I still thought that if that password isn't supposed to be used, it will not allow me to access anything. But:
And the user even had sudo rights:
But because of the comment, I thought that there probably is yet another way to admin. And sure enough, there was a root suid binary, which caught my attention.
When I was testing out the file (I downloaded it to my own computer first), I determined that the application takes a single command line argument and writes that to the end of a hard coded log file. If the parameter is too long though, it will overflow to the file name and eventually overwrite it. By passing a value of exactly 456 bytes, you overwrite the filename with NULL (0x00), effectively making the file name an empty string:
So now I can write to any file I choose with root permissions, as long as what I was writing was over 456 characters and didn't contain any spaces or newlines (nor nulls). Since the text was always appended to the target file I thought that I could add a new line to the /etc/passwd file and went with the idea.
Here's the python script I used to exploit the vulnerability:
And here I run the actual exploit
Time to confirm the results:
Win!
Btw, the password has was created with the command "openssl passwd -1 -salt xyz yourpass".
After obtaining root privileges on the target I found a file flag.png from the /root folder:
So this is it. Thanks for Ivanza for creating the challenge and the good guys at vulnhub for hosting it.