SecOS is a web based VM created by PaulSec. Here is the briefing:
Not too tired after BSides London? Still want to solve challenges? Here is the VM I told about during my talk where you’ll have to practice some of your skills to retrieve the precious flag located here: /root/flag.txt. This VM is an entry-level boot2root and is web based.
The beginning should be familiar by now…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
Let’s see what’s running on port 8081:
Looking at the about page, we can see the site is really secure!
Also, there is some sort of hint in the source code:
1
|
|
Checking that page, there is this message:
Well, there is something to see in the source code:
1 2 3 4 5 |
|
I created a user to check the functionality of the app. It seems you can send and receive messages between users. The spiderman user is the admin, so we’re mainly interested in that account. Using the hint, the likely course seems to be crafting a CSRF request to change the admin’s password and sending it to him in a message.
First, a HTML form that will take care of resetting the password:
1 2 3 4 5 6 7 8 9 10 11 |
|
Breaking it up, the form submits the username and password (which are hidden because we are using Javascript to send them to the server, and not clicking buttons ourselves) to the change password page. Because of the hint we found in the source code, we are using the localhost address instead of the machine’s IP. I copied it to /var/www/
and served it with apache.
And now to send a message to spiderman, with a URL for him to click:
Success! His password was reset and we can log in with the new password that we’ve just set. In the Messages section, we see that another user also had less than honorable intentions:
Next thing I did was try to SSH into the box as spiderman, with the password CrazyPassword!. And it worked! In spiderman’s home directory, there is a folder called vnwa..a vulnerable web application maybe? I found something potentially interesting buried in the internalServer.js code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
|
Indeed, this app is listening on port 9000:
1 2 3 4 5 6 7 |
|
By looking at the code, it seems it’s a pinging app. During the enumeration phase, I also noticed that unlike the web server we’ve exploited, this internal server is run by root:
1 2 3 4 5 6 |
|
To access this application, I set up a SSH tunnel. On my machine, I ran this command:
1
|
|
This allowed me to connect to the remote application on port 9000 from the browser of my Kali machine. Let me break it up:
-f Requests ssh to go to background just before command execution. This is useful if ssh is going to ask for passwords or passphrases, but the user wants it in the background.
-N Do not execute a remote command. This is useful for just forwarding ports.
-L [bind_address:]port:host:hostport
Specifies that the given port on the local (client) host is to be forwarded to the given host and port on the remote side. This works by allocating a socket to listen to port on the local side, optionally bound to the specified bind_address. Whenever a connection is made to this port, the connection is forwarded over the secure channel, and a connection is made to host port hostport from the remote machine.
-l Specifies the user to log in as on the remote machine.
192.168.80.128 The IP address of the SecOS box
What this did was forwarding the connections to port 4444 on my local machine to the remote server on port 9000. Remember that the application is only listening on the localhost interface on the SecOS box. So, the SecOS machine is acting as a sort of gateway, tunneling the connections I point to my 4444 port to the 9000 port on localhost. You can read some more about how this works on http://en.wikibooks.org/wiki/OpenSSH/Cookbook/Tunnels
Now, in my browser, I went to http://127.0.0.1:4444/ and:
I tried pinging my Kali machine to see if it works but it just appeared to hang. So I tried limiting the amount of pings by entering -c 2
after the IP to be pinged. And it worked!
We know the ping app is running as root, so if we can do remote code execution, we’ll be able to run commands as root. And the application is vulnerable to just what we need! Remember these lines from the internal server code:
1 2 |
|
The ip variable is passed to the exec function without any prior input sanitization. So, we just close the first command (which would be the ping), and insert an additional command of our choosing, which in this case will be to read the flag:
1
|
|
And profit!
Don’t tell any big lies today. Small ones can be just as effective.