Tryhackme En-Pass Report

https://tryhackme.com/room/enpass

En-pass is a medium difficulty room, created by @kiransau

Directory busting reveals four paths: a recursive path that contains a passphrase-protected private SSH key, an input form where the correct input will print a password, a 403 status page that can be bypassed to reveal a username, and a file directory with a hundred archives. 

Each path can be solved and each solution’s puzzle piece can be assembled together to achieve a low-privileged shell to the target. 

Privilege escalation is possible due to a scheduled task that executes a python script as the root user.  The script reads and executes the contents of a YAML file.  Injecting malicious commands into the YAML file allows arbitrary code execution.  

  • Port 22, SSH
    • No obvious usernames or passwords to try and brute force.
  • Port 8001, HTTP
    • The main page contains a slideshow with three pictures:
    • The first picture shows ciphertext; caesar cipher 3-shift reads “best of luck”.
    • The second picture reads: “Sad <newline> Z”, after base64 decryption.
    • The third picture has a quote about a mountain; I couldn’t find the source. 

 

Sad 
Z

  • /web/ is interesting, and can be recursively directory busted to find anything interesting
  • /reg.php contains a POST submit form with little obvious information
  • /403.php responds with a 403 status, may be able to bypass?
  • /zip/ contains over 100 zip files

By recursively directory busting, the full path is found:

/web/resources/infoseek/configure/key

Attempt to crack the private key with JTR

Hashcat cannot crack RSA private keys so John the Ripper is used.  Convert the private key into a format readable by john with ssh2john.py. 

Tried to crack the private key using both rockyou.txt and the best64 rules but no luck. 

 

Examining the source of the page shows php logic:

Notice the "Congo" username in the source code.

If the input is correct, $result is printed.  The logic is as follows:

  • The ‘title’ POST parameter is exploded; input is separated by ‘,’ and then placed into a list.
  • ‘sum’ is a counter variable and is incremented in a loop each time the conditions are met; the loop iterates 9 times.  So if the conditions are true, then ‘sum’ will have the value of ‘9’ after the loop.
  • If ‘sum’ is 9 at the end of the loop, the $result will be printed.

What does the input need to be in order for the conditions to be true?

  • The input needs to be comma (,) separated like a list.  The first index of the list will be [0].
  • The first condition is strlen($val[0]) == 2.  This means the length of the first item in the list needs to have a length of 2.
  • The next condition means the index [8] of the list needs to have a length of 3.
  • The index [5] value needs to be different than index [8]’s value.
  • The index [3] value needs to be different than index [7]’s value.
  • A proper input that meets all these conditions is:

This password is the passphrase for the private SSH key.  Verifying with JTR:

 

Attempt to bypass this 403 with 403fuzzer.py:

  • $./403fuzzer.py -u http://target:8001/403.php

The one with a different length (917) is the path that can bypass this 403 status.

Can add ‘imsau’ to the list of potential usernames. 

/zip/ is a file directory with 102 zip files.  Files a0.zip – a100.zip are identical, each with a file named ‘a’ containing the string “sadman”.

The only file noteworth here is a.zip, who’s size (940B) is far larger than the other files.  a.zip is an archive containing: a0.zip, a50.zip, and a100.zip.  They are all the same, containing a file named ‘a’ containing the string “sadman”.  

Add “sadman” to the list of potential usernames. 

With a private SSH key in hand, and it’s passphrase, all that’s needed is a username.

The list of potential usernames is:

  • kiransau
  • kiran
  • sau
  • congo
  • imsau

The correct username that successfully authenticates is imsau.

Identifying the Privilege Escalation Path

There is interesting folder in /opt/, called /scripts/ with a python script inside. file.py reads and executes the contents of /tmp/file.yml in the yaml.load() function. /tmp/file.yml doesn’t exist, so we can write it and hopefully insert malicious commands inside it.

 

The file.py script is owned by root, but imsau user can execute it in context of imsau. The script does not have SUID bit set so imsau user cannot run it as root.
So, if the ‘imsau’ user cannot manually run the script with elevated privileges, maybe there is a cron job or a scheduled task that runs the script as root.

  • Running linpeas.sh doesn’t show any jobs or scheduled tasks
  • Use pspy64; it monitors in real-time any processes that are created, with their command-line arguments.

  • Here it shows the file.py script being run with sudo and then /tmp/file.yml is deleted.
  • Goal is to determine what malicious commands we can write in /tmp/file.yml to have yaml.load() function execute those commands.

 

Malicious Payload

Initially found this link and followed the payload Alex Chan used: https://alexwlchan.net/2019/12/yaml-impossible/, but there was no ‘exec’ module on the system. 

Another payload method was found and tested: https://xerosecurity.com/wordpress/exploiting-python-deserialization-vulnerabilities/

  • can successfully create a file named “swag.txt”

Write a malicious payload; copy bash to /tmp and set the SUID bit as root.

Leave a Reply