CVE-2021-41258
Executive Summary
CVE-2021-41258 is a stored cross-site scripting (XSS) vulnerability affecting Kirby, an open-source file-structured CMS. The flaw resides in the default snippet for the image block within Kirby's blocks field, which fails to escape HTML special characters in the source, alt, and link fields. An authenticated Panel user with access to create or edit content can inject malicious HTML/JavaScript that executes in the browsers of site visitors and logged-in users browsing the site frontend. The vulnerability is patched in Kirby version 3.5.8, and exploitation requires valid credentials within the authenticated Panel user group, reducing the overall risk profile for unauthenticated external attackers.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Technical Analysis
Kirby's blocks field is a structured content component that stores block-level data for templating purposes. Each block contains typed fields — in the case of the image block, fields for source, alt, and link — which are rendered to HTML via block snippets during page rendering. This architecture means that the data stored in these fields is interpolated directly into the final HTML output served to site visitors.
The vulnerability arises because the default image block snippet did not invoke Kirby's built-in HTML escaping helper for these three fields. When user-supplied content containing HTML special characters (e.g., <, >, ", ', &) is stored without escaping and later rendered, those characters are interpreted as markup rather than plain text. An attacker who can control the contents of these fields — via the Panel interface — can craft a payload such as a <script> element or an event-handler attribute (e.g., onerror) that executes when the page is loaded in a victim's browser.
The root cause is therefore a missing output-encoding control at the template layer. The vulnerability class is CWE-79 (Cross-site Scripting), specifically the stored/persistent variant, where the malicious payload is persisted on the server and delivered to all subsequent visitors of the affected page. The attack surface is the public-facing website frontend, reachable by unauthenticated visitors; however, the attack vector requires prior authentication to a Panel account with content-creation privileges.
The patch, released in Kirby 3.5.8, applies the escaping helper to the output of the default image block snippet, ensuring that HTML special characters in the source, alt, and link fields are rendered as literal text rather than executable markup. Users who do not use the blocks field are unaffected, as the vulnerable code path is never reached.
Exploitation Scenarios
The following attack chain is inferred from the NVD description and the vulnerability class. No public exploit code or PoC is available at the time of writing.
Step 1 — Reconnaissance / Target Identification:
An attacker identifies a target running Kirby 3.5.7 or earlier that uses the blocks field with the default image block snippet. This can be done via fingerprinting techniques (e.g., identifying Kirby-specific paths, headers, or file structure) or by observing the CMS's distinctive template patterns. The attacker also assesses whether the target has a Panel interface exposed (typically at a /panel path) and whether any low-privilege accounts exist that could be compromised.
Step 2 — Gaining Authorized Access:
The attacker must obtain valid credentials for an authenticated Panel user account. This could be achieved through credential stuffing, phishing, brute force on weak passwords, or reuse of credentials leaked from other breaches. The attacker logs into the Panel successfully, now holding the necessary privileges to edit content.
Step 3 — Payload Injection:
The attacker navigates to an editable page or article and inserts or modifies an image block. In the source, alt, or link field, the attacker injects a malicious payload — for example, an HTML string containing a <script> tag or an event-handler attribute (e.g., <img src=x onerror=alert(document.cookie)>). Because the default snippet does not escape these fields, the payload is stored verbatim in the content database.
Step 4 — Execution / Delivery:
When any user — site visitor or logged-in Panel user — loads the affected page, the server renders the block snippet and outputs the unescaped payload directly into the HTML. The victim's browser parses the injected markup and executes the embedded JavaScript. This is a stored XSS, meaning the payload persists and fires on every subsequent page load for every visitor.
Step 5 — Post-Exploitation Impact:
Depending on the privilege level of the victim, the attacker can achieve a range of impacts: stealing session cookies (especially of other Panel users, including administrators), exfiltrating CSRF tokens to perform actions on behalf of the victim, defacing the public site, redirecting visitors to malicious domains, or performing keylogging. If an administrator is targeted, the attacker could potentially achieve full administrative control of the CMS, leading to remote code execution via file upload features or server-side template manipulation.
The CVSS score of 7.3 reflects a high confidentiality and integrity impact (C:H/I:H) with low attack complexity, but the requirement for authenticated access and user interaction (PR:L/UI:R) tempers the overall severity. No public PoC exists; the attack chain is inferred from the described vulnerability class.
Impact Assessment
Business Impact: The vulnerability enables authenticated content editors to perform stored XSS attacks against all site visitors and other authenticated users. This can lead to session hijacking, credential theft, site defacement, malware distribution to visitors, and reputational damage. In a CMS context, a successful XSS against an administrator could escalate to full server compromise through panel features.
Affected Systems: All Kirby CMS installations running version 3.5.7 or earlier that use the blocks field with the default image block snippet. Installations that do not use the blocks field, or that use custom snippets that already escape output, are not vulnerable.
Blast Radius: The primary blast radius is the public-facing website and its visitor base. Because the XSS is stored, the impact persists for the duration the malicious content remains in the page — potentially indefinitely if not detected. Secondary impact extends to the CMS backend: a stolen admin session could lead to full site compromise, impacting data integrity and availability.
CVSS Context: The score of 7.3 (High) with a confidentiality impact of High and integrity impact of High reflects that the vulnerability can lead to significant data exposure and content manipulation. The low attack complexity and network attack vector indicate ease of exploitation once the authentication barrier is overcome. Availability impact is rated None, meaning the vulnerability itself does not cause denial of service; however, post-exploitation actions could.
Detection Guidance
Sigma Rule
title: Kirby CMS Stored XSS via Image Block Fields
id: 9a4d2c17-6d8e-4b2f-9a3e-7f8d9e2c5b1a
status: experimental
description: Detects stored XSS payloads submitted via Kirby Panel in image block fields
author: Valtersit Threat Intelligence
date: 2024/01/15
logsource:
category: web_application
product: kirby
detection:
selection:
http.method: POST
http.url|contains:
- '/panel'
- 'pages'
http.body|contains:
- '<script'
- 'onerror='
- 'onload='
- 'javascript:'
- '<script'
condition: selection
level: high
falsepositives:
- Legitimate HTML content in pages that intentionally include scripts
- Admin users pasting code snippets into content fields
tags:
- attack.t1190
- attack.t1059.007
- cve.2021.41258
YARA Rule
rule Kirby_ImageBlock_StoredXSS {
meta:
description = "Detect stored XSS payloads targeting Kirby CMS image block fields (CVE-2021-41258)"
author = "Valtersit Threat Intelligence"
date = "2024-01-15"
reference = "CVE-2021-41258"
severity = "high"
strings:
$xss1 = /<script[^>]*>[\s\S]*?<\/script>/i
$xss2 = /onerror\s*=\s*["']?[^"'\s>]+/i
$xss3 = /onload\s*=\s*["']?[^"'\s>]+/i
$xss4 = /javascript\s*:\s*[\S]+/i
$img_block = /"type"\s*:\s*"image"/i
$src_field = /"src"\s*:|"source"\s*:/i
$alt_field = /"alt"\s*:/i
$link_field = /"link"\s*:/i
condition:
uint16(0) == 0x0A7B and // JSON object
$img_block and 3 of ($src_field, $alt_field, $link_field) and 1 of ($xss1, $xss2, $xss3, $xss4)
}
Suricata IDS Rule
alert http any any -> $HOME_NET any (msg:"KIRBY CMS - Stored XSS in Image Block (CVE-2021-41258)"; flow:established,to_server; http.method; content:"POST"; http.uri; content:"/panel"; http.request_body; content:"<script"; nocase; http.request_body; content:"image"; nocase; http.request_body; content:"source"; nocase; http.request_body; content:"alt"; nocase; http.request_body; content:"link"; nocase; pcre:"/(<script|onerror=|onload=|javascript:)/iU"; classtype:web-application-attack; sid:10041258; rev:1; metadata:created_at 2024_01_15, cve CVE-2021-41258, mitre_tactic_id TA0001, mitre_tactic_name Initial_Access;)
Elastic Detection
sequence by source.ip with maxspan=5m
[network where event.outcome == "success" and destination.port == 443]
[http where http.request.method == "POST" and url.path contains "/panel" and url.path contains "pages"]
[process where event.type == "start" and process.name == "php" and process.args contains "kirby"]
[file where event.type == "modification" and file.extension == "php" and file.name contains "snippet" and not process.executable like "*upgrade*"]
Splunk SPL Query
sourcetype=apache:access OR sourcetype=iis:access OR sourcetype=nginx:access
| where like(_raw, "%/panel%") AND like(_raw, "POST")
| regex _raw="(?i)(<script|onerror\s*=|onload\s*=|javascript\s*:)"
| rex field=_raw "POST (?<uri>[^\s]+) HTTP"
| rex field=_raw "(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})" as src_ip
| stats count min(_time) as first_seen max(_time) as last_seen by src_ip, uri
| where count >= 1
| convert ctime(first_seen) ctime(last_seen)
| table first_seen last_seen src_ip uri count
Wazuh OSSEC Rule
<group name="web_application,">
<rule id="100412" level="12">
<decoded_as>json</decoded_as>
<field name="url">\.*\/panel\/.*</field>
<field name="method">POST</field>
<match>(\<script|onerror\s*=|onload\s*=|javascript\s*:)</match>
<description>Kirby CMS stored XSS attempt in image block field (CVE-2021-41258)</description>
<group>web_application_attack,xss,cve-2021-41258,</group>
<mitre>
<id>T1190</id>
</mitre>
</rule>
</group>
Mitigation & Patch Guidance
Patch Confidence: 2/4 (CLAIMED — single source claims patch, not independently confirmed). The CNA claims the fix is in Kirby 3.5.8, but independent verification is recommended.
1) Immediate Mitigations:
- Upgrade immediately: Update to Kirby 3.5.8 or later. This is the only confirmed remediation.
- Restrict Panel access: Limit Panel access to a trusted network or require VPN/MFA to reduce the chance of credential compromise that enables exploitation.
- Review existing content: Audit all existing image blocks for suspicious HTML in the
source,alt, andlinkfields. Search the site's content database for<script>tags,onerror=/onload=attributes, andjavascript:URIs. - Temporarily disable blocks field: If upgrade is not immediately possible, consider disabling the blocks field or replacing the default image block snippet with a custom snippet that applies an escaping helper function.
2) Patch/Upgrade Steps:
- Download Kirby 3.5.8 from the official repository or via Composer.
- Test in a staging environment to ensure custom templates and plugin compatibility.
- Deploy the upgrade to production.
- After deployment, clear any cached page output to ensure the patched snippet is used.
3) Long-Term Hardening:
- Defense in depth: Implement a Web Application Firewall (WAF) rule to flag XSS patterns in POST bodies, especially those targeting
/panelendpoints. - Content Security Policy (CSP): Deploy a strict CSP header that disallows inline scripts (
script-src 'self'), preventing execution of injected JavaScript even if a similar XSS recurs. - Input validation: Enforce server-side validation of all content fields, rejecting HTML markup in fields where plain text is expected.
- Access control: Apply the principle of least privilege — only grant content-editing Panel access to users who require it.
- Monitoring: Enable audit logging for content changes in the Panel and alert on modifications to image block fields.
- Credential hygiene: Enforce strong passwords and multi-factor authentication for all Panel accounts.
References
- NVD Entry: https://nvd.nist.gov/vuln/detail/CVE-2021-41258
- Kirby Security Advisory: https://github.com/getkirby/kirby/security/advisories/GHSA-8f9g-9h4j-9v5m (vendor advisory for CVE-2021-41258)
- Kirby Release Notes (3.5.8): https://github.com/getkirby/kirby/releases/tag/3.5.8 (patch release)
- CWE-79 Reference: https://cwe.mitre.org/data/definitions/79.html (Cross-site Scripting)
- MITRE ATT&CK — T1190: https://attack.mitre.org/techniques/T1190/ (Exploit Public-Facing Application)
Threat Actor Activity: As of the report date, there is no known exploitation in the wild, no CISA KEV inclusion, and no public PoC or exploit code available. The EPSS score of 0.00781 (52.7th percentile) indicates a low-to-moderate probability of exploitation in the near term, primarily because the attack requires authenticated Panel access, which raises the barrier to entry for most external threat actors.
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.