zoukankan      html  css  js  c++  java
  • 基于 burpsuite的web逻辑漏洞插件开发(来自JSRC安全小课堂,柏山师傅)

    基于 burpsuite的web逻辑漏洞插件开发

         BurpSuite 提供了插件开发接口,支持Java、Python、Ruby语言的扩展。虽然 BApp Store 上面已经提供了很多插件,其中也不乏优秀好用的插件。

    推荐几个个人感觉好的插件CO2,Logger++,Autorize,XSS Validator

          但是通用化的工具无法完全符合web安全测试人员的特定需求。
    本节我和大家探讨,如何根据实际需求自己开发出提高安全测试效率的插件。
          本次课程主要是从以下四个方面展开

     1.为什么要独立开发插件

          随着厂商安全意识增强,传输过程中,大多数线上业务通过https传输,传输流量加密。无法做中间人攻击了就服务端,数据库中的敏感数据加密存储,访问控制受限,即使拿到数据库也无法拿到明文数据。但是数据在客户端最终要展示给用户,必然明文展现。

        传统的安全防御设备和措施对逻辑漏洞收效甚微,现在攻击者更倾向于在客户端利用此类漏洞。而逻辑漏洞种类很多,通用化的工具无法完全符合web安全测试人员的特定需求。一个业务的逻辑漏洞抽象出来的模型,难以在其他业务层进行批量处理,通用的解决方案往往效果不佳。(但是一个业务层抽象出来的模型,在其自身站点往往具有通用性。)

        例如,某URL存在越权,可能该站点其他URL也可能存在类似的问题。我们基于该URL特征,开发burpsuite插件,批量扫描该站点,就能更全面的发现同类问题。

    2. 开发环境配置

    Burp支持Java、Python、Ruby语言的扩展,本次讲座以python环境为 例进行说明。Burpsuite 是运行在java环境,所有的库是java所写。Python作为开发语言,调用Java库就要用到Jython。

     Burpsuite Jython环境的配置

    Extender -> options -> python Environment -> select file,导入下载好的jython jar包。

     3.插件开发关键接口的使用实例

        API接口查阅可以从以下拿到:
    API接口文档可以在burpsuite 的Extender -> APIs 
    也可以通过https://portswigger.net/burp/extender/api/index.html进行查阅。

         IBurpExtender
    IBurpExtender是Burpsuite插件的入口,所有插件的开发都必须要实现。当插件被建立以后,registerExtenderCallbacks也需要实现。

    代码如下:class BurpExtender(IBurpExtender):
    def registerExtenderCallbacks(self, callbacks):

    参数callbacks可获取核心基础库,例如日志,请求,返回值修改等。IBurpExtenderCallbacks: 这个接口几乎是必备的。在插件编写的过程中会经常用到。

        IExtensionHelpers: 
    提供了编写扩展中常用的一些通用函数,比如编解码、构造请求、获取请求参数,获取请求头等。如:IRequestInfo analyzeRequest(byte[] request)
    通过analyzeRequest函数,可以拿到请求的细节。

    通过如下几个接口方法可以拿到

     IHttpRequestResponse: 这个接口包含了每个请求和响应的细节。在Brupsuite中的每个请求或者响应都是IHttpRequestResponse实例。通过getRequest(), getResponse()方法可以获取请求和响应的细节信息。

    以registerHttpListener为例进行代码说明:

        如图所示,在user 和 webserver之间建立监听,调用HttpListener接口。获取请求,响应的日志。

     实现这个功能,最重要的是这个方法:
    # register ourselves as an HTTP listener
    callbacks.registerHttpListener(self)

    def registerExtenderCallbacks(self, callbacks):

            self._callbacks = callbacks
            self._helpers = callbacks.getHelpers()
            ## 设置插件名
            self._callbacks.setExtensionName("getTheRequest")

    # //如果没有注册,下面的processHttpMessage方法是不会生效的。处理请求和响应包的插件,这个应该是必要的

            callbacks.registerHttpListener(self)

    ### processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo),
    ### 在messageInfo这个参数中,我们可以获取到request和response日志。

     def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
            if toolFlag == 4:
                if not messageIsRequest:
                    request = messageInfo.getRequest()
                    analyzedRequest = self._helpers.analyzeResponse(request)
                    request_header = analyzedRequest.getHeaders()

                    try:
                        method, path = res_path.findall(request_header[0])[0]
                        host = res_host.findall(request_header[1])[0]
                        url = method + " " + host + path
                    except:
                        url = ""

                    if method == "GET":
                        print “[+++++]The URL is ", url
                        print "[+++++]The host is ",host
                        print "[++++] The URI is following"
                        print path
                        for iterm in path.split("/"):
                            print iterm
                        print 

    代码如上所示,就可以打印出URL,HOST,URI日志信息

        如果做扫描类插件:
    class BurpExtender(IBurpExtender,IScannerCheck)
    callbacks.registerScannerCheck(this);


        实现IScannerCheck后需要重写被动扫描的函数。
    doPassiveScan(IHttpRequestResponse baseRequestResponse) {}

    doPassiveScan这个接口,在baseRequestResponse获取请求和响应数据,并利用这些数据进行基于扫描规则进行扫描。

       逻辑漏洞检测插件开发探讨

    这个插件实现的基本功能是:确定哪些cookie有效cookie,可以基于这些URL,生成字典,进行目录爆破

    首先,我们需要拿到requests 的 cookie

    request = messageInfo.getRequest()
                analyzedRequest = self._helpers.analyzeResponse(request)
                requestHeaders = analyzedRequest.getHeaders()

                newHeaders = dict()
                cookies = dict()

                for header in requestHeaders:
                    header = header.encode('utf-8')
                    if "HTTP/" not in header and "Host" not in header and "Cookie" not in header:

                        header_item = header.split(": ")
                        newHeaders[header_item[0]] = ": ".join(header_item[1:])

                    if header.lower().startswith("cookie"):

                        rawCookie =  header.strip("Cookie: ")

                        for item_cookie in rawCookie.split("; "):
                            key = item_cookie.split("=")[0]
                            value = "=".join(item_cookie.split("=")[1:])
                            cookies[key] = value
                    lengthList = {}
                    for key,value in cookies.items():
                        tempcookie = {}
                        tempcookie[key] = value
                        response = requests.get(url,headers=newHeaders,cookies=tempcookie,verify=False)
                        lengthList[key] = len(response.content)
                    if lengthList.keys():
                        print url
                        print lengthList
    根据响应长度的不同确定哪些cookie是有效cookie

     针对DES,AES加密参数的逻辑漏洞挖掘:

    AES,DES属于对称加密,所以客户端和服务器端都会有秘钥存在,也就是说密钥在客户端肯定能找到。网页,微信小程序中,往往在js代码中就能找到,找到密钥即可进行逻辑漏洞测试。

    在一次对微信小程序渗透测试中,抓包发现订单ID参数以密文形式进行传输。因此,我们需要获取加密方法。通过反编译微信小程序包,发现了密钥,加密方法是DES加密。
    这是在一次渗透测试过程中获取DES秘钥的截图;

    昨天分享了一下,今题讲一些插件的tips

     ## 代码编写获取订单ID密文。

     在burpsuite测试过程:
    由于是对订单ID加密,我们先遍历明文ID,再对明文Id进行加密,生成字典。再利用burp 的爆破插件,进行爆破即可。

    tips:遇到参数加密的情况并不可怕,既然是对称加密,秘钥一定能在客户端拿到。对js代码进行分析,往往就可以获取到秘钥。

    # 对消息体进行解析
    analyzeRequest= helpers.analyzeRequest(messageInfo); 
    # 获取请求头
    headers= analyzeRequest.getHeaders()
    # 获取参数列表
    paraList= analyzeRequest.getParameters();#获取参数列表,参数分为三种类型,URL中的参数,cookie中的参数,body中的参数。

    for para in paraList:
    # 这里可以考虑对加密参数进行筛选
    key= para.getName() # 获取参数名
    value= para.getValue() # 获取参数
    aesValue = aes.encrypt(value); 
    aesValue = URLEncoder.encode(aesvalue); 

    遍历参数,可以对参数名进行过滤,处理需要加密的参数

    newPara= helpers.buildParameter(key, aesValue, para.getType()); #构造新的参数                          
    updateRequest = helpers.updateParameter(new_Request, newPara); #构造新的请求包
    messageInfo.setRequest(updateRequest);//设置最终新的请求包

    //如果作为插件开发的话,只需要更改AES秘钥即可。

  • 相关阅读:
    5.5团队冲刺08
    5.6团队冲刺09
    5.4团队冲刺07
    5.3团队冲刺06
    5.2团队冲刺05
    第14 周作业
    CentOS Linux release 7.4 yum 安装mariadb-5.5.65 登录报错 ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/data/mysql/mysql.sock' (2)
    第13周作业
    解析函数
    npm模块安装机制
  • 原文地址:https://www.cnblogs.com/cat47/p/12273525.html
Copyright © 2011-2022 走看看