Lab 209 — BuildForge — Path Traversal in Static File Serving
Lab 209 — BuildForge — Path Traversal in Static File Serving
Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Easy | OS: N/A | **Author: XESXOR Techniques: curl_path_as_is, path_traversal_prefix_bypass, string_concatenation_bypass
Summary
Walkthrough of the CUSTOM Web Lab 209 — BuildForge — Path Traversal in Static File Serving. Task: CI/CD dashboard with custom static file serving at /static/{filepath}. Solution: path traversal via ../data/.env bypasses prefix check due to string concatenation without normalization.
Description
BuildForge is a CI/CD management dashboard built by ForgeStack Labs. The application uses a custom static file serving layer for its frontend assets. The goal was to find and read a sensitive configuration file that should not be publicly accessible.
Target: https://b43a7a70-5af1-41a7-a308-aa616e8f4851.labs.hackadvisor.io/
Credentials: user@test.com / password123
Analysis
Reconnaissance
-
Static file endpoint discovered: Files served at
/static/{filepath}(e.g.,/static/css/app.css,/static/js/app.js) -
Directory structure from JS comments:
/staticmaps to/app/publicon the filesystem- Configuration files located at
/app/data
-
Technology stack: Node.js/Express behind nginx/1.25.5
-
robots.txt revealed
/data/directory exists -
Honeypot detection: Decoy flags embedded in HTML to fool automated scanners:
FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts}
Vulnerability Analysis
The static file serving middleware has a path traversal vulnerability due to improper path validation. The security check uses string concatenation without normalizing ../ sequences before the prefix check:
Vulnerable logic:
javascript read-only • copy allowed// Pseudocode of the vulnerable check const fullPath = '/app/public/' + userInput; if (fullPath.startsWith('/app/public/')) { // Serve the file serveFile(fullPath); }
The bypass:
- Input:
../data/.env - Check: Does
/app/public/../data/.envstart with/app/public/? → YES (passes) - Filesystem resolution:
/app/public/../data/.env→/app/data/.env(traversal succeeds)
The prefix check passes because the string comparison happens BEFORE the filesystem normalizes the path.
Solution
Use curl with --path-as-is flag to prevent client-side path normalization:
bash read-only • copy allowedcurl -s --path-as-is "https://b43a7a70-5af1-41a7-a308-aa616e8f4851.labs.hackadvisor.io/static/../data/.env"
Why --path-as-is is critical:
- Without this flag, curl normalizes
/static/../data/.envto/data/.envbefore sending - The server would then reject the request or return 404
- With
--path-as-is, the literal path/static/../data/.envis sent to the server
Response
The .env file contained sensitive configuration:
SECRET_TOKEN=FLAG{REDACTED}
DATABASE_URL=postgres://...
AWS_ACCESS_KEY_ID=...
API_SECRET=...
Key Takeaways / Lessons
- Mastering curl_path_as_is, path_traversal_prefix_bypass, string_concatenation_bypass was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-04-27 • CUSTOM • Lab 209 — BuildForge — Path Traversal in Static File Serving • Difficulty: Easy