Desires
HackTheBox
"As survivors face the vault, anticipation thickens the air, igniting desires for power and glory. Subtle glances reveal hidden ambitions. Unbeknownst to them, toxic gas twists thoughts, fueling greed and paranoia."
$ ls tags/ techniques/
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
Desires — HackTheBox
Description
"As survivors face the vault, anticipation thickens the air, igniting desires for power and glory. Subtle glances reveal hidden ambitions. Unbeknownst to them, toxic gas twists thoughts, fueling greed and paranoia."
Target: http://154.57.164.82:31868
Technology Stack
- Go (Fiber framework) — main web service on port 1337
- Node.js (Express) — internal SSO service on port 8080 (SQLite + bcrypt)
- Redis — session ID storage
- mholt/archiver/v3 v3.5.0 — archive extraction library
- File-based sessions stored at
/tmp/sessions/<username>/<sessionID>
Architecture
Two services managed by supervisord:
- Go service (public-facing): handles registration, login, file upload, admin page
- Node.js SSO (internal only): handles user authentication against SQLite DB
Session flow:
- On login,
sessionID = sha256(unix_timestamp)is generated PrepareSession(sessionID, username)storesusername → sessionIDmapping in RedisloginUser(username, password)authenticates against the SSO serviceCreateSession(sessionID, user)writes user JSON to/tmp/sessions/<username>/<sessionID>GetSession(username)reads Redis to get sessionID, then reads the file at/tmp/sessions/<username>/<sessionID>
The admin page at /user/admin checks if user.Role == "admin" and renders the flag.
Upload endpoint extracts archives to ./files/<username>/ using archiver.Unarchive(). The uploaded file is renamed to uuid + filepath.Ext(originalFilename).
Username validation blocks /, ., \ characters.
Analysis
Vulnerability 1: Session Puzzling (CWE-384)
In LoginHandler in http.go:
func LoginHandler(c *fiber.Ctx) error { sessionID := fmt.Sprintf("%x", sha256.Sum256([]byte(strconv.FormatInt(time.Now().Unix(), 10)))) err := PrepareSession(sessionID, credentials.Username) // Redis SET before auth! user, err := loginUser(credentials.Username, credentials.Password) // Auth happens AFTER sessId := CreateSession(sessionID, user) // File only created on success }
Critical flaw: PrepareSession() stores the session ID in Redis BEFORE authentication. A failed login leaves Redis pointing to a session ID with NO corresponding session file on disk. The session ID is also predictable: sha256(unix_timestamp).
Vulnerability 2: Symlink Attack via archiver/v3
...
$ grep --similar
Similar writeups
- [web][free]Dark Runes— HackTheBox
- [web][free]Proxy— hackthebox
- [web][Pro]Lab 66 — GrowthPilot — Stored XSS via User Registration— hackadvisor
- [web][free]SSOS— hackthebox
- [misc][free]Prison Pipeline— HackTheBox Business CTF 2024