教你如何用BurpSuite挖掘多种基础漏洞,认知几种BurpSuite的高赞插件,以及如何自己为自己定制插件。

常见场景


http://static-v.zhishibox.net/2021226_qiniu_6c76273375a36e05004962b905d5c4fb.mp4|https://static.zhishibox.net/20210226/image_100808175.png

身份验证系统是什么?

身份验证是应用程序防御恶意攻击的核心。它是防止未经授权访问的第一线。如果攻击者可以绕过防御措施,他通常会完全控制应用程序的功能,并可以不受限制地访问其中的数据。如果没有强大的身份验证依赖,其他核心安全机制(例如会话管理和访问控制)都不会有效。 身份验证如今复杂多样,有传统的登陆,也有
双因素(2FA)认证
,还有
单点登陆(SSO)

OAuth2.0认证(第三方登录)
。 传统登录,如图所示: 对于传统的身份验证登陆来说,Burp Suite的攻击方式无非就是爆破,爆破是什么?就是不断修改数据包发送的信息,然后重复发送,通过响应包来判断是否爆破成功,核心理念就是成功失败的响应不一致。就比如登陆成功响应包中有一个关键字success,就可以通过观察哪些响应包里有这个关键字,然后判断账号密码是什么。 那开发人员为了应对这种情况,怎么做呢?
1在登录验证时添加验证码 添加一次性token

特殊情况:先发送验证码的请求包,然后再发送账号密码的请求包,这样就可以只抓取账号密码的请求包,进行爆破,从而达到绕过验证码进行爆破的目的。

攻击方式


http://static-v.zhishibox.net/2021226_qiniu_a5a699270d2e822d7a21b131ceb218fe.mp4|https://static.zhishibox.net/20210226/image_103332863.png

爆破需要准备:


1字典(100个常见的弱口令) 爆破参数 基准响应

总结

什么时候可以通过 Burp Suite 来进行身份验证的攻击?

有登录后台的时候。

什么情况下可以进行攻击?

不存在验证码,不存在 token 的时候。

攻击流程是什么?

抓取提交账户密码的请求包,放到 intruder 模块里,填充加载字典,进行爆破。

如何判断是否攻击成功?

完成之后,通过查找不同程度的响应,找到爆破成功的 password。

Burp Suite测试SQL时间盲注


http://static-v.zhishibox.net/2021226_qiniu_e6af9ad3e899467ae2c6ecd65a8260aa.mp4|https://static.zhishibox.net/20210226/image_101986784.png

前端限制控件的绕过与利用


http://static-v.zhishibox.net/2021226_qiniu_32a4eb3d0aa5131726f4eac280fe1710.mp4|https://static.zhishibox.net/20210226/2238600_1574846565_109784360.png

被动式漏洞扫描检测


http://static-v.zhishibox.net/2021226_qiniu_7bdcc820abf24114023963f9f47d49f9.mp4|https://static.zhishibox.net/20210226/image_108599564.png

Burpsuite安装扩展

Burpsuite提供了相当完善的扩展功能,安全人员可以根据自己的需求添加扩展 Burpsuite扩展的支持的语言有java,python,ruby,但是python的插件需要提供一个Jython环境,而ruby呢则需要提供Jruby环境
java python ruby

jython是java实现的python解释器,jruby呢是java实现的ruby解释器{这两个的特点就是慢,因为多了抽象层次,但是相比于java,python和ruby编写插件明显很简单}

话不多说,直接开始学习,如何安装自己想要的插件

{安装插件有两种形式,一是在BApp中下载官方套件,还有一种就是手动Add插件}


1BApp Extensions
同时呢,安装插件还有python和ruby的环境问题,得提前在Options中准备好运行环境
http://www.jython.org/downloads.html

https://www.jruby.org/download
下载好对应的包,然后导入: 导入前后的变化是什么呢?可以以BApp中的Actice Scan++为例,在导入Jython环境前,是无法直接Install的,当导入后 前后对比图:

BApp直接安装

