讲道理有点标题党了,这篇文章主要聊一聊结合爬虫实现漏洞检测的思路,以及目前用burpsuite插件实践过程的记录。
结合上一篇爬虫篇来看,这里整个的工作流程就像这样:
浏览器插件同步Cookie -> Server -> Spider -> 正向代理(Brup、Xray等)实现漏洞检测
懒得画图了,脑补一下8
有心捣鼓的师傅会发现在我开源的爬虫CrawlerVuln中,其实在module/Crawler.js
中注释掉了一行代码:'--proxy-server=http://127.0.0.1:8080'
,puppeteer在启动时可以配置一个代理,包括http、https、socks5等类型,配合一些正向代理漏扫工具,比如xray、GourdScanV2等等,但是觉得别人写的工具又不如自己写的用着舒服,计划 第一版先借助Burp插件实现自己一些扫描的需求,第二版将考虑写一个http正向代理,实现一个代理池去自定义规则扫描检测漏洞模块。
使用Puppeteer+Brup组合使用,让Headless流量全走Burp出去,配合好写的插件进行漏洞检测。这样的好处是我不用在写爬虫的时候去hook网络请求(为了获取链接)。
思考:如何发更少的数据包,发现更多的漏洞
想这个问题的原因有几点,区别于传统扫描器的大量发生数据包,实战环境中不是太允许我们发生大量的有害payload请求去测试,一来可能会被各种防御软件拦截导致封IP、或者Cookie强制注销,得不偿失无疑造成大量测试点遗漏;二来我们的目的只是为了找到短板,找到漏洞,而不是相较于传统扫描器找全漏洞。我们就可以根据自己的想法写一些自己想测试的规则,用最少的数据包发现漏洞。
以SQL为例,分享一个在lufei师傅博客看到的挺有意思的点
11^sleep(5)#'^sleep(5)#"^sleep(5)#
11^sleep(5)#')^sleep(5)#")^sleep(5)#
当然这样检测也有缺陷,比如limit、insert、update注入不能很好的检测,但也启发着我们可以从这个角度来思考各种其他的探测场景。
从burp导出接口文件:burp->extender->apis->save interface files
配置IDEA,参考这篇文章
命令行编译
javac -d build src/burp/*.java
jar cf plugin.jar -C build burp
动态调试
破解版动态调试和付费版有一点不太一样,需要指定一个-Xbootclasspath/p:burp-loader-keygen.jar
破解文件的路径。
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -Xbootclasspath/p:burp-loader-keygen.jar -jar -Xmx4G burpsuite_community.jar
接着在IDEA里边配置远程调试环境:
接着保持burp中打包的代码和本地代码一致就可以下断点debug了。
一个必须要实现的接口和方法
public class BurpExtender implements IBurpExtender, IHttpListener { private IBurpExtenderCallbacks callbacks; private IExtensionHelpers helpers; private PrintWriter stdout; private String ExtenderName = "SQL Inject Scan"; @Override public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks){ stdout = new PrintWriter(callbacks.getStdout(), true); callbacks.printOutput("Author: Passer6y"); this.callbacks = callbacks; helpers = callbacks.getHelpers(); callbacks.setExtensionName(ExtenderName); callbacks.registerHttpListener(this); } } @Override public void processHttpMessage(int toolFlag, boolean messageIsRequest,IHttpRequestResponse messageInfo) { // 接着当有HTTP请求响应时,会调用该方法,我们只需要通过翻阅文档摸清这几个参数的类型所对应的用法即可 }
大部分漏洞检测需求一般都在于处理HTTP的请求和响应中,这里以SQL注入探测插件为例,在爬虫爬行时,需要对所有参数进行各种payload的添加。
@Override public void processHttpMessage(int toolFlag, boolean messageIsRequest,IHttpRequestResponse messageInfo) { if(!messageIsRequest){ // 请求结束之后 if ((toolFlag == 4)) {//经过Proxy工具的流量 for(byte[] payload:payloads){ attack(messageInfo, payload); } } } }
在attack函数中对messageInfo
参数进行数据包解体,添加payload,构造新的参数:
public void attack(IHttpRequestResponse messageInfo, byte[] payload){ List<int[]> matches = new ArrayList<>(); IHttpService iHttpService = messageInfo.getHttpService(); IRequestInfo analyzeRequest = this.helpers.analyzeRequest(messageInfo); // this.stdout.println("[*] Current URL:" + analyzeRequest.getUrl()); List<IParameter> paraList = analyzeRequest.getParameters(); for (IParameter para : paraList){ if (para.getType() == 0 || para.getType() == 1){ //0是URL参数,1是body参数,2是cookie参数 String key = para.getName(); String value = para.getValue(); try { String changedValue = value + this.helpers.bytesToString(payload); byte[] new_Request = messageInfo.getRequest(); IParameter newPara = this.helpers.buildParameter(key, changedValue, para.getType()); //构造新的参数 new_Request = this.helpers.updateParameter(new_Request, newPara); //构造新的请求包 IHttpRequestResponse messageInfoExp = this.callbacks.makeHttpRequest(iHttpService, new_Request); // 发送含poc的包
添加issue的时候摸索了一会,有两种办法添加issue,很多插件都是在调用IScannerCheck
接口的doPassiveScan
或者doActiveScan
方法,接着通过return一个IScanIssue
的数组,然后burp就实现添加了添加issue的过程,但是在爬虫爬行的过程中,我们想要实现的是将经过proxy的流量进行探测,探测到的结果添加issue,在这里分享一个个人习惯,搜索一个issue关键字,然后在左边api里边上下滑动api接口,可以快速定位到相关方法:
this.callbacks.addScanIssue(new CustomScanIssue( iHttpService, analyzeRequest.getUrl(), new IHttpRequestResponse[]{callbacks.applyMarkers(messageInfoExp, null, matches)}, "SQL Time Delay Injection", "Payload: " + key+"="+changedValue + " ,sleep time: " + Long.toString(sleepTime/1000) + ", Netwok Delay: " + Long.toString(networkDelay) + "ms", "High"));
最后推荐给一些新入坑的小伙伴一些建议,可以多看文档,多看官方的demo,在Github学习优秀的插件代码
最后奉上源码,欢迎一起交流~
https://github.com/Passer6y/SQLScan