Stream
- Initial access
- Spring Boot actuator heap dump
- HTB solve rank
- Player #643 to solve Stream
- Data platform
- ClickHouse-backed AIDX ingestion pipeline
- Foothold
- XXE file disclosure and recovered SSH access
- Privilege escalation
- Database-controlled formatter executed by a root timer
01Heap dump discovery
The API virtual host exposed a minimal Spring Boot actuator surface, including an unrestricted heap dump. Parsing the HPROF revealed live Hikari connection material for the event-ingestion database.
curl -sS http://api.htb-airport.htb/actuator
curl -sS http://api.htb-airport.htb/actuator/heapdump -o api-heapdump.hprof
java -jar JDumpSpider.jar api-heapdump.hprof
This was a reminder that heap dumps are secrets-bearing artifacts: they can retain active connection objects, usernames, passwords, tokens and application configuration.
02ClickHouse and the AIDX pipeline
The recovered service account authenticated to ClickHouse. Schema inspection showed a raw Kafka-backed XML feed alongside a normalized JSON view:
partner_feed.flightleg_raw
partner_feed.flightleg_raw_kafka
partner_feed.flightleg_raw_mv
partner_feed.flightleg_json
partner_feed.flightleg_json_kafka
partner_feed.flightleg_json_mv
XML submitted to /feeds/aidx was persisted as raw data and also transformed into structured JSON.
The structured output became a useful observation point for testing parser behavior safely within the lab.
03XXE file disclosure
The XML parser resolved external entities. By placing an entity in a field retained by the downstream
normalizer, local-file content became visible in the JSON table. Reading /etc/passwd identified
the service and interactive user accounts, including martin_cole.
The key lesson was not only the XXE itself: an asynchronous pipeline can still be an exfiltration channel when attacker-controlled parsed fields are subsequently stored and queryable.
04User foothold
The identified interactive account used a weak password. After validating the credential against the authorised
lab SSH service, I obtained a stable shell as martin_cole.
05Kopia backup recovery
Martin owned a configured Kopia repository containing a snapshot of ClickHouse logs. The repository could be listed and restored through the existing local configuration:
kopia repository status
kopia snapshot list --all
kopia snapshot restore <snapshot-id> ~/restored-ch-logs
A historical ClickHouse error exposed administrative authentication material. The resulting account had broad database privileges, including file and Kafka capabilities.
06Root through a DLQ formatter trust boundary
Systemd exposed a root-owned AIDX dead-letter-queue timer. Its worker consumed messages from Kafka and invoked a Python formatter from ClickHouse's user-files directory. This created a dangerous boundary: a database administrator could alter a file that the root service later executed.
Within the lab, I validated that the formatter was writable through the database's authorised file interface, triggered the DLQ consumer, and waited for the timer. The root execution context then created a privileged local shell.
07Attack path
exposed Spring Boot heap dump
↓
live database credentials
↓
AIDX raw XML / parsed JSON pipeline
↓
XXE → local account discovery
↓
SSH foothold
↓
Kopia snapshot → historic privileged database access
↓
database-controlled formatter executed by root timer
↓
root
08Takeaways
- Restrict actuator endpoints and treat heap dumps as highly sensitive production data.
- Disable external entity resolution in XML parsers unless it is explicitly required.
- Apply least privilege to database service accounts and segregate writable data from executable code.
- Protect backups and logs as carefully as application secrets; historic records can expose valid credentials.
- Run scheduled tasks with the least privilege necessary and validate every file they execute.
◆If this were my environment
Memory dumps, parser behavior, logs and a privileged dead-letter formatter all became credential or execution paths. I would minimize sensitive data at every stage of the stream-processing pipeline.
- Restrict heap-dump creation and access, exclude secrets from process arguments and memory where possible, and rotate credentials after diagnostic collection.
- Disable XML external entities and network resolution, use hardened parsers, and validate input against a strict schema.
- Redact tokens and passwords from Kopia and application logs; send logs to an append-only store with access controls and retention limits.
- Run DLQ formatters as unprivileged workers with fixed templates and no shell, filesystem or secret-store access.
Hardening guides and benchmarks
These references offer different implementation paths: consensus benchmarks, prescriptive government checklists, vendor baselines and application-security verification requirements. I would select the profile that matches the system's role, document exceptions, test it in staging and continuously measure drift.