webfreemedium

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/
session_puzzlingtar_symlink_escapepredictable_session_brute_forcesession_forgerysymlink_directory_traversal

$ 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:

  1. Go service (public-facing): handles registration, login, file upload, admin page
  2. Node.js SSO (internal only): handles user authentication against SQLite DB

Session flow:

  1. On login, sessionID = sha256(unix_timestamp) is generated
  2. PrepareSession(sessionID, username) stores username → sessionID mapping in Redis
  3. loginUser(username, password) authenticates against the SSO service
  4. CreateSession(sessionID, user) writes user JSON to /tmp/sessions/<username>/<sessionID>
  5. 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