环境准备好后就可以通过BApp直接install想要的插件,其中插件的介绍都写在右边,而来源呢则都来自于portswigger的官方github 官方列表上还有根据好评和下载量的排序,截至课件的时候,下载量最高的就是刚才说的Active Scan++,而好评这个因为五星众多,所以难以排序。不过插件类型不同,有的是属于辅助类型的,也有属于主动探测的,更有将Burpsuite扩展到其余用途的插件,这些都得自己根据需求一点点的接触摸索,从而知道效果。
Extensions Add
官方的插件虽然好,但是很多时候并非我们所需要的,这时候就需要我们根据需求去寻找优质的第三方插件导入,这就需要注意如下两点。
python和Ruby的直接导入 java的则需要编译成jar包导入
python和ruby相同,所以只演示导入python的,这儿就用unicode转码的插件为例子
https://github.com/stayliv3/burpsuite-changeU
我们将源码下载下来,然后点击Add,选取类型为python,导入刚才的python文件,至于输出和错误输出的话,这儿我是推荐都选择UI,因为方便看 安装后 java的插件稍显麻烦,需要本地先编译成jar包,然后导入,找一个例子看一下
https://github.com/PortSwigger/log-viewer
git下来后,然后在Burpsuite中把所有的API java文件下载下来,放入src/burp中,同时在src同级目录中创建build文件夹和bin文件夹,一个用来存编译后的.class文件,另一个则来存打包好的jar包 点击Save Inerface files,将所有的API文件存入 和插件源码放在一起
javac -d build/ src/burp/*.java

jar cf bin/logs.jar -C build burp
这时候bin目录下会有一个log.jar文件,用之前的方法正常导入即可,当然还有导入IDEA之类的编译方式,但是都用到这些IDE了,应该也不需要多说什么了。

总结

Burpsuite的扩展上虽然java插件的速度要优于python/ruby,但是灵活性上则差得很多,因此对于新手或是仅仅是为了灵活实现目的玩家来说,个人推荐python/ruby来编写插件,而非java

Burpsuite插件的开发实战(三)

{本章是插件开发类的最终章,内容并不是很对,而是直接带领完善下上一章中编写的插件,完成属于自己的插件的开发。}回顾下上一章节,已然拉好了插件的框架,那么本章就可以把检测的逻辑填入其中了。}

筛选需要检测请求

{首先是筛选出需要检测请求的逻辑,先前也说过,就是先找到携带CORS标志的响应,那么自然就需要针对每一个响应内容作一次筛选,如果符合规则的话,则进入到接下来的逻辑之中。} 获取响应
baseResponse = self._helpers.bytesToString(baseRequestResponse.getResponse())
{首先需要明白的就是,一个插件从Burpsuite获取到的是一个封装好的实体,也就是baseRequestResponse,可以理解为一个基础单元,而后续的操作都是基于这个实体的。而之前针对api的章节也提到过IExtensionHelpers这个万用类,因此获取到相应的响应内容就可以借助到此类中的getResponse函数实现。} 判断是否存在cors标识
if 'Access-Control-Allow-Credentials: true' in baseResponse:
{直接打扁整个响应内容,暴力搜索携带认证的字符串是否在其中,倘若存在的话就自然的要去检测是否存在CORS的问题,不然没有什么检测的价值。}

构建头

{既然确认了是要进行检测的信息,那么通过getHeaders()函数返回一个头信息的List,挨个判断其中是否是origin:这样的开头,也可以写的严谨一点使用正则,判断是否是一个合理的形式,因为有可能出现origin: null这样的形式。}

payload payload = 'Origin: http://cors.check'

{当满足条件时,就该把对应的头信息给替换掉,那落实到代码可以先创建一个空的List,然后把原本的header给保存下来,遇到符合型式的,自然就替换掉就行了。}
new_headers =
for singleHeader in requestHeaders: if singleHeader.startswith("Origin:"): payload = 'Origin: http://cors.check' # Look for Content-Type Header) singleHeader = payload new_headers.append(singleHeader)

构造请求

{当一个已经包含了payload的头构造完成后,就可以将其利用api形成一个合法的请求发送出去,并且验证相应的响应信息。如果要做点这一点,就可以使用到buildHttpMessage()这个函数,只需要提供header信息和body信息即可,如果是GET的请求的话,body置空就行。}
NewRequest = self._helpers.buildHttpMessage(new_headers, new_body) NewResponse=self._helpers.bytesToString(self._callbacks.makeHttpRequest(baseRequestResponse.getHttpService(),NewRequest).getResponse())
{此刻可以构造一个标志,倘若为1则证明存在漏洞,而只有经过上述的逻辑检测后才将其设置为1}
re = 'http://cors.check' vul = 0 if re in NewResponse: vul = 1

返回一个封装的信息

{关于单个漏洞的信息需要提前写好,然后一起返回后封装程一整个实体信息。}
new_body = '' new_headers =
re = 'http://cors.check' vul = 0 ISSUE_NAME="Cors Vulnerability" ISSUE_DETAIL="Cors" ISSUE_BACKGROUND="Origin: http://cors.check" REMEDIATION_DETAIL="Cors Vulnerability"
返回项 return new_headers,new_body,re,vul,ISSUE_NAME,ISSUE_DETAIL,ISSUE_BACKGROUND,REMEDIATION_DETAIL ScanIssue实体 issue.append(ScanIssue(baseRequestResponse.getHttpService(), self._helpers.analyzeRequest(baseRequestResponse).getUrl(),httpmsgs, vuldetail
, vuldetail
, SEVERITY, CONFIDENCE, vuldetail
, vuldetail
, REMEDIATION_BACKGROUND)) {到此为止,一整个代码结构就写完了。贴一下完整代码}
#!/usr/bin/env python2 #coding = utf-8 #Burpsuite module from burp import IBurpExtender from burp import IRequestInfo from burp import IResponseInfo from burp import IScanIssue from burp import IScannerCheck #python module import sys sys.path.append('/usr/lib/python2.7/site-packages') #INCLUDE YOUR lib from array import array import requests #Extender describre class BurpExtender(IBurpExtender,IRequestInfo,IResponseInfo,IScanIssue,IScannerCheck): def registerExtenderCallbacks(self,callbacks): #keep a reference to our callbacks object self._callbacks = callbacks #helper methods self._helpers = callbacks.getHelpers() #define name self._callbacks.setExtensionName("CorsScan") #register a scancheck callbacks.registerScannerCheck(self) return def doPassiveScan(self,baseRequestResponse): issue =
vuldetail= self.cors_check(baseRequestResponse) if vuldetail
== 1: NewRequest = self._helpers.buildHttpMessage(vuldetail
, vuldetail
) baseRequestResponse = self._callbacks.makeHttpRequest(baseRequestResponse.getHttpService(),NewRequest) #mark re match = self.getMatches(baseRequestResponse,vuldetail
) httpmsgs =
issue.append(ScanIssue(baseRequestResponse.getHttpService(), self._helpers.analyzeRequest(baseRequestResponse).getUrl(),httpmsgs, vuldetail
, vuldetail
, SEVERITY, CONFIDENCE, vuldetail
, vuldetail
, REMEDIATION_BACKGROUND)) return issue #payload code def cors_check(self,baseRequestResponse): ################### new_body = '' new_headers =
re = 'Access-Control-Allow-Origin: http://cors.check' vul = 0 ISSUE_NAME="Cors Vulnerability" ISSUE_DETAIL="Cors" ISSUE_BACKGROUND="Origin: http://cors.check" REMEDIATION_DETAIL="Cors Vulnerability" ######################### baseResponse = self._helpers.bytesToString(baseRequestResponse.getResponse()) #baseResponse = self._helpers.analyzeResponse(baseRequestResponse) baseRequest = self._helpers.analyzeRequest(baseRequestResponse) requestHeaders = baseRequest.getHeaders() print baseResponse if 'Access-Control-Allow-Credentials: true' in baseResponse: for singleHeader in requestHeaders: if singleHeader.startswith("Origin:"): payload = 'Origin: http://cors.check' # Look for Content-Type Header) singleHeader = payload new_headers.append(singleHeader) NewRequest = self._helpers.buildHttpMessage(new_headers, new_body) NewResponse = self._helpers.bytesToString(self._callbacks.makeHttpRequest(baseRequestResponse.getHttpService(),NewRequest).getResponse()) if re in NewResponse: vul = 1 return new_headers,new_body,re,vul,ISSUE_NAME,ISSUE_DETAIL,ISSUE_BACKGROUND,REMEDIATION_DETAIL class ScanIssue(IScanIssue): def __init__(self, httpService, url, httpmsg,issueName, issueDetail, severity, confidence, remediationDetail, issueBackground, remediationBackground): self._issueName = issueName self._httpService = httpService self._url = url self._httpMessages = httpmsg self._issueDetail = issueDetail self._severity = severity self._confidence = confidence self._remediationDetail = remediationDetail self._issueBackground = issueBackground self._remediationBackground = remediationBackground def getConfidence(self): return self._confidence def getHttpMessages(self): return self._httpMessages #return None def getHttpService(self): return self._httpService def getIssueBackground(self): return self._issueBackground def getIssueDetail(self): return self._issueDetail def getIssueName(self): return self._issueName def getIssueType(self): return 0 def getRemediationBackground(self): return self._remediationBackground def getRemediationDetail(self): return self._remediationDetail def getSeverity(self): return self._severity def getUrl(self): return se

Burpsuite插件的开发实战(二)


http://static-v.zhishibox.net/2021227_qiniu_4008917c379dd02c780419037242ccb6.mp4
{上一章讲了Burpsuite插件开发基本的环境的准备,这一章就该正式踏入开发流程了,一个插件的开发首先得想好目的,其次才是去探索实现的技术手段。先前也说过,Burpsuite的插件能够提供多方面的便利,而初次开发的人练手最好的也是扫描类的插件,那本次就以一个扫描类的插件来进行开发。}

检测漏洞 CORS 开发语言 python 扫描方式 被动扫描

{简单定义下开发的目的,开发语言与扫描模式,这样我们就能拉出一个开发框架了。比如是检测的漏洞是CORS,那既然如此就需要简单知道这个漏洞的检测需要什么。}

CORS

{cors是一种跨域请求机制,即跨域资源共享,当请求是由XMLHttpRequest或者Fetch发起的跨域请求时,就必须要携带CORS的请求响应头,这样才能允许资源的跨域访问,否则会被拦截。} 跨域请求机制 {其中发起请求的一方在自己的http请求中必须携带CORS的字段,即Origin来标明请求来源,如果与server的允许源一致的话,才能正确建立资源访问。}

Client: Origin

Server: Access-Control-Allow-Origin

{先前的视频应当讲过这个漏洞的具体问题,那么要实际检测的话,该怎么做呢?首先回想一下先前的课程,关注点在于响应中的Access-Control-Allow-Origin和Access-Control-Allow-Credentials,倘若这两者同时存在,就可以通过修改请求中的Origin来判断漏洞是否存在} 浏览器的最后防线

The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'

设计思路

{一个被动扫描虽然可以针对所有的请求做一个全量的检测,但是那样未免有些蠢,CORS是在跨域请求中出现的问题,那么自然需要筛选出跨域的请求,或者说是携带CORS特征的请求,否则针对任意请求就去添加一个Origin的请求头,很有可能引起意想不到的错误。} 特征 {之前说了,检测的逻辑在于响应中的CORS头是否存在,那么插件中监听的就应当是响应头中的内容,倘若检测到了再重构请求头来校验漏洞是否存在,若存在则输出相应的漏洞详情。} 监控响应 {重构请求后自当判断,按照先前的逻辑只是简单检测的话,就直接修改请求中的Origin然后判断新的响应中Access-Control-Allow-Origin是否包含了Origin且Access-Control-Allow-Credentials是否为True} Origin in Access-Control-Allow-Origin Access-Control-Allow-Credentials=true

拉框架

{因为选取的是被动扫描模式,所以必须要实现被动扫描的方法,那么在BurpExtender中就必须继承IScannerCheck,同时需要输出漏洞的信息的话,那就还要继承IScanIssue} class BurpExtender(IBurpExtender,IRequestInfo,IResponseInfo,IScanIssue,IScannerCheck): {因为检测需要的功能并不是很多,因此继承需要用到的即可,而并不需要想得太多。}

doPassiveScan

{既然是被动扫描模式就需要重写被动扫描的方法,将检测逻辑放入其中,这样才能在浏览时针对通过proxy的http消息流作处理,最后处理完自然应当返回issue的信息}
def doPassiveScan(self,baseRequestResponse): issue=
cors_check(baseRequestResponse) return issue

ScanIssue

{实现漏洞信息的输出也是需要写代码的,并非说调用就完事了,当cors_check检测完后自然要对漏洞信息进行封装,例如调用了ScanIssue,把各种信息封装后再塞到issue中,目的是为了解耦,方便增加新的检测逻辑时候调用,不然每一次塞入就写一次封装其实十分麻烦。}
class ScanIssue(IScanIssue): def __init__(self, httpService, url, httpmsg,issueName, issueDetail, severity, confidence, remediationDetail, issueBackground, remediationBackground): self._issueName = issueName self._httpService = httpService self._url = url self._httpMessages = httpmsg self._issueDetail = issueDetail self._severity = severity self._confidence = confidence self._remediationDetail = remediationDetail self._issueBackground = issueBackground self._remediationBackground = remediationBackground def getConfidence(self): return self._confidence def getHttpMessages(self): return self._httpMessages #return None def getHttpService(self): return self._httpService def getIssueBackground(self): return self._issueBackground def getIssueDetail(self): return self._issueDetail def getIssueName(self): return self._issueName def getIssueType(self): return 0 def getRemediationBackground(self): return self._remediationBackground def getRemediationDetail(self): return self._remediationDetail def getSeverity(self): return self._severity def getUrl(self): return self._url

框架代码

{在没写功能的情况下,先把框架代码贴出来,之后把逻辑代码填进去正确返回信息就能完成这个插件的编写了}
class BurpExtender(IBurpExtender,IRequestInfo,IResponseInfo,IScanIssue,IScannerCheck): def registerExtenderCallbacks(self,callbacks): #keep a reference to our callbacks object self._callbacks = callbacks #helper methods self._helpers = callbacks.getHelpers() #define name self._callbacks.setExtensionName("CorsScan") #register a scancheck callbacks.registerScannerCheck(self) return def doPassiveScan(self,baseRequestResponse): issue =
isissue= self.cors_check(baseRequestResponse) issue.append(ScanIssue(isissue)) return issue #payload code def cors_check(self,baseRequestResponse): return issue class ScanIssue(IScanIssue): def __init__(self, httpService, url, httpmsg,issueName, issueDetail, severity, confidence, remediationDetail, issueBackground, remediationBackground): self._issueName = issueName self._httpService = httpService self._url = url self._httpMessages = httpmsg self._issueDetail = issueDetail self._severity = severity self._confidence = confidence self._remediationDetail = remediationDetail self._issueBackground = issueBackground self._remediationBackground = remediationBackground def getConfidence(self): return self._confidence def getHttpMessages(self): return self._httpMessages #return None def getHttpService(self): return self._httpService def getIssueBackground(self): return self._issueBackground def getIssueDetail(self): return self._issueDetail def getIssueName(self): return self._issueName def getIssueType(self): return 0 def getRemediationBackground(self): return self._remediationBackground def getRemediationDetail(self): return self._remediationDetail def getSeverity(self): return self._severity def getUrl(self): return self._

Burpsuite插件的开发实战(一)


http://static-v.zhishibox.net/2021227_qiniu_cc71ddf3c020a0078eb39ec68d9d0e0c.mp4
{本章开始进入整个课程的终三章,也将带大家从熟悉插件的开发环境到最终编写出一个完整功能的插件,对于Burpsuite的插件来说有java,python,ruby三种,但是我只接触过其中的java和python,而针对新手来说,python编写插件要比java方便很多,因此主要讲解的是python编写,但是也会提及java的开发环境以及编写。}

开发环境

java

{java的开发环境在一定程度上要比python的复杂的多,为了方便开发,我选择的环境如下}

IDEA openjdk 1.8.0_192

{首先先把burpsuite提供的各种api的java源码导入到项目之中,就是先前编译java插件的课程中提到的方式,到Extender-APIs下下载所有的interface,然后保存到一个文件夹下。} {打开IDEA,选择导入项目,也就是import project将刚才的文件夹导入,之后选择create project form existing sources,然后一直next就行} {最终如果进入到IDEA的开发界面并且没有什么报警的话, 就说明导入完成了,接着就可以测试下是否能够成功编译插件,像学习编程一样,我们尝试编写一个最简单的hello world,就像先前说的一样,插件代码必须有BurpsuiteExtende并且实现IBurpsuiteExtender,因此就创建一个这样的类出来。} {修改一下代码格式,加入需要实现的registerExtenderCallbacks方法,拉出一个最初的框架出来}
package burp; import burp.IBurpExtender; public class BurpExtender implements IBurpExtender{ @Override public void registerExtenderCallbacks(burp.IBurpExtenderCallbacks callbacks) { //TODO }
{插件名取名NewExtender,然后打印一个Hello World出来,最终的代码如下}
package burp; import burp.IBurpExtender; public class BurpExtender implements IBurpExtender{ @Override public void registerExtenderCallbacks(burp.IBurpExtenderCallbacks callbacks) { callbacks.setExtensionName("NewExtender"); callbacks.printOutput("Hello World"); }
{导出jar包,IDEA用快捷ctrl+alt+shift+s打开Project Structure,然后选择Artifacts点击右上角绿色的+号,选择JAR-From module,接着Main Class中选则刚写好的BurpExtender,可能会报错不用管,出现如下界面即可,后面直接点击OK后选择输出目录再finish即可。} {Build-Build Project快捷键是ctrl+F9,将项目的java文件编译程.class文件,接着选择Build-Build Artifacts选择要打的jar包就是刚才的哪个burp.jar直接build即可。} {导入测试下,输出Hellow World就没什么问题}

python

{相比之下,python明显就简单很多,只需要写一个输出脚本加载进去就行。除了jython,就不需要再准备什么环境了。直接上代码即可,而且不像java一样每次改动就要重新编译,因此开发效率上要方便快捷很多。}
#!/usr/bin/env python2 from burp import IBurpExtender class BurpExtender(IBurpExtender): def registerExtenderCallbacks(self,callbacks): callbacks.setExtensionName("NewExtender") callbacks.printOutput("Hello World")

认识Burpsuite的API(三)


http://static-v.zhishibox.net/2021227_qiniu_f438c51f29749408c9654afd762b5b33.mp4
{这是关于Burpsuite中api介绍的最后一章了,前面两章分别阐述了插件的框架搭建,插件和Burpsuite原生工具的联动,现在这一章则讲解一下Burpsuite中最为重要的一部分,也就是关于HTTP信息的处理。} HTTP消息处理接口 {Burpsuite的插件基本都是针对http信息的操作,其中包括了请求和响应两种信息,一次完整的http消息,请求和响应在Burpsuite中都有不同的表示类型,这一章就详细讲解一下关于Burpsuite中最基础的三个类。}

介绍

{Burpsuite是一个针对web的测试工具,那么既然是针对web,就是和http信息打交道的,如此就必然得包含大量针对http信息的处理方法。因此在Burpsuite中,一个类型就显得特别的重要,也就是IHttpRequestResponse} IHttpRequestResponse IHttpRequestResponse {这其实是Burp中对于一个http信息的封装,这样说也许不太理解,所以我展示一个IHttpRequestResponse,看看它的样子是什么样的。}

request: GET / HTTP/1.1 Host: 127.0.0.1 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:59.0) Gecko/20100101 Firefox/59.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Connection: close Content-Length: 2

Burpsuite中的输出

burp.x2e@48762ea6 {这一个burp.x2e@48762ea6就是一个IHttpRequestResponse类型的baseRequestResponse,那么这个burp.x2e@48762ea6中有哪些信息呢}
request response httpservice
....(这部分数据不常用,可以自己了解) {前两个好说,后面的httpservice什么呢?这个可以直接理解为host+port+ishttps,是不是看着很熟悉,用肉眼可以看的就是在repeater模块右上角那个修改按钮中的东西,倘若以一个baseRequestResponse的操作为例子。} baseRequestResponse.getRequest() self._helpers.analyzeRequest(baseRequestResponse) {然而具体输出的话,其实第一个是一个array数组,就可以简单理解成是整个字符串的合集,并没有区分head和body,而第二个则是一个IResponseInfo类型的数据,是依旧封装的东西,内部还有结构}

IRequestInfo和IResponseInfo

{很重要的两个类型,一个代表了request一个代表了response,对于这两个类型,官方还提供了很多功能强大的处理方式,以被动扫描来说,需要明白到底要对数据做哪些处理,比如针对一个漏洞,需要对request进行识别,判断是否存在可疑点,接着就是针对这个request进行修改甚至是重构,然后再根据重构后的response进行判断。按照如上的逻辑,需求可以简单划分为对request的读写和对response的读,而写又分为edit/update(编辑)和build(重构)} 查看一下官方的文档,列出一个IRequestInfo的可用函数:

getBodyOffset() getContentType() getHeaders() getMethod() getParameters() getUrl()

{函数名都很简洁易懂,清晰的展示了自己的功能,这些都属于读取,那写(更新/重构)的函数有哪些}

setRequest(byte
message) makeHttpRequest(IHttpService httpService, byte
request) buildHttpRequest(java.net.URL url) buildHttpMessage(java.util.List‹java.lang.String› headers, byte
body)

{就以读来说,知道上面的几个函数就完成了吗?不是,这讲解的是类型,那么这儿怎么可能没有类型导致的坑呢。python下是不能直接处理Burpsuite所特有的类型的,那么按照顺序来,光是读的那部分,函数返回的类型是如下}
int byte list
String list
url
{这些类型里int,list
,string可以直接被python使用,而url经过str()函数强转也可以被python使用,而其余的则需要经过官方提供的函数继续处理。同样的针对函数的使用也要着重注重类型的转换,相应的类型才能被使用,比如buildHttpMessage这样的函数,他的传参是一个byte,那么如果传入的数据是一个str类型,就会出错,因此以这个坑来说,就自然提供了下面的转换函数来解决。} stringToBytes(java.lang.String data) 把字符串转byte类型数据

总结

{在一次插件的开发过程中,可以说各种方法的实现其实都是针对这种类型的数据的处理,如修改参数值,添加头,检测头,构造特殊的请求,都是针对整个消息作改造,然后再传递到各个工具模块中使用,甚至是通过插件本身内部将消息解析后发送,比如利用python的request模块直接发送,将插件逻辑还原到最熟悉的python脚本也不失为一个好的方法。}

认识Burpsuite的API(二)


http://static-v.zhishibox.net/2021227_qiniu_444fee531149578d44c0ab8e23543284.mp4
{上一期中介绍了Burpsuite中主要的入口类接口以及帮助类接口,这些接口组成了插件的主体框架,而今天则来认识一下Burpsuite中的工具组件类接口。Burpsuite中包含了我们经常用到的各式工具,如Proxy,Scanner,Intruder等等,而为了方便插件调用这些工具,自然而然的开放了相应的接口。}
IProxyListener IScanIssue IScannerCheck
{上述三个接口是新手开发插件时候最常用到的三个接口,为什么呢?并非说这三个插件十分的基础,其实上来说工具类插件基本都是并级关系,和已有的工具相互对应,常用的原因主要是因为开发的目的。} 试手用插件开发
扫描类 优化类
{在利用Burpsuite作插件开发的时候,除非有什么特殊的用途,一般的功能无外乎于针对扫描模块的补全,比如之前的J2EEScanner,添加了大量java的payload以此产生对于企业级应用的扫描支持,而优化类则比较好理解,就是针对Burpsuite中的信息作优化,比如自动转编码,保活机制等。}

工具类接口

IProxyListener {如其名,这是一个关于代理工具的接口,简单来讲功能的话就是插件可以从这个接口获取到经过Proxy工具的请求和响应,然后插件可以针对这些消息作分析和修改。但是这一切的前提就在于,得先注册这样的一个监听器。}

对于工具类的接口来说,只要涉及到Listen的,基本都需要预先注册监听,这样才能在信息通过相应工具时候触发插件的逻辑

注册监听器 java:
public void registerExtenderCallbacks(final IBurpExtenderCallbacks callbacks){ ....... callbacks.registerProxyListener(this); }
python:
def registerExtenderCallbacks(self,callbacks): ........ . callbacks.registerProxyListener(self) return
{设置了监听后,就需要通过创建官方指定的函数来接收Proxy传输过来的数据,也就是实现一个processProxyMessage方法,而针对对应消息的操作则都在此方法中实现。} 其中这儿有一个tips需要知道,那就是当你开启intercept时,即使你Drop了request,依然会传入此监听器,因为request是优先进入的Proxy 方法实现 java:
public void processProxyMessage(boolean messageIsRequest, IInterceptedProxyMessage message) { // TODO }
python:
def processProxyMessage(messageIsRequest,message) // TODO
{第一个参数是一个布尔值,其中1则代表是一个请求消息,0则是响应消息,第二个参数是对应的消息,是一个IInterceptedProxyMessage类型的数据,而这个类型的数据则提供了对应的处理方法。这个可以到官方API中查看,而其中最常用的则是下面这个函数。}
getMessageInfo() //这个方法能够返回一个IHttpRequestResponse类型的数据,这在Burpsuite中代表一个具体的信息。

IScanIssue

{这个接口是最常被扫描器使用的一个接口,因为通过它,新的插件就能利用Burpsuite来展示漏洞的详情,就像之前的插件利用原生模块输出一样,就是通过这个接口。此接口主要是获取到Scanner工具的信息和自定义扫描详情,因此使用此接口实际有多种方法。} 因为是讲自定义插件,因此这部分主要讲解如何自定义详情 {自定义详情主要通过两种方法,一个是注册一个IScannerCheck,还有一种就是调用addScanIssue方法}
注册接口 调用方法
{但不管是哪一种方法,都要求的是传入参数类型为IScanIssue,这是一个Scanner工具才会传出来的类型,因此可以理解成这个接口是需要依托于Scanner工具的} java:
public void newScanIssue(IScanIssue issue){ callbacks.addScanIssue(IScanIssue issue); }
python:
def newScanIssue(issue) self._callbacks.addScanIssue(issue)
IScannerCheck {IScannerCheck这个可以说是另类监听器,也可以说是一个检查器,其实后者更为准确,在开发被动扫描插件时,我原先使用的是IProxyListener,后来发现IScannerCheck更为便捷,通过注册一个检查器,然后再利用doPassiveScan的实现来做到对于PROXY的请求的变相监听,这儿说是变相监听是因为官方文档的说明定义此处仅是对一个baseRequestResponse做被动检查,而非如上两个监听器的行为,但是其最终效果,却十分的出色。} IBurpExtenderCallbacks.registerScannerCheck() {在之前说过的,大部分工具类接口的使用都需要先注册,因此此处同理,只有在注册了之后,才能够在信息通过相应模块时触发逻辑。}
doActiceScan doPassieScan
{这两个方法和名字基本相同的解释,当主动扫描时调用此方法,当被动扫描时调用此方法。而有一个更好玩的点就是Burpsuite的本身在信息通过Proxy后就会主动进行被动扫描了,因此只要你的插件选取的是doPassiveScan,就代表在这个方法下的逻辑就会一并添加入被动扫描模块中,基本就相当于是一个方法补全了。} java:
public List doPassiveScan( IHttpRequestResponse baseRequestResponse) { // TODO here return null; }
python:
def doPassiveScan(self,baseRequestResponse): issue =
return issue

认识Burpsuite的API(一)


http://static-v.zhishibox.net/2021227_qiniu_25aa4d5a9943076e39fac9f54e7c1056.mp4
{从本章节开始,不再讲插件了,而是进入到关于Burpsuite的高级部分,认识Burpsuite所提供的丰富的API,为后面编写插件打下基础,当然,Burpsuite的API众多,因此不一一讲解,只挑选其中的重点,坑点进行讲解,以此带领大家做一个入门。}

API帮助文档


https://portswigger.net/burp/extender/api/
{实际上来说,官方只提供了接口文档却并没有提供api的详细解释,因此无形之中就提高了整个插件的开发学习难度,而国内的话,也只有曾今乌云社区中出现过较为详细的文章展示各个API的利用,但是呢,其中的坑点难点还是没有较好的说明,因此在编写插件时候还是容易踩坑。而这种情况下官方也给出了开发者社区,其中也包含了各种开发者开发过程中遇到的问题来指导解决}
https://support.portswigger.net/

http://www.vuln.cn/6098

API类型

{章节主要将API类型分为如下三类作相关讲解,但是实际上官方提供的api还有UI相关类,然而对于初学者来说,这方面的内容可以省略掉,因为刚开始写插件时候还是以实现功能为主。}
插件入口与辅助 Burpsuite工具组件接口 HTTP消息处理

插件入口与辅助

{这一部分介绍的是Burpsuite必须实现或者着重关注的几个类,如果把插件比喻成建房,那么这几个类就是房子中的横梁或者支柱。}

IBurpExtender

{这是一个核心类,任何一个插件都需要实现这个接口,且接口名称即实现的类名必须为BurpExtender,必须声明为public,必须提供一个默认的构造函数。} 三个必须
名称:BurpExtender 声明:public 构造函数
构造函数:
void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks)
{这是官方定义好的构造函数,当插件被加载时即调用此方法,意思就是说,如果没有这个方法的话插件就无法被加载。这个方法提供了一个IBurpExtenderCallbacks的接口,从这个接口中可以获取到一个IBurpExtenderCallbacks对象其中封装好了各种方法,方便插件的开发。} Java:
public class BurpExtender implements IBurpExtender{ @Override public void registerExtenderCallbacks(final IBurpExtenderCallbacks callbacks){ //TODO } }
Python:
class BurpExtender(IBurpExtender): def registerExtenderCallbacks(self,callbacks): //TODO
{这儿给出了java和python的两种写法,就此便已经是现实了一个插件的入口,能够使得插件被顺利加载。}

IBurpExtenderCallbacks

{这个类不需要插件去继承或者实现,因为在插件加载之后,Burpsuite会通过调用上面的registerExtenderCallbacks方法传递一个IBurpExtenderCallbacks的对象,然后插件通过传入的这个对象调用其中的方法。}

这儿有一个约定俗成就是保持对回调对象即callbacks的引用

java: this.callbacks = callbacks; python: self._callbacks = callbacks

{IBurpExtenderCallbacks这个类中封装的方法非常多且十分的实用,但是其中尤其要注意的就是回调方法接收的参数类型以及返回的数据类型,这在Burpsuite的插件开发中是一个十分大的坑点。以插件初步的开发来说,为一个插件设置属性比如插件名字,那么写法就如下面的代码一样。} java:
callbacks.setExtensionName("this is new extentd");
python:
self._callbacks.setExtensionName("this is new extentd")
效果 {还有非常多的方法从官方文档上查看,功能上面有比较简单的解释,后面写插件时候做相关函数的讲解,认识一下其中最为常用的万金油函数。}

IExtensionHelpers

{这个官方定义为辅助方法的接口,那么想要调用此接口,就需要在最初实现插件接口时就进行调用,但是呢在IBurpExtenderCallbacks中有一个方法能够获得这个实例,所以我们就不需要去继承。} self._helpers = callbacks.getHelpers() {上面的方法可以直接获得一个IExtensionHelpers实例,进而使用其中的各种方法,而从名字上也可以看出,这个类就是Burpsuite官方提供的一个专门辅助开发的,其中包含了大量的工具类的方法。这儿提出几个比较核心的方法。}
analyzeRequest() //最常用函数之一,返回一个IRequestInfo,分析一个IHttpRequestResponse的请求 analyzeResponse() //同上分析一个响应,返回IResponseInfo,但是这儿有个坑,就是传入只能是byte
buildHttpMessage() //构造一个byte类型的请求,非常实用的一个函数,我自己开发时基本都是用这个函数重构的请求,传入为(string headers,byte
body) bytesToString() //还记得上面提到的大量的byte形式的数据吗,就是通过这个函数能够转成被python识别的string stringToBytes() //上面反者理解,因为有很多函数处理的是数据类型就是byte而非string

IExtensionStateListener

{虽然是核心功能,但是这却是一个不常用的接口,因为一般的小插件很少需要针对插件的卸载作善后处理。不过学习一个插件的完整开发也并非不行。该接口和IBurpExtender一样只提供了一个方法。}

unload方法


void extensionUnloaded()
{这个方法是当插件被卸载时候调用,终止插件的线程以及相关的资源调用。说一下实现接口的方式。} java:
public class BurpExtender implements IBurpExtender, IExtensionStateListener{ @Override public void registerExtenderCallbacks(final IBurpExtenderCallbacks callbacks){ this.callbacks = callbacks; callbacks.registerExtensionStateListener(this); } }
python:
class BurpExtender(IBurpExtender,IExtensionStateListener): def registerExtenderCallbacks(self,callbacks): self._callbacks = callbacks self._callbacks.registerExtensionStateListener(self)

Backslash-Powered-Scanner:扫描理念的变化(三)


http://static-v.zhishibox.net/2021227_qiniu_2cfca59902e8eebca893d86f78df030b.mp4
{上一章了解到传统扫描器的薄弱点,那么从这一章开始自然应当学习下由Backslash-Powered-Scanner带来的一种新颖的漏洞扫描工具的设计观念。首先先概述一个手工测试与fuzz的概念。}

手工测试

{手工测试是以人为本,对于漏洞的识别能力取决于测试者的知识储备与测试技巧,一个合格的测试者能够针对不同waf规则进行规避,也能够凭借微小的网络痕迹对一个薄弱点作针对性测试,而不是浪费大量的时间把所有的方法尝试一遍。但是与之相对的劣势也是非常明显,就是成本问题}

劣势 测试体量越大效率越低 对测试者能力依赖强,成本高

{大家总想要获得一个能力强又高效的产品,因此又有一种模糊测试的手段产生了,也就是俗称的fuzz测试,介于完全手工与完全自动化之间,但是这毕竟还是一种高级技巧,而且测试结果的质量高低一定程度上又依赖于定制化,因此成本上来说并不算低。但同样不可否认的,这种技巧的上升空间非常之高}

插件

核心逻辑

判断输入是否造成了服务端输出的变化 {这样说法也许有点空洞,那就换一个说法,针对一个web的链接来说,手工测试者无法确定是否存在漏洞,那就先按照正常的逻辑获取到一个应用程序的正常响应,也就是作为一个基准响应。接着按照测试者的经验发送相关的字符信息作为探针,例如在正常请求的基础上加上一个单引号,若此刻获取到的响应内容与基准响应不同,那么就可以说明应用程序会对单引号做出反应,虽然无法代表这儿就是存在漏洞,但是可以肯定的是对于应用程序来说,单引号存在某些意义,比如应用程序就是拒绝携带单引号的输入。但是若是携带单引号的响应与基准响应相同,这就可以确定单引号是一个能够逃逸检查的字符,以此循环替换探针。}

迭代

{针对插件来说,这是一个十分重要的过程,因为相比于传统扫描器直接定位漏洞是否存在,Backslash这样的插件更注重的是针对web应用行为的探测,通过对探针的不断迭代,如上就是单引号到反斜杠单引号的变换,快速忽略掉无用的输入为探测出有影响的字符串节省了大量的时间,形成一个部署探针-扫描比对-结果研究的迭代过程。} {假设Backslash针对一个注入点进行探测时,首先识别的就是哪种引号的使用,因为针对一个后端逻辑来说,引号意味着闭合方式,双引号和单引号的输入是能够造成不同的影响的,接着识别的是字符的连接方式,然后识别可能的函数调用,最后发送特定的函数尝试利用。当然这些尝试并非说是完全告别了payload,而是相比于传统的测试方式,这种方式明显更为高效且更注重逻辑性}

核心问题

{对于扫描的结果的探测来源于针对不同探针的响应的识别,那么核心问题也就很明显了,如何去识别呢?如果只是简单的字符串比较实际上在整个应用程序中是没什么作用的,因为应用程序本身就是一个动态的,响应中存在着动态生成的一次性令牌,时间戳,缓存甚至是对应的输入。插件作者在插件编写之初并没有很好的解决这个问题,因此插件并没有第一时间发布,而是在很久之后,通过了一种针对响应属性值计算的方式来进行判断,这种方式会针对状态码,Content-Type,HTML结构,行数,单词数,输入处理数以及关键字出现频率来作统一的计算}
状态码 Content-Type HTML结构 行数 单词数 输入处理数 关键字出现频率

但这一部分的详细内容并不打算讲解,有兴趣的同学可以自行研究源码

结语

{Backslash插件提出了一种新颖的扫描概念,并展示了迭代过程说明了测试者可以轻易的将一个明显的安全问题和需要多次验证的问题进行区分,而所需要做的也仅仅是针对探针灵活性的优化,或者说这个插件并非是一个漏洞扫描工具,而是针对web应用行为的探测,然后在一定程度上对结果进行聚合输出。现在web方面发展越来越迅速,各种安全机制的发展导致传统扫描器的能力逐步下降,甚至在某种程度上waf已经能够针对0day进行防御,因此对于安全产品的设计自当另辟蹊径而非只是一味的通过提高样本数量进行暴力测试。}

Backslash-Powered-Scanner:扫描理念的变化(二)


http://static-v.zhishibox.net/2021227_qiniu_e8c2c1ba6bdc7f4da74b2c4e9953be6a.mp4
{上一章节中应该清楚,这个插件依旧是一个扫描器,或者说是扫描器的补充。那么到底有什么值得推崇的呢?}

现有web扫描器

{现有的web扫描器都是通过在传参上利用大量payload进行测试或者寻找特征来判断是否存在漏洞,这样的扫描方式无非都在比拼谁的payload更多更有效,同时因为扫描器依赖于大量特定技术的payload,因此其缺乏应变性就意味着即使是最为先进的扫描器也难以做到像安全测试人员一样识别出某些明显的漏洞或者是绕过某些简单的waf} 例子(这儿其实是耍了诈)
‹?php $a=$_GET
; if($a == 'robots'){ echo "‹h1›this is test‹/h1›"; echo "‹!--admin:password--›"; }else{ echo "Nothing!!"; } ?›
请求后的结果: {对于扫描器来说,dir是一个传参,那么扫描器自然就应当在这个参数上进行大量的测试,直到传入参数是一个robots时候就会导致页面产生变化,扫描器就会进入下一个步骤,即按照既定规则来判断页面是否产生了应该产生的变化,比如输出,报错什么的?可以看到上面这个例子,如果是手工测试发现这样的一个页面第一反应应该是什么呢?当然是信息泄露啊。然而倘若扫描器的规则库中并不存在一个针对敏感信息泄露的识别,自然就不可能对这个漏洞进行定义。}

劣势 缺乏应变 能力取决于payload 对逻辑漏洞的支持能力差

扫描盲点

{这是一个针对上面劣势的补全说明,从三个盲点入手,详细阐述下通用扫描器的问题。}

一. 技术覆盖度

{扫描器的核心检测能力取决于特定技术的payload,然而这个特定技术是什么呢?以sql注入为例子,这是一种针对数据库的注入漏洞,那自然需要尽可能多的覆盖不同种类的数据库类型,这是因为并没有一种有效的payload能够一次性把所有的数据库都给覆盖全面。} 百度百科上展示的数据库产品 MySQL MariaDB(MySQL的代替品,英文维基百科从MySQL转向MariaDB) Percona Server(MySQL的代替品·) PostgreSQL Microsoft Access Microsoft SQL Server Google Fusion Tables FileMaker Oracle数据库 Sybase dBASE Clipper FoxPro foshub BigTable(Google) Cassandra MongoDB CouchDB Apache Cassandra Dynamo LevelDB {看到上面这章表,这代表仅仅是sql注入就得针对每一种的数据库产品做覆盖,而且需要对每一种数据库针对payload的解析做一个测试,以免产生不可预估的风险,那如果是模板注入的漏洞呢,代表扫描器需要有每一种模板引擎的payload硬编码,然而光是维基百科上有名的模板引擎就多达百种,这极大的挑战着扫描器的扫描能力,最终导致扫描器对于小众技术的应用程序进行检测时,性能下降十分严重。}

二. 规避能力

{依旧是以sql注入为例子,一个mysql的双引号盲注,扫描器可以通过这样的一条payload轻松检测出来}

".sleep(10)."

{但若是此刻web应用存在waf过滤了括号呢?手工测试者可以通过反引号绕过}

".`sleep 10`."

{waf再次检测sleep这个关键字呢?测试者可以在上一个payload的基础上进行编码绕过}

".sl%D0%B5ep(10)."

{再苛刻点,应用程序过滤了双引号}

{${sleep(10)}}

{安全测试人员可以通过实际的响应变换自己的payload主体,而扫描器则不行,传统扫描器的设计上就使得容易因为各种过滤或者变体而检测失败,而绕过的方式也仅仅是通过添加大量的payload来尽可能覆盖漏洞的每一个变体,然而漏洞越多,变体越多这代表在一次扫描周期内扫描器有可能发送了上百万个请求,这对于业务线来说其实是难以接受的一种情况。}

三. 构造能力

{这是一个非常高难度的能力,即使是人工测试也在这方面的能力也并非十分出色,因为不管是人还是机器的扫描逻辑在一般情况下都是针对已知参数进行测试,然而就是有一些漏洞比如hpp(http参数污染)这样的,通过构造恶意数组或者恶意参数从而触发漏洞。} 寻常的http请求

GET /search/?q=david HTTP/1.1 Host: sea.ebay.com.sg User-Agent: Mozilla/5.0 etc Firefox/49.0 Accept: text/html Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://sea.ebay.com.sg/ Cookie: session=pZGFjciI6IjAkLCJlx2V4cCI6MTA4 Connection: close

实际的攻击方式
GET /search/?q=david&q
=sec{${phpinfo()}}
{对于扫描器来说,其实这是十分难以实现的一个逻辑,因为这属于安全人员针对自身知识以及测试对象痕迹的总结,属于一种无中生有的测试手段,更别说扫描器如果真的想发现这种漏洞在一定程度上需要服务端对于请求数量没有限制,不过这也是比较极端的例子,因此不用考虑太多。}

Backslash-Powered-Scanner:扫描理念的变化(一)


http://static-v.zhishibox.net/2021227_qiniu_11153c813b6c29bbf6fe4756f9215208.mp4
{这次带大家认识的是Burpsuite的当家插件,也是PortSwigger官方Github放在首位的插件,Backslash-Powered-Scanner,这是一款全新概念的扫描插件,与传统扫描器不同,从新的维度开启针对web薄弱点的检测。}

安装与使用

{老规矩,本章节简单带大家认识一下这款插件的安装与使用,这是一款被官方极力推广的插件,因此直接通过BApps即可下载安装,同样的如果是从源码安装的话也可以使用官方提供的插件源码地址}
https://github.com/PortSwigger/backslash-powered-scanner

使用

{插件本身的定位是针对已知或者未知类型的服务端注入漏洞查找,是基于Burpsuite主动扫描能力的补充,因此插件的使用上其实十分简单,就是单纯的开启主动扫描即可。} sql注入 {同样是能够扫描出sql注入来,我们以一个靶机为例,看一下主动扫描与插件的对比结果} 主动扫描 {这是Burpsuite主动扫描的结果,我们先前说过,针对sql注入漏洞,Burpsuite是通过构造相关payload然后判断响应中是否存在敏感字符串来判断漏洞是否存在} Backslash-Powered-Scanner {这是插件的扫描结果,我们可以看到同样是识别出了mysql注入漏洞,然而插件的展示形式却完全不同,先前主动扫描本身也仅仅是提供了两个请求,而插件则是构造了高达20个请求,而且看一下响应中的高亮字符} 高亮字符串 {这与主动扫描采用的并非是相同的判断方式,那么插件为什么要采用这么大量的请求,又是通过什么方式来判断是否存在漏洞的呢?为什么要这样呢?这些都是本次插件值得学习的地方,也就是一种全新理念的安全扫描工具的设计。}

插件定级


vulnerable interesting boring
{上面扫描结果的图上,我们可以看到插件扫描出来的前缀是interesting,这是代表插件发现了疑似薄弱的地方,并提出了自己的漏洞定义,但是仍需要安全人员手动测试来最终定级,而与之相对应的还有vulnerable和boring两个定级,分别代表是插件确定存在某种漏洞,而boring则是不可利用的信息,不值得花费时间关注。}

小结

{插件的使用非常的简单,但是并非说这个插件十分简单,正相反Backslash我认为是极为难以使用的一个插件,因为它真正实现的是取代手工进行fuzz,并在某种程度上绕过了waf输出相关的利用,这是寻常扫描器所远远不能够相比的,而更加详细的内容,则下一期作讲解。}

burpsuite与sqlmap的联动(四)


http://static-v.zhishibox.net/2021227_qiniu_2d33e4a2f0ce23043446f0444febcfce.mp4
{上一章讲的东西并不多,只是带大家通过burpsuite的SQLiPy插件学习sqlmapapi的基本使用,但是也才刚进入到检测状态,而一个合格可靠的自动化测试工具自然少不了exploite阶段,本章节就深入熟悉下如何构建属于自己的自动化sqlmap调用工具。}

sqlmap的攻击 --current-user --current-db --dbs --tables --columns --dump

{一个sqlmap的使用就像第一章中所讲的,用的命令大概就是上述几种,分别是列出当前使用的数据库,列出当前用户,列出所有库,所有表,所有列,输出数据,这就要回想起第一章的内容,sqlmap是如何工作的呢?}

识别出薄弱点

http://victim.com/login/login.php?id=2016 {当上述url填入sqlmap中,此时sqlmap会先进行识别过程,也就是第三章的内容,即识别出一个url是否有薄弱点,在sqlmap中的具体表现就是如图这样,然而在sqlmapapi中那是代码调用的东西,那我们就要去判断并获取相应的信息才能进一步调用。} sqlmap识别薄弱点 sqlmapapi状态
"status": "terminated"
{对一个sqlmapapi的任务来说,当status显示为terminated就代表这个任务已经结束了,与之对应的状态是running,当任务结束后,此时的程序还不知道url中是否存在薄弱点,此刻便需要请求api获取到server返回的信息加以判断} SQLiPy 169-173行
resp = json.load(urllib2.urlopen(req, timeout=10)) vulnerable = False for findings in resp
: vulnerable = True
{这个代码是sqlipy的一个处理逻辑,判断一个url是否为携带薄弱点的url,就先打上false的标记,倘若发现api返回了data信息,则置为True,从这我们便可以判断出,只有sqlmapapi确认url是有漏洞的才会返回data} 有漏洞的返回 对应请求的api
curl http://127.0.0.1:8775/scan/‹taskid›/data
{单单是这一份返回之中,就包含了有漏洞的parameter,dbms即后端数据库类型还有多种类型的测试payload}

加以利用

{与sqlmap那样灵活使用命令操作不同的是,sqlmapapi通过任务开始前的设置,也就是第三章中所讲的option的设置操作,即把要查寻的数据提前填写,这样sqlmapapi才会在内部进行相关的sqlmap调用,例如上面的那个例子,就只是简单的针对URL的扫描,这样的话就不携带任何参数,那么查寻出来的数据自然就是最简单的data} SQLiPy 1341-1476行
if self._jCheckTO.isSelected(): textonly = ' --text-only' textonlystatus = True else: textonlystatus = False if self._jCheckHPP.isSelected(): hpp = ' --hpp' hppstatus = True else: hppstatus = False if self._jCheckCU.isSelected(): cu = ' --current-user' custatus = True else: custatus = False if self._jCheckDB.isSelected(): cdb = ' --current-db' cdbstatus = True else: cdbstatus = Fal
{这儿只列举其中的几行,可以看到,每一个在插件UI上的设置都会转变成一个对应的指令,例如Current DB这个勾选项在代码中就是sqlmapapi中就是'getCurrentDb': cdbstatus} Current DB
cdbstatus = True 'getCurrentDb': cdbstatus
{继续观察的话你可以很轻易的发现出api中非常多的操作都是getXXX作为开头,这些实际上就是sqlmapapi提供的对应着sqlmap命令的接口,如getCurrentDb就是获取当前数据库,getDBs就是上面的--dbs命令,getTables就是--tables命令} 操作接口 {我们手动发出一条--current-dbs和--dbs命令对应的请求,看一下构造与回显示便能发现sqlmapiapi确实返回了我们想要的结果,那是不是我们把所有的操作都设置为True就行了?} 请求构造
curl -H "Content-Type: application/json" http://127.0.0.1:8775/scan/‹taskid›/start -X POST -d '{ "url" : "http://127.0.0.1/login/login.php?id=2016","getDbs":"True","getCurrentDb":"True"}
回显示

{ "status": 1, "type": 12, "value":
}

限制

{记得在sqlmap中使用--tables之前,会先加一个-D的参数,这个参数的作用是指定要查询的数据库,联合起来的意思就是列出指定数据库的所有表名,那如果不加这个-D参数会是什么后果呢?这个可以自己尝试下,sqlmap会把所有能够探查到的库的表名全部都给查询出来,这样的造成的后果就是浪费时间而且输出的结果可能非常庞大。那么同样的道理,针对sqlmapapi的设限也是非常有必要的} 指定库
curl -H "Content-Type: application/json" http://127.0.0.1:8775/scan/‹taskid›/start -X POST -d '{ "url" : "http://127.0.0.1/login/login.php?id=2016","getTables":"True","db":"vulcms"}'
{这样的操作是不是十分有既视感?设置db为vulcms,再设置getTbles操作为True,正好对应了命令的-D vulcms --tables,我们看一下输出结果,也正是所预料的一样,没有把所有的库的表名给输出出来而是仅仅只输出了vulcms这个库的表名} 输出结果

{ "status": 1, "type": 13, "value": { "vulcms":
} }

结语 {至此一个完整的操作就结束了,后面的列表列数据完全就是参照上述的方式,找到对应的api即可,对于一个sqlmapapi的自动化测试工具开发来说熟悉其API是必要的一步,因为在一定程度上sqlmapapi才是工具的逻辑引擎,而二次开发的工具其实仅仅只是负责了交互部分而已,就如同sqlipy一样,你很难说它是一个非常有技术含量的插件,但是在某种程度上,它却是一个非常有价值的插件。}

burpsuite与sqlmap的联动(三)


http://static-v.zhishibox.net/2021227_qiniu_c3ca859c5db0d282e58b5c82a6d967a2.mp4
{先前已经认识了sqlmap的使用以及SQLiPy这个插件的使用,针对burpsuite与sqlmap的联动已经有了一个了解,但是在开发上这样的联动是如何实现的呢?这就得说一下sqlmapapi.py这个文件了。} 联动核心:

sqlmapapi.py

{sqlmapapi是一个python的Web微框架,但却也不能算是服务框架,应该算是中转框架,因为其作用就是负责处理各种请求,然后调用sqlmap.py执行相应的命令返回相关的信息,也就是说针对sql的测试逻辑其实还是在sqlmap.py中实现的,这部分并不用看,直接看sqllipy的运行机制}

SQLiPy的运行

{因为SQLiPy本身实现了一个UI界面,所以代码中包含了大量的图形绘制,并获取用户的输入存入变量之中。而针对用户的输入,实际上是构造了一个个请求。}

StartScan创建task


req = urllib2.Request('http://' + self._jTextFieldScanIPListen.getText() + ':' + self._jTextFieldScanPortListen.getText() + '/task/new')
{插件中IPListen和PortListen分别是在插件UI上填写的数据,获取后拼接成一个完整的API请求,以此请求sqlmapapi服务来获取到一个taskid,即新建一个扫描项目,以先前的数据为例。} 构造的请求
http://127.0.0.1:8775/task/new
{这是sqlmapapi的一个API规则,即构造一个task,因为利用sqlmapapi进行的扫描每一个任务都以一个task为单元,后续的操作都是针对该task的操作,构造如此请求后,即可从Server获取到一个taskid,这就是一个task标识,然后保存为sqlitask = resp
,看一下界面上的显示辅助理解。} 保存taskid
sqlitask = resp

任务属性设置

{sqlmapapi针对一个task进行扫描前得预先设置这个task的属性,这都是sqlmapapi预先定义好的也就是之后的逻辑处理依据,即根据设置的属性调用sqlmap产生相应的行为。一个任务的属性可以通过构造/option/taskid/list查看,其中每一个属性都有自己的默认状态。}
curl http://127.0.0.1:8775/option/‹taskid›/list
其中着重关注的选项是:
url data cookie

三者对应的分别是sqlmap的-u,--data,--cookie参数

{插件通过读取用户在界面上的输入,然后填充成一个完整的json数据,接着post到server上即可修改其中的某些属性}
sqliopts = {'authType': authtype, 'csrfUrl': csrfurl, 'csrfToken': csrftoken, 'getUsers': lusersstatus, 'getPasswordHashes': lpswdsstatus, 'delay': self._jComboDelay.getSelectedItem(), 'isDba': isdbastatus, 'risk': self._jComboRisk.getSelectedItem(), 'getCurrentUser': custatus, 'getRoles': lrolesstatus, 'getPrivileges': lprivsstatus, 'testParameter': paramdata, 'timeout': self._jComboTimeout.getSelectedItem(), 'torPort': torport, 'level': self._jComboLevel.getSelectedItem(), 'getCurrentDb': cdbstatus, 'answers': 'crack=N,dict=N', 'method': httpmethod, 'cookie': cookiedata, 'proxy': proxy, 'os': os, 'threads': self._jComboThreads.getSelectedItem(), 'url': self._jTextFieldURL.getText(), 'getDbs': ldbsstatus, 'tor': torstatus, 'torType': tortype, 'referer': refererdata, 'retries': self._jComboRetry.getSelectedItem(), 'headers': custheaderdata, 'authCred': authcred, 'timeSec': self._jComboTimeSec.getSelectedItem(), 'getHostname': hostnamestatus, 'agent': uadata, 'dbms': dbms, 'tamper': tamperdata, 'hpp': hppstatus, 'getBanner': 'true', 'data': postdata, 'textOnly': textonlystatus}
{插件支持的修改项非常多,为了方便理解,我就手动复现一下api的使用。} API地址
http://127.0.0.1:8775/option/‹taskid›/set
{要注意的是发送的POST数据为json格式,当返回值为true时,说明修改正确。尝试修改agent的值为twosecurity,此刻的值如图,为一个标准的UA头} 构造数据
{ "agent" : "twosecurity" }
发送请求
curl -H "Content-Type: application/json" http://127.0.0.1:8775/option/‹taskid›/set -X POST -d '{ "agent" : "twosecurity" }'
{此时再list属性时便可以看到agent的值已经变了}

发起扫描


http://127.0.0.1:8775/scan/‹taskid›/start
直接看插件的源码:
req = urllib2.Request('http://' + self._jTextFieldScanIPListen.getText() + ':' + self._jTextFieldScanPortListen.getText() + '/scan/' + sqlitask + '/start') req.add_header('Content-Type', 'application/json') resp = json.load(urllib2.urlopen(req, json.dumps(sqliopts), timeout=10))
{发起POST请求后,server端便可以开始扫描了,不过这时候还是得提供值,任意一条属性即可,不过建议就是把之前构造的完整的属性值给传输过去就行。返回值是"success": true 便是代表没有问题。至此一段简单的调用sqlmapapi针对sql检测的就完结了。可以通过/log看一下情况。}

查看扫描情况


curl http://127.0.0.1:8775/scan/‹taskid›/log
{这儿的信息是不是非常的眼熟,因为这正好对应了sqlmap -u参数对应的检测结果,也就是说至此为止插件完成了sqlmap的第一个步骤。}

结语

{这是一个针对sqlmapapi调用的实例,从这个例子中我们能够学会如何通过自写的脚本去调用sqlmap进行自动化检测,但也目前也只是第一步而已,后面将会涉及到关于sqlmapapi更细化的调用学习,以此帮助各位打磨出属于自己的sqlmap利用工具。}

burpsuite与sqlmap的联动(二)


http://static-v.zhishibox.net/2021227_qiniu_2f559cb082898c530f6267c2ba2da66f.mp4
{Burpsuite与sqlmap可谓是web安全测试中的两大神器,那么作为一个安全测试人员是如何将二者联动使用的呢?要知道在burpsuite中测试的是整个http请求,因此注入点是有可能出现在任何一个地方的,get参数,cookie的值,user-agent值,或者是表单提交的值中。在这种需求下,sqlipy这个工具就能很好的解决上述的问题。} {以一个post请求为例子,分别展示传统手段与插件的方式针对一个sql注入作利用}

传统手段

{我们可以看到图中,参数名为id的地方存在一个post注入,在这种的情况下,最初sqlmap的使用应该是使用--data将指定参数测试的值POST发送}

--data sqlmap -u http://victim.com/login/login.php --data='id=2016'

{但是这儿就遇到了很多问题,就这--data仅仅是按照POST方式提交参数值而已,那如果是有权限认证呢?有新的http头呢?有特殊的格式呢比如json怎么的,这样的话sqlmap的就得一一去设置,十分的麻烦,因此传统手段下大多使用的是-r参数}

-r sqlmap -r /home/lang/Desktop/1.txt

1.txt中保存的是从burpsuite中保存的http请求 点击copty to file保存整个请求 {-r参数是最传统意义上burpsuite与sqlmap的联动方式,利用此参数,sqlmap加载并解析指定的文件内容,然后以文件中的目标与请求进行测试,十分的高效快捷}
http://static-v.zhishibox.net/2021226_qiniu_925225460883ddbc7c8535c604e004ab.mp4
SQLiPy {这是一款burpsuite中专门与sqlmap联动的插件,与-r参数不同,作为buresuite的模块,sqlipy能够自由调用burpsuite的资源,例如扫描线程,例如ISSUE展示,例如消息推送,因此测试人员针对多个点的sql注入无需多次保存文件,而是直接在框体中选取SQLiPy Scan即可进行检测。} 安装
https://github.com/codewatchorg/sqlipy
在BApps中直接安装即可,不过因为是python写的,所以要准备Jython环境。 使用 {与XssValiditor类似,sqlipy也需要提供一个检测服务,既然是与sqlmap联动,那此服务的功能当然是sqlmap,其实当你安装此插件时,插件会自动下载一份给定的sqlmap作为使用并定义好相关路径而无需测试者自己下载。}

启动sqlmapapi.py 因为我本身python环境的问题,默认环境是python3,因此我选择利用手动方式启动,如果默认环境是python2的话,可以通过插件启动。


python sqlmapapi.py -s
填写监听地址与端口

服务启动会返回一条信息,包含了服务地址




Running REST-JSON API server at '127.0.0.1:8775'..
选取要检测请求,设置规则

右键请求,然后选择SQLiPy Scan即可将请求送入插件当中

{上面显示没有启动是因为只有是通过插件启动的sqlmapapi服务才会有状态变化,我们手动开启的因此可以无视掉,Method选择默认,插件会根据送入的请求作判断,而下面的各种参数不懂的情况下选择默认即可,level和risk参照sqlmap的规则,而操作的话默认没有,这儿就选择一个List DBs,也就是列库的选项,再下面设置的是线程数和超时等,看自己的需求来,后面如果没有代理的话,就没有什么可以设置的,直接点击Start Scan} 结果 {首先看一下sqlmapapi之中,当出现Retrieved scan status便已经代表产生结果了} {此时Burpsuite的Issue中则会展示出界面化的结果} SQLMap Scan Finding List DBs的结果

结语

{相比于单纯的sqlmap或者是burpsuite测试,sqlipy明显更加友好,且在界面的展示上更加人性化,而插件界面的各种选项则是图像化了sqlmap的参数,相较于单纯的sqlmap,又是简化了不少,十分利于新手学习与老手简化测试。}
{作为OWASP TOP10排名首位的漏洞,sql注入自98年以来,一直困扰着开发人员,不断的对网络安全造成威胁。前面的视频与教程中都有关于sql注入的讲解,因此在这就不过多赘述。若说起sql注入,自然应当想到针对sql注入最著名的安全软件--sqlmap}
http://static-v.zhishibox.net/2021227_qiniu_ef50a9db6b5239f7b1c3d1923752f8ce.mp4

Sqlmap

{sqlmap是python写出来的一个跨平台自动化sql注入渗透工具,其中还包含了指纹检测,字典爆破等功能,其本身提供了大量测试的payload,并且有一套完善的拼接方式,因此极大的便利了安全人员,从繁琐的手工测试中解脱出来。本次视频将详细讲解如下三个问题}
新手如何使用sqlmap 如何将burpsuite与sqlmap配合使用 sqlipy的运行机制

新手学sqlmap

安装:


http://sqlmap.org/
{因为win的命令行不好看,所以默认为linux讲解,从官网下载sqlmap的源码或是git拉取源码,接着需要本地提供能够运行的python2.7环境,当一切准备好后,直接在sqlmap的根目录下执行sqlmap.py文件,若出现如图内容,则说明运行没问题}
$git clone --depth 1 https://github.com/sqlmapproject/sqlmap.git sqlmap-dev //git方式下载sqlmap $cd sqlmap-dev $python2 sqlmap.py

使用:

{作为一款知名安全测试工具,sqlmap实际上在各种linux发行版下都有相应的软件包支持,甚至在某些发行版,例如BT5,kali下是默认安装的工具,可以直接通过命令行下执行sqlmap使用} $sqlmap {新手学习sql注入时候,就像之前课件中说的一样,通过简单的单引号就可以判断出是否有注入,因为非常多的网站实际上是没有关闭数据库报错的,凭借页面的报错信息,就能很轻而易举的判断注入,构造攻击payload达成目的} Mysql数据库的典型报错

You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''2016''' at line 1

Burpsuite也能轻易发现这种类型的sql注入 {上图中的高亮部分就是Burpsuite对于此种sql注入的判断依据,但是呢,之前说的构造攻击payload其实对于新手来说并不是十分友好,先不说数据库的类型不同导致注入的语句并非一致,需要攻击者掌握大量的sql语句知识与数据库知识,单单只是mysql一种数据库,手工注入的过程便已经十分繁琐,从判断表名,列名到最后的读取指定数据,中途要经过多种语句的变换,更别说倘若有些许waf,就需要测试者不断探测规则,从而达成绕过。而使用sqlmap无疑是一个攻击捷径,sqlmap自身携带的大量逻辑语句使得攻击者仅仅需要记住几个指令,便可以将一个注入点利用起来。} 典型的sql注入点
http://victim.com/login/login.php?id=2016
{假设在上述的URL中已经发现了sql注入,现在就来看下在sqlmap中如何利用} 在sqlmap中确认注入点

-u参数可以理解为url,即针对指定的url进行测试


$sqlmap -u http://victim.com/login/login.php?id=2016
{当出现parameter 'id' is vulnerable.这样的提示时候,就说明已经判断出有漏洞了,这儿选择直接回车,也就是不再继续测试其他的了,最后会输出详细的服务信息并提供给我们sqlmap的测试payload}
$sqlmap -u http://victim.com/login/login.php?id=2016 --dbs
因为是mysql的数据库,就直接在后面提供--dbs的参数,意思是注入出所有的库名 $sqlmap -u http://victim.com/login/login.php?id=2016 -D test --tables

这儿有个小技巧,就是sqlmap中,一个-加一个大写字母大部分是指定,即指定某个库啊,某个表什么的,且往往是英文字母的开头,比如-D就是指定的名为test的库,而两个-加英文单词,则往往是某种操作,比如这儿的--tables意思为列出所有的表名


$sqlmap -u http://victim.com/login/login.php?id=2016 -D test -T sales --columns
意思同上,而--columns则是列出列信息
$sqlmap -u http://victim.com/login/login.php?id=2016 -D test -T sales -C product --dump
--dump因为是双-所以是个操作,实际含义就是导出这个列的数据,而这往往就是一个sql注入的最后一步,获取到最后的信息。 {以上就是sqlmap针对一个注入点的全部攻击流程,从获取库名,获取表名,获取列名,获取列数据层层递进,而测试者需要了解的仅仅是相关的指令,而非繁琐冗长的sql攻击语句} sql测试语句
id=-9261' UNION ALL SELECT NULL,CONCAT(0x7178787071,0x5658744f4b53704b70436669744f6267646c7a4d6a7342416b447a45694e746176645a5863435a49,0x7162717071),NULL,NULL#
数据库层级结构

库 表 列 数据 //攻击者真正想要的

使用sqlmap时建议加上-v的参数,能够学习到发包详情

结语

{作为一款sql注入的测试工具,sqlmap的地位无疑是十分崇高的,这是安全人员精心打磨制作出来的安全测试产品,初学者并不应该说因为怕丢面子而故意避开工具的使用,脚本小子是一种学习状态,是沉迷于工具而不知进取,而从一款好的安全产品中学习到其中的思想,技术反而才是真正的新手学习方式,本节课学习的是利用sqlmap实现的全自动化的sql注入测试,下节课则学习测试人员利用burpsuite与sqlmap相结合的半自动化测试。}

software-vulnerability-scanner:SCAP合规(二)


http://static-v.zhishibox.net/2021227_qiniu_a28b28983fabf69e619260a6e0b8a68f.mp4
{随着技术的发展,计算机上越来越多的安全问题被暴露出来,但这些问题却并不一定是代码层的问题,还有可能来源于配置,因此在这情况下,一个安全自动化协 @议,即SCAP即被提了出来,并逐渐成了全球标准,当然我们熟知的CVE,也是其中的一个组件。} SCAP的三大构成:
列举 CCE CPE CVE 评分 CVSS 表述与检查 XCCDF OVAL
{对于非企业级运维来说,普通的安全从业者只需要知道CPE,CVE,CVSS与OVAL即可,而其中CPE与CVE还存在一个包含关系,因此实际上来说,需要学习的正好就涵盖了三大构成,也就能够初步对一个对象进行安全检测了,而software-vulnerability-scanner这个插件则是在一定程度上实现了自动化的检测,因为其大部分功能的实现都是依赖的CPE。}

CPE

{CPE是一个针对系统,软件,硬件的标准命名规范,通俗来说,就可以简单理解为针对某一个软件/硬件/系统的正式描述} CPE语法:
cpe:/{part}:{vendor}:{product}:{version}:{update}:{edition}:{language}
以tomcat:5.5.31为例:
2.3: cpe:2.3:a:apache:tomcat:5.5.31:*:*:*:*:*:*:* 2.2: cpe:/a:apache:tomcat:5.5.31
其详细的描述为: {而通过这样的一个描述,我们能够在NVD(美国国家标准与技术研究院)中查询到这一个CPE下包含的所有的CVE信息,为什么要是NVD呢,因为那是目前这个星球上最规范全面的一个标准库。对于CPE这样说可能有些不太能理解,再简单点说,我们知道了要检查的对象是一个5.5.31版本的tomcat,通过CPE就能知道这个版本有哪些漏洞了。}

插件运行

{回过来看插件,插件首先提供了一个正则,用于提取响应头中的版本信息,当提取到信息后,则构成一个查询的URL,实际上内部逻辑还是组成了一条CPE规则,接着按照相应的规则将早已存入数据库中的NVD的信息提取出来,然后做处理后输出到ISSUE当中,告诉测试者对应的软件版本包含了哪些漏洞。} tomat: 版本拼接: 假设提取到5.5.31,插件查询的地址: https://vulners.com/api/v3/burp/software/?software=cpe%3A%2Fa%3Aapache%3Atomcat&version=5.5.31&type=cpe 实际对应的: cpe:/a:apache:tomcat:5.5.31 检测的核心: 指纹识别 {插件检测的核心在于正则是否能有效的识别出是什么软件,什么版本,这样才能调用相应的CPE规则进行合规查询,因此强大的指纹识别功能是必不可少的,而插件的指纹识别的实现原理也只是强特征检测,即某个一定会出现的特征配合上某些规则来作检测,实际上这并不是一个优秀的方案,因为就像上文所说的,对象的环境多种多样,因此有极大的可能会出现超出意料之外的特征从而导致指纹失效,这样的话无法确定指纹也就无法找出合适的CPE规则,更不用说输出安全问题了。}

意义

{版本检测意义在哪儿呢?当某一个版本的软件出现了问题,官方往往会发布两种解决方法,一种是临时的修复方式,即更改某些配置,或者是手动修改某些代码,第二种是升级解决,在新的版本中把上个版本的问题解决掉。而对于使用者来说,真正去修复往往是采用第二种方式,而不是冒着风险采用临时修复建议,因为这样很有可能发生为了修复一个BUG产生更多BUG的情况,大部分的企业都是如此,那么在软件更新新版本前,就有极大的可能出现真空期,从而出现大量安全问题,而安全合规检测就是要把这些安全问题都给暴露出来,从而提醒到运维人员漏洞的存在,再让其自身决定是否修复。}
临时修复,更改配置 升级版本

一款好的合规安全产品:


强大的指纹识别功能 完善的规则库 人性化的交互
{完善的规则库已经有了NVD作支持,因此安全测试人员需要考虑的仅仅只有如何去识别,而做安全产品开发的人则是在尽可能的实现自动化识别的基础上,再去思考人性化的交互,能够快捷高效的向运维人员展示出存在的安全问题。}

总结

{这个插件本身并非是一个多么好的安全产品,但是作为一个合规类检测的产品来说,的确是一个值得研究的demo,学习其内在的运行逻辑与安全思想,对打磨出属于自己的合规检测产品或是学习到一种安全检测维度提供了一定的帮助。}

software-vulnerability-scanner:SCAP合规(一)


http://static-v.zhishibox.net/2021227_qiniu_ee5900047de446f255e375b71f67ca20.mp4
合规检测一直是企业安全管理中非常重要的一环,而其中针对所有资产的梳理调研存在着周期长,人力成本高等各种问题,这是因为SCAP标准复杂庞大,若没有自动化工具的帮忙,仅凭人力很难将各种信息梳理出来,因此为了解决这个问题,有非常多的安全团队都提供了相关的漏洞数据库并提供了使用接口,其中本次要讲到的software-vulnerability-scanner,就是由Wallarm团队开发的一款Burpsuite插件
插件地址|https://github.com/vankyver/burp-vulners-scanner


|https://github.com/PortSwigger/software-vulnerability-scanner
二者代码没什么区别,就是一个挂在官方名下的分支代码而已,随便哪个都可以用。

安装的两种方式

BApp直接安装 这种方式最为简单,安装即用 jar包安装

系统环境:java 1.7+,Maven Maven是一个项目管理工具,通过一个基本单元(项目对象模型 pom.xml)中声明的结构与内容,自动化构建出整个项目。

因为这个插件提供了pom.xml,因此可以直接通过Maven打包,而非是先前介绍的那样麻烦的编译。 git clone https://github.com/PortSwigger/software-vulnerability-scanner.git mvn package /target/burp-vulners-scanner-1.1-shaded.jar 当出现BUILD SUCCESS时,说明打包成功,然后会在target目录下生成一个定义好文件名的jar包,接着直接导入到Burpsuite中便可。

使用


http://156.67.219.128:2001/login

这是在zoomeye上找的一个网站,测试样例可自己寻找,但请勿对他人网站进行攻击

首先得知道这个插件的用途,这个插件的作用是通过vulners.com的API来对指定版本的应用软件进行查询,输出这个版本中所携带的安全问题,通俗点来说就是版本检测。而版本呢,则是插件通过写好的正则来匹配。 Regex便是正则,以样例网站为例: 响应内容为:
HTTP/1.1 200 OK Server: nginx/1.10.2 Content-Type: text/html; charset=UTF-8 Connection: close X-Powered-By: PHP/7.2.9 Cache-Control: no-cache, private Date: Wed, 02 Jan 2019 08:06:44 GMT Set-Cookie: XSRF-TOKEN=eyJpdiI6IjU1RmZqakpCcTBZMWhFYW8xWDJBXC9BPT0iLCJ2YWx1ZSI6ImNvSXdidmFMbzh0QmRjQk1SQWE1UXRQY2ZrdUd3RHcwK01qOW0rYk1vMVwvQ0V4T1QzTVwvcGpKTG9kZFFkbWtKeSIsIm1hYyI6IjA3ZDUzODBmY2E4YWE2NjI0YTAzNGE5NTgxNWFjMGQ3NmQxMzI5ZjI5ZDc1MThhMDQyM2NiODhjZDY1OGQ5NGEifQ%3D%3D; expires=Wed, 02-Jan-2019 10:06:44 GMT; Max-Age=7200; path=/ Set-Cookie: laravel_session=eyJpdiI6IlNSbzdUTUdKVklqVnBWOWZkVE85Ymc9PSIsInZhbHVlIjoib1NvdXNyNkZwNHJNdzMwREFtN3VtMTZFK2tFM3JTV2VwNlJMVVVuUUpKNjM1ckJuZ0NUcGpsWjJOYWFWSjVOOSIsIm1hYyI6IjgxNDQ4ZmJiNmY3MWNjZjNkNzBjZTZiZDJkYmI3MzM1NTk2NWFlNGZlMmY2MDIyMzBiYWI4Y2Y0YzA3MjNiZmQifQ%3D%3D; expires=Wed, 02-Jan-2019 10:06:44 GMT; Max-Age=7200; path=/; httponly Content-Length: 5613
识别出来的东西为:

Nginx/1.10.2 php/7.2.9 Igor nginx/1.10.2

版本的识别对应来源于:

Server:\s*nginx(?:/(
+))? PHP/(
+
+(?:
+)?)|Server:\s*php/?(
+)?|X-Powered-By:\s*php/?(
+)? nginx/(
+)

然后查看到插件的页面,可以看到相关的识别信息,但是插件UI下的展示有问题,得刷新下才能出来,正则写的也是有问题的,其实仔细看了https://vulners.com/api/v3/burp/rules中的正则,很多都有问题,但是考虑到仅仅是开源插件而非商业软件,因此也并非不能接受,无非就是自己修改的问题,插件在Rules URL设置成可设置模式,应该是早已想到了这个情况,所以并没有把默认规则设置的多么合理。 插件会把识别出的version作一个拼接,然后去查询相关的结果:
start check for domain 156.67.219.128 for software PHP, headers/7.2.9 : https://vulners.com/api/v3/burp/software/?software=cpe%3A%2Fa%3Aphp%3Aphp&version=7.2.9&type=cpe 比如这儿的 https://vulners.com/api/v3/burp/software/?software=cpe%3A%2Fa%3Aphp%3Aphp&version=7.2.9&type=cpe 这儿是一个CPE结果,最终会被展示到ISSUE里,并展示相关漏洞,漏洞来源 这儿展示上也一直出问题,简直要崩溃了,插件的UI上已经检测到了相关漏洞,就是不在ISSUE上展示,但是实际上是能展示的,显示的结果就是有哪些CVE,然后来源是由于php/7.2.9的版本。 具体的流程就是:
安装插件 访问网站 Passive Scan自动匹配version,获取远程API的结果 ISSUE展示结果

其中因为默认的rules是国外的,因此提供了一个proxy接口,可以代理访问,否则如果没有访问到的话,结果就是空,因此个人推荐上对于rules这个页面,在本地搭建一个其实更为有效方便

这个插件和先前的插件比起来,在一定程度上来说,实用性非常的低,甚至可以说是粗糙,但是为什么要单独来说呢?因为这个插件是一个合规学习的非常好的切入点,虽然功能上有些差,但是在思想上确实是一个非常规范的实现,这也就为后面的学习打下了基础,就比如说先前出现的一些名词,后面都将得到解释。

疑问

CPE vulners.com SCAP

J2EEScan:初识DAST(三)


http://static-v.zhishibox.net/2021227_qiniu_4466bdddfc9dd52d5b0b520423f00eea.mp4
针对一个扫描插件来说,从源码角度去分析插件的运行机制是十分有必要的,因为直接接触到了源码,明白扫描逻辑,才能更好的去主动触发相应的扫描模块,提高扫描效率。 以Struts2 s2-032漏洞为例,将源码与Burpsuite实例作结合剖析: 测试环境:
https://github.com/Medicean/VulApps/tree/master/s/struts2/s2-032
插件源码:
https://github.com/ilmila/J2EEScan/blob/master/src/main/java/burp/j2ee/issues/impl/ApacheStrutsS2032.java

源码与实现

作为一个安全人员,应该清楚安全工具是如何替代人工进行DAST的,因为这决定了你是否能够对工具的结果做出正确的分析与判断,同样的,当逐渐熟悉自动化DAST的代码逻辑,培养出安全开发思维,安全人员也就能够写出自己的DAST工具了 漏洞详情: 请求何处来? 作为使用者,我们当然知道,这样的一个请求并不是我们手动发起,而是Burpsuite的插件自己构造的,那这样的构造需要什么条件吗?或者说什么情况下插件会构造出怎么样的一个请求呢? 源码73-75:
rawrequest = callbacks.getHelpers().addParameter(rawrequest,callbacks.getHelpers().buildParameter("method:", "%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(%23parameters.hook
)%2c%23kzxs.print(new%20java.lang.Integer(829%2b9))%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString", IParameter.PARAM_URL)); addParameter(request,parameter):为request添加一个新的参数 buildParameter(name,value,type):构造一个新的参数,类型为type
上面这个代码的大致意思就是,构造一个新的URL参数,名字为method:,值为payload,然后把这个参数添到请求中去 ?method:=payload modifiedRawRequest = utf8rawRequest.replaceFirst("=", "").getBytes(); //去掉= 源码84-86:
modifiedRawRequest = callbacks.getHelpers().addParameter(modifiedRawRequest,callbacks.getHelpers().buildParamter("hook","HOOK_VAL",IParameter.PARAM_URL));
与上述的代码相同,也是添加了一个新的参数,名字是hook,值是HOOK_VAL,这儿不用在意为什么请求信息从rawrequest变成了modifiedRawRequest,因为中间做了一个转字符串,去掉=的操作,变量名是任意定的

rawrequest --› utf8rawRequest --› modifiedRawRequest

因此此时请求的参数变成了:

?method:payload&hook=HOOK_VAL

至此,完成携带payload的请求的构造,再看判断。 源码45:
private static final Pattern DYNAMIC_METHOD_INVOCATION = Pattern.compile("HOOK_VAL838",Pattern.DOTALL | Pattern.MULTILINE);
源码95:
Matcher matcher = DYNAMIC_METHOD_INVOCATION.matcher(response);
源码97:
if (matcher.find()) {
HOOK_VAL838为检查项目 这儿也很好理解,就是提前定义了一个检查项目值为HOOK_VAL838,然后查找响应中是否出现了这个值,如果出现了,则输出漏洞信息 流程:
定义检查项 构造请求 接收响应 判断响应中是否有检查项 输出漏洞信息
如上便是一个DAST插件的基础实现,这个和手工测试的流程基本一致,针对大部分漏洞来说,安全人员一样也是构造请求,然后判断回显从而确定漏洞 总结 DAST技术的核心就是安全人员对HTTP请求作分析和处理,而使用了J2EEScan的Burpsuite在一定程度上成为了一个针对J2EE应用的自动化DAST工具,插件本身能够对每一个录入的请求做自动化测试,这极大的减少了安全人员的测试成本,告别了曾经对每一个接口发送大量payload这种重复的工作模式,可以说,J2EEScan能够让一个技术并非十分高明的测试者也能轻松发现/挖掘J2EE web应用中的高危漏洞

J2EEScan:初识DAST(二)

应用安全的检测方法,目前常用的有四种:
http://static-v.zhishibox.net/2021227_qiniu_77dc37534c4aad309ce10006f917c513.mp4

SAST DAST IAST RASP
{分别是静态安全测试,俗称白盒检测;动态安全检测,俗称的黑盒测试;交互式安全测试,一般是针对字节码的灰盒检测;最后就是在运行中根据上下文实时识别的技术,不过RASP比较偏向于waf类的技术}

针对web的黑盒测试

{安全人员针对web的黑盒测试核心还是对于http请求响应的分析与构造,很多漏洞只有在构造了特殊的请求后,才能被发现,例如sql,xss这些,而又比如CSRF,越权这样的漏洞,则只要针对请求/响应进行合理的分析和测试,即可判断是否有漏洞}
原始HTTP请求/响应的分析 构造恶意请求
为何不直接用扫描器呢?这就要说一下传统扫描器的实现
资产导入 资产发现 资产识别 构造请求 判断响应 判断漏洞
{传统扫描器的实现主要流程是资产导入-资产发现-资产识别-构造请求-判断响应-判断漏洞,这是一种十分传统的过程,优势是自动化,而且因为爬虫功能能发现大量安全人员未接触的页面,而指纹的存在则更是帮助安全人员快速识别出web信息,但是同样的,传统扫描器的劣势也十分明显,比如逻辑漏洞的检测,权限内页面的检测,这些都是传统扫描器一直难以绕过的一个坎,实现起来非常困难} Burpsuite的核心功能是针对HTTP消息的处理,而这个处理包括:
拦截 修改 重放
然后平台还自带:
爬虫 编码/解码 对比
在这个基础上,自然而然的就会有安全模块的实现:
Intruder

J2EEScan的实现

之前说过J2EEScan因为调用了scanapi和issueapi所以无需自己画界面出来,但是还有一点就是,因为调用了scanapi,因此它可以直接对扫描队列中的请求进行测试。 {用一个struts2环境测试,可以看到请求历史中只有两个请求,但是在target模块中,却显示一个我们不曾访问到的页面,default.action页面,而灰色表示,说明我们还没访问过,这个是爬虫发现的请求} 灰色表示的default.action 访问后变色 扫描后的结果: {可以很明显的看到,J2EEScan在default.action这个请求基础上重新构建了一个全新的请求,在请求中添加了payload,然后针对response作对应的判断来判断漏洞是否存在,这儿就出现了一个非常明显的问题,就是基础请求是否存在,爬虫虽然在一定程度能能够补全安全测试人员未访问到的页面,但是为了及时发现漏洞,测试人员还是应该尽可能多的向burpsuite中录入接口请求,便于测试}

扫描的核心: 基础请求存在


J2EEScan:初识DAST(一)

要知道J2EEScan是什么,怎么用,就先得知道J2EE是什么,J2EE用于企业级java应用开发的B/S开发架构,包含了诸如EJB,servlet等各种组件的运用,这样说可能有些抽象,那就说的实际点,J2EE就是一种提供了各种API的java环境 J2EEScan是扫描J2EE application的一款插件 常见的应用程序有诸如weblogic,tomcat之类的web应用,也有比如struts这种java框架,而J2EEScan则是帮助测试者发现实际环境中可能存在的漏洞

J2EE application: weblogic jboss struts tomcat jetty

插件可以通过BApp直接安装,也可以在官方github上下载后自己编译安装,不过这个插件在2017年以后就不再更新了,因此没有加入最新的java漏洞的检测,所以等以后学会写插件了,可以自己填入payload测试最新的漏洞 https://github.com/ilmila/J2EEScan

安装

{直接通过BApp安装即可,当插件的Output中输出如下内容,则说明安装成功,可以正常使用了,因为插件直接调用的ScanAPI和IssueAPI,因此不需要自己重新画界面出来,而是直接使用的Burpsuite原生的界面} 安装成功: 勾选使用 使用 J2EEScan支持扫描的漏洞很多,如多种配置文件/系统文件的文件包含漏洞,s2系列的漏洞,虽然只更新到了021,也有jboss的远程命令执行漏洞,weblogic/tomcat等应用的弱口令检测,可惜没有weblogic的RCE检测,这个最近几年非常火 J2EEScan支持的漏洞:

只写几个 JBoss SEAM 远程命令执行 (CVE-2010-1871) Apache Struts 2 S2-021 Tomcat 管理器控制台弱口令 Weblogic 管理控制台弱口令 本地文件包含 - weblogic.xml HTTP 验证弱口令 ......

burpsuite 2.0以前的版本只需要直接选取要检测的站点,右键点击Actively scan this host,将站点添加入主动扫描队列即可 burpsuite 2.0以后则需要站点先添加入scope中,通过Dashboard创建单独的扫描队列 点击Add to scope 创建新的Scan,扫描并审计 等待扫描完成

J2EEScan也有调用被动扫描模块,不过其中支持的多数漏洞都是需要构造新的请求,也就是利用的主动扫描方式

不管是2.0以前还是以后,漏洞的详情都是以J2EEScan开头的,这是因为这是插件本身定义的输出,和Burpsuite自身无关,在扫描过程之中,Burpsuite会利用爬虫主动爬取到新的请求链接,但是仍需要测试者尽可能多的点击页面发起请求,将各种API接口或是请求录入Burpsuite当中,添加入扫描队列待检测,而这种测试方式也就是一种自动化的DAST,即针对应用程序的动态安全分析方法

SAST DAST IAST


XssValidator:动态渲染测试XSS(二)

就像第一章所说的,现在的网站交互性越来越多,只有依靠动态检测的方案才能有效的检测出层出不穷的xss,既然是动态检测,那必然是需要一个浏览器的,因此在这个需求上,phantomjs成了一个很好的选择。
PhantomJS: 无界面webkit解析器
说到底XSS就是用户的输入被带入页面解析,造成了JS代码的执行,这一切的操作在浏览器中都是能够被查看/监控到的

XSS的来源有: URL cookie 表单 headers .......

输入来源复杂,因此以编程的方式模拟页面解析来验证XSS是否存在,是非常典型的一种动态检测方式,而phantomJS提供了很多的监控和脚本触发接口,非常方便安全人员通过一定的编程规则针对各个输入源作自动化测试。

phantomJS检测原理

被动扫描VS插件fuzz 以xssValidator提供的代码为例:
https://github.com/nVisium/xssValidator/blob/master/examples/dom-xss.php
图中所展示的就是burpsuite的被动扫描结果,确定了在dom-xss.php页面存在一个DOMxss,而判断的标准就是高亮显示的部分 静态检测逻辑:
Data is read from document.URL and passed to document.write() via the following statement:
就是说,数据直接从document.URL中获取并被传输到了document.write()中,这便会导致一个dom型的XSS,同时我们可以看到,还有一个动态检测的tab 并没有构造新的请求 这个动态检测并没有去构造出一个新的请求出来,而是一个动态测试方式的罗列,最终给出一个可用的payload出来,这儿给的信息比较详细,但是问题就在于,这依然只是被动扫描的预定义,只是编写者在臆想合理的场景,然后尝试提供一个可能解法,而非提供一个实际解法

phantomjs的解法

phantomjs的劣势在于,测试者需要手动去设置需要检查的项目,这就代表了需要测试者针对漏洞有一定的敏感程度,知道某种请求/某个参数最可能会存在XSS,而优势在于phantomjs省略了大量尝试payload然后观察页面解析的步骤,即模拟解析,然后为符合规则的payload打上标记

手动配置检查项目 手动fuzz变为自动化fuzz

那么检测规则到底如何呢? 这是一个例子,可以看到test123123便是打上的标记,携带这个标记的便表明存在XSS,而除了这个标记,便没有发现任何脏数据,那到底是如何动态解析的呢?
wp.onAlert = function(msg) console.log("On alert: " + msg); xss.value = 1; xss.msg += 'XSS found: alert(' + msg + ')'; };
针对alert形式XSS的处理 两张图一张是来自于phantom server,一张来自于插件output,而其中的on alert正好对应的代码中的console.log,而output的msg则对应的xss.msg,简单来说就是通过onAlert来判断是否有弹窗,如果有的话,则把xss.value设置成1,然后返回值,同时插件本身会对返回作一个判断,就是构造的值在解析后返回的页面中是否存在,即弹出的数据是否为定义的,当都满足时,则打上标记,确定为XSS漏洞。
xssResults = parsePage(pageResponse,pageUrl,headers);
这儿是针对与JS事件检测的处理逻辑函数,通过事件分发函数来运行,有兴趣可自行了解。 因此整个插件的顺序是:

intruder使用插件作为payload生成器 插件拦截intruder的消息,并由phantom server处理 xss.js针对server进行请求,处理消息,为可用payload的响应打上标记 intruder根据标记区分是否存在漏洞

总结

xssValidator对于脚本小子来说,在实际使用上其实并没有那么友好,因为payload的框架是使用者自定义的,因此这就要求了使用者必须具备一定的安全功底,能够根据薄弱点作闭合构造,然后才进行fuzz测试,找出正确可用的payload,但这不妨碍它成为一款优秀的安全插件,因为通过其学习到的检测理念是一种极为先进的手段。

xssValidator:动态渲染测试XSS(一)

现在的web漏洞挖掘里,XSS一直是一个出现频率非常高的漏洞类型,但是随着现在网站的交互越来越复杂,使得传统的检测手段变得极为尴尬,漏报极高,这是因为越来越多dom型的XSS的出现,而传统检测又仅仅是针对响应作判断,难以识别出来,那么针对这种情况该怎么办呢,那就需要用到动态检测的方式,也就是这次介绍的插件xssvalidator

三种检测方式

传统XSS检测: 发送payload,检测响应中是否存在检测的字符

Burpsuite检测: 被动扫描会简单判断响应中的脚本语义,判断是否为Domxss

xssvalidator: 动态验证,发送payload,判断是否执行了JS代码或创建新的dom节点

认识xssValidator

{xssValidator说是一个插件,不如说是一个intruder模块的代理或者说是api,能够帮助我们利用自动化动态检测方式验证xss是否存在,即使是DOM型xss也能检测出来,但是插件使用上稍显麻烦,需要多步骤的手动配置}

下载到使用

下载: BApps直接下载安装 可以看到插件界面有个Getting started选项,这个就是插件的使用说明,其中第二点说明了插件的使用要启用一个phantom服务,这也对应了下面的第一个框体phantomjs server setting。在插件使用前,先下载好phantomjs和xss.js,这两个才是检测的关键,二者结合负责了针对内容的动态解析和漏洞判断
http://phantomjs.org/download.html

https://github.com/nVisium/xssValidator/blob/master/xss-detector/xss.js
以linux为例: 下载后用phantomjs执行xss.js,建立phantom服务,负责接收处理intruder模块传输过来的数据 启动phantom服务
phantomjs xss.js
接着建立一个新的intruder tab: 这儿是十分繁琐的一个步骤,首先将一个要检测请求放入intruder模块中,然后给需要替换payload的地方打上添加标记,攻击类型看自己的需求设置,如果只是对单个点验证,默认即可 选取payload: 可以回看到插件界面,在右边那默认的32条数据就是payload的基础格式,上面也给了提示,javascript和eventhandler分别代表了方法和行为,这是为了方便安全人员自己添加规则 默认32个payload:

为了检测方便,只保留一个测试‹script›{JAVASCRIPT}‹/script›

intruder-payloads: payload type选择Extension-generated 接着下面的Extension-generated选择为xss validator payloads 至于payload processing是预处理器任意,选了不选都行 intruder-Options: Grep - Match勾选,然后把关键字填入 intruder-Options中选取match方式,把关键字填入,这儿的填写对照插件界面的Grep phrase,那边填写什么,这儿就填写什么,这是为了给payload打标记,命中的payload会被打上这个标记,从而告诉测试人员,哪些payload是有效的 至此针对一个请求测试intruder模块配置完了,再回来看插件界面的设置,着重关注的只有grep phrase,javascript function,javascript even handlers和payloads四个部分,分别代表了标记,payload中使用的方法,payload中使用的行为以及payload的主体框架 简单展示: 配置结束,点击intruder的start attack即可: 发送的详情可以在多个部分看到: phanton server: 请求主体 Extensions output: 检测详情: xssValidator是一个针对单个请求作测试的插件,主要的用途是针对可疑参数作批量的payload测试,而优点就在于动态解析的方式即使是DOM型的XSS也能有效地识别出来
账户系统的身份伪造讲解,SQL安全问题带来的时间盲注,前端限制控件的绕过与利用,被动式漏洞扫描检测,Burpsuite安装扩展,Burpsuite插件的开发实战(三),Burpsuite插件的开发实战(二),Burpsuite插件的开发实战(一),认识Burpsuite的API(三),认识Burpsuite的API(二),认识Burpsuite的API(一),Backslash-Powered-Scanner:扫描理念的变化(三),Backslash-Powered-Scanner:扫描理念的变化(二),Backslash-Powered-Scanner:扫描理念的变化(一),burpsuite与sqlmap的联动(四),burpsuite与sqlmap的联动(三),burpsuite与sqlmap的联动(二),burpsuite与sqlmap的联动(一),software-vulnerability-scanner:SCAP合规(二),software-vulnerability-scanner:SCAP合规(一),J2EEScan:初识DAST(三),J2EEScan:初识DAST(二),J2EEScan:初识DAST(一),XssValidator:动态渲染测试XSS(二),xssValidator:动态渲染测试XSS(一),知识盒子,知识付费,在线教育