burpsuite插件开发总结

0x00基础

burpsuite api:

burpsuite插件开发总结

接口:

用java开发插件就把这个burp文件夹放到工程目录即可

burpsuite插件开发总结

Java文档

burpsuite插件开发总结

在线版

https://portswigger.net/burp/extender/api/index.html

 

官方教程:https :
//portswigger.net/burp/extender/

https://portswigger.net/blog/writing-your-first-burp-suite-extension

https://portswigger.net/blog/archive?y=2012_12_01_archive.html

 

推荐用Java,执行效率高,不会出现奇奇怪怪的问题……

burpsuite插件开发总结

//图片图片网路

插件入口和帮助接口类:

IBurpExtender,IBurpExtenderCallbacks,IExtensionHelpers,IExtensionStateListener

IBurpExtenderCallbacks接口类是IBurpExtender接口的实现类与Burp其他各个组件(扫描仪,入侵者,蜘蛛……),各个通信对象(HttpRequestResponse,HttpService,SessionHandlingAction)之间的纽带。

IExtensionHelpers,IExtensionStateListener这两个接口类是插件的帮助和管理操作的接口定义。

 

UI相关接口类:

IContextMenuFactory,IContextMenuInvocation,ITab,ITextEditor,IMessageEditor,IMenuItemHandler

种类接口类主要是定义Burp插件的UI显示和动作的处理事件,主要是软件交互中使用。

 

Burp工具组件接口类:

IInterceptedProxyMessage,IIntruderAttack,IIntruderPayloadGenerator,IIntruderPayloadGeneratorFactory,IIntruderPayloadProcessor,IProxyListener,IScanIssue,IScannerCheck,IScannerInsertionPoint,IScannerInsertionPointProvider,IScannerListener,IScanQueueItem,IScopeChangeListener

这些接口类的功能非常好理解,Burp在接口定义的命名中使用了的见名知意的规范,看到接口类的名称,基本可以将这个接口作为适用于其中的工具组件。

 

HTTP消息处理接口类:

ICookie,IHttpListener,IHttpRequestResponse,IHttpRequestResponsePersisted,IHttpRequestResponseWithMarkers,IHttpService,IRequestInfo,IParameter,IResponseInfo

这些接口的定义主要是围绕HTTP消息通信过程中涉及的Cookie,请求,响应,参数几大消息对象,通过对通信消息头,消息体的数据处理,来达到控制HTTP消息传递的目的。

— https://t0data.gitbooks.io/burpsuite/content/chapter16.html

 

0x01常用的接口和方法

公共接口IBurpExtender

void registerExtenderCallbacks(IBurpExtenderCallbacks回调)

演示:

公共  BurpExtender 实现 IBurpExtenderITabIContextMenuFactoryActionListener {


公共 无效 registerExtenderCallbacksIBurpExtenderCallbacks 回调){

        回调setExtensionName(“ burp-info-extractor”);

        这个hps =回调getHelpers();
        这个cbs =回调;


回调registerContextMenuFactory(this);

 

公共接口IBurpExtenderCallbacks

演示:

callbacks.setExtensionName(“ burp-info-extractor”);

callbacks.registerContextMenuFactory(this);

 

公共接口IExtensionHelpers

IRequestInfo analyticsRequest(IHttpRequestResponse请求);
    IResponseInfo analyticsResponse(byte [] response);

演示:

 reqHeaders = 自我._helpers.analyzeRequest(requestResponse).getHeaders()

 

公共接口IScannerCheck

列表< IScanIssue > doPassiveScan(IHttpRequestResponse baseRequestResponse);



演示:
    def  doPassiveScanselfbaseRequestResponse):

        islaunchBurpUnauthChecker =  INT.launchBurpUnauthCheckerCheckBox.isSelected())

        如果不是islaunchBurpUnauthChecker )self .isFilterSuffix(baseRequestResponse))self .isFilterStatusCode(baseRequestResponse)):
            返回


        scan_issues = []

        newRequestResponse =  self .sendUnauthenticatedRequest(baseRequestResponse)

        #print str(self._helpers.analyzeRequest(baseRequestResponse).getUrl())+'\ n'

        问题= 自我.compareResponses(newRequestResponse,baseRequestResponse)


        scan_issues.append(issue)
        返回scan_issues


    高清 consolidateDuplicateIssues自我ISBISA):
        返回 - 1

 

公共接口IHttpListener

无效processHttpMessage(int toolFlag,

布尔messageIsRequest,

IHttpRequestResponse messageInfo);

 

toolFlag在公共接口IBurpExtenderCallbacks中可查看

/ **

*用于标识Burp Suite整体的标志。

* /

整数TOOL_SUITE = 0x00000001;

/ **

*用于标识打Bur目标工具的标志。

* /

整数TOOL_TARGET = 0x00000002;

/ **

*用于标识打p代理工具的标志。

* /

整数TOOL_PROXY = 0x00000004;

/ **

*用于标识Burp Spider工具的标志。

* /

整数TOOL_SPIDER = 0x00000008;

/ **

*用于标识Burp Scanner工具的标志。

* /

整数TOOL_SCANNER = 0x00000010;

/ **

*用于标识Burp Intruder工具的标志。

* /

整数TOOL_INTRUDER = 0x00000020;

/ **

*用于标识打p中继器工具的标志。

* /

整数TOOL_REPEATER = 0x00000040;

/ **

*用于标识Burp Sequencer工具的标志。

* /

整数TOOL_SEQUENCER = 0x00000080;

/ **

*用于标识Burp Decoder工具的标志。

* /

整数TOOL_DECODER = 0x00000100;

/ **

*用于标识Burp比较器工具的标志。

* /

整数TOOL_COMPARER = 0x00000200;

/ **

*用于标识Burp Extender工具的标志。

* /

整数TOOL_EXTENDER = 0x00000400;

演示:

def processHttpMessage(self,toolFlag,messageIsRequest,messageInfo):

如果messageIsRequest和toolFlag == 4:

 

公共接口IHttpRequestResponse

byte [] getRequest();
byte [] getResponse();

演示:

reqBodyByte = requestResponse.getRequest()。tostring()[reqBodyOffset:]

 

公共接口IContextMenuFactory

 List < JMenuItem > createMenuItems(IContextMenuInvocation调用);


演示


    public  List < JMenuItem > createMenuItems(IContextMenuInvocation invocation){
         // TODO自动生成的方法stub 
        selectedItems = invocation getSelectedMessages();       
        
        List < JMenuItem > menu = 新的 ArrayList < JMenuItem >();
        
        JMenuItem itemManualTesting = 新的 JMenuItem“将rsp发送到BIE”);
        itemManualTesting setActionCommand(“ sendRSPToBIE”);
        itemManualTesting addActionListener(this);
        
        菜单add(itemManualTesting);
        
        返回菜单;
    }

 

开发burpsuite插件关键在于处理http请求和响应

可以参考

https://github.com/bit4woo/burp-api-drops

再以jython为例:

获取标题:通过IRequestInfo对象

reqHeaders = self._helpers.analyzeRequest(requestResponse).getHeaders()

 

获取参数:通过IRequestInfo对象

paramList = 自我._helpers.analyzeRequest(requestResponse).getParameters()

用于paramList:

            paramType = para.getType()

            如果(paramType ==  0(paramType ==  1):

                paramKey = para.getName()

                paramValue = para.getValue()

#参数共有7种格式,0是URL参数,1是body参数,2是cookie参数,6是json格式参数

 

获取正文:通过字符串格式的request截取

reqBodyOffset = self._helpers.analyzeRequest(requestResponse).getBodyOffset()

reqBodyByte = requestResponse.getRequest()。tostring()[reqBodyOffset:]

 

更新参数值:

如果paramKey.lower()authParamsList:
                    newAuthParam =  self ._helpers.buildParameter(paramKey,newAuthParamValue,paramType)
                    newRemoveGetPostAuthParamsRequest =  self ._helpers.updateParameter(newRemoveGetPostAuthParamsRequest,newAuthParam)

 

更新标题:

newHeaders = []

        newAuthHeaderVal =  self .replaceHeaderValWithTextField.getText()


        对于reqHeaders:
            headerName = header.split(':')[ 0 ]
         #如果headerName.lower()不在self.authParamsList中:
        #newHeaders.append(header)#
        返回self._helpers.buildHttpMessage(newHeaders,None)
            如果headerName.lower( ) 自己的.authParamsList中:
                标头= headerName +  “:”  + newAuthHeaderVal
                newHeaders.append(header)
            其他
                newHeaders.append(header)

 

更新正文:

如果paramType ==  6

                paramKey = para.getName()
                paramValue = para.getValue()

                打印paramKey +  “:”  + paramValue

                reqJsonBodyOffset =  self ._helpers.analyzeRequest(requestResponse).getBodyOffset()
                reqJsonBodyString = requestResponse.getRequest()。tostring()[reqJsonBodyOffset:]

                打印reqJsonBodyString

                reqJsonBodyStringDict = json.loads(reqJsonBodyString)

                #reqJsonBodyStringDict = ast.literal_eval(reqJsonBodyString)

                对于authParamNameauthParamsList:
                    如果authParamNamereqJsonBodyStringDict.keys():
                        reqJsonBodyStringDict [authParamName] = newAuthParamValue

 

重新构造请求包:

newRemoveGetPostAuthParamsRequest =  self ._helpers.buildHttpMessage(jsonReqHeaders,newReqJsonBodyString)

                    
返回 自身._callbacks.makeHttpRequest(requestResponse.getHttpService(),newRequest)

 

0x02开发插件

未授权访问权限检测:

https://github.com/theLSA/burp-unauth-checker

敏感参数提取:

https://github.com/theLSA/burp-sensitive-param-extractor

信息提取:

https://github.com/theLSA/burp-info-extractor

 

burp-unauth-checker

需求

自动化检测未授权访问
aauthize
authz
authmatrix
自动转发器
上几个插件都挺好,但是还是不太符合,想要的是在浏览的时候可以自动检测是否有未授权访问权限。

实现

python编写,实现IScannerCheck接口doPassiveScan方法

authParams.cfg文件存储授权的参数,如令牌,cookie等

在UI输入框增加授权参数要以英文逗号(,)分隔,并单击保存按钮保存,其他操作不需要点击保存按钮。

显示帖子正文即显示帖子数据的正文内容。

show rspContent即显示响应正文内容,建议尝试不开启。

一些授权参数是在get / post参数中的,如user / list?token = xxx,这时可以重置替换替换授权参数值的GET / POST Auth参数。

默认过滤后缀列表filterSuffixList =“ jpg,jpeg,png,gif,ico,bmp,svg,js,css,html,avi,mp4,mkv,mp3,txt”

应对一些特殊情况,设置了排除的授权参数列表excludeAuthParamsList

onlyIncludeStatusCode:设置检测的响应码,仅只检测200的响应

原本想直接取消掉授权参数,但是可能造成响应失败,所以把授权参数值替换成自定义的数据,如:cookie:[空],token = unauthp

sendUnauthenticatedRequest发送替换了授权参数值的请求

授权参数分两种
1-在http的header中,如cookie,authorization等
2-在http参数中,如post数据中的token等
实现:
1-直接将header的授权参数值替换为:
if headerName。 self.authParamsList中的lower():
header = headerName +“:” + newAuthHeaderVal
2-
get / post请求的参数,常规操作buildParameter,updateParameter可。jsonParameter
,直接将正文数据解析为字典再替换授权参数值,然后再将字典转换字符串,最后构造新请求数据包。

如果paramType ==  6

                paramKey = para.getName()
                paramValue = para.getValue()

                打印paramKey +  “:”  + paramValue

                reqJsonBodyOffset =  self ._helpers.analyzeRequest(requestResponse).getBodyOffset()
                reqJsonBodyString = requestResponse.getRequest()。tostring()[reqJsonBodyOffset:]

                打印reqJsonBodyString

                reqJsonBodyStringDict = json.loads(reqJsonBodyString)

                #reqJsonBodyStringDict = ast.literal_eval(reqJsonBodyString)

                对于authParamNameauthParamsList:
                    如果authParamNamereqJsonBodyStringDict.keys():
                        reqJsonBodyStringDict [authParamName] = newAuthParamValue

有两个问题

1-字典有【u“】,

2-还有将字符串转为字典,json数据有空格和单引号

json.loads重新构造的json数据有空格

尝试使用

d = json.dumps(s,分隔符=(’,’,’:’))

发现类型是str不方便处理,loads()没有separators参数

ast.literal_eval()也一样有空格和单引号……

想直接替换掉空间,但是有些数据可能会有空间……

两个问题的解决方案:

reqJsonBodyStringDict = json.loads(reqJsonBodyString)

……#替换授权参数值

newReqJsonBodyString = json.dumps(reqJsonBodyStringDict,separators =(’,’,’:’))

即先用json.loads()将串联转换字典进行处理后再将字典用json.dumps()转换为字符串来构造请求数据包。

最后再对比原请求和替换了授权参数值的响应body
compareRespons:
如果(str(nBody).split()== str(oBody).split()):

一致则为未授权访问突破。

临时不提供在ui界面删除授权参数的功能,如要删除直接在authParams.cfg内部删除,切记将光标移动到最后一个授权参数(末行)的结尾。

坑点

1] dopassivescan的request不能直接用,要复制一个再用,否则会出现请求只能只读的异常,因为这个请求响应已经完成了,再编辑是没意义的。

解决:

newRemoveGetPostAuthParamsRequest = newRemoveAuthHeaderRequest

2】python中的空要用None,java是null

效果图

burpsuite插件开发总结 burpsuite插件开发总结

 

打敏感参数提取器

需求

检测并提取请求参数中的敏感参数名,如用户名,用户名,方便测试越权突破,并形成敏感参数字典。

实现

使用python开发,实现IHttpListener接口,processHttpMessage方法。

param-regular.cfg:参数正则配置文件,id表示检测请求参数中包含id的参数,如userid,idcard等

支持4种参数检测:

self.requestParamDict [‘urlParams’] = []
self.requestParamDict [‘BodyParams’] = []
self.requestParamDict [‘cookieParams’] = []
self.requestParamDict [‘jsonParams’] = []

先获取请求的所有类型参数,放到requestParamDict再找到SensitiveParam最后写入2文件。

界面右侧的列表即参数正则,可实时增删,删除只需单击列表元素再单击删除按钮即可。

IHttpListener似乎无法实现请求关键字参数高亮,IScanIssue-ScanIssue-self._callbacks.applyMarkers可以,暂不实现参数高亮了。

无法处理较复杂的请求json参数,某些多重层次结构,这种情况下,暂不做处理。

坑点

1】所谓的json的get请求参数可能无法获取最连续键值对?

解决:这种请求的情况可能见,暂不处理。

效果图

burpsuite插件开发总结

 

打bur信息提取器

需求

快速提取数据中毒性的信息,如HTTP响应数据包中的用户名,密码等。

例如一个api(/ user / list)返回大量用户名/密码,大多数是json格式(jsonarray),就可以使用此工具快速提取信息。

实现

使用java开发,实现IContextMenuFactory接口createMenuItems方法。

采用两种提取方式:
1.json格式提取
2.正则提取

【1】json格式
提取:采用google gson

【2】正则
提取re库常规操作即可

坑点

1】

现象:

发送rsp到bie中空行问题,复制的http请求和手动换行复制body没问题,直接发送到的请求就无法以\ n \ n获取body,可能是有\ t,\ r,\ n之类的字符

解决:
rspBody1 = rspBody1.replaceAll(“ \ r \ n | \ r | \ n | \ t”,“”);

2】

现象:

runnable里面run(),无法直接使用动作监听,如:
cleanRspBodyButton.setActionCommand(“ cleanrspbody”);

cleanRspBodyButton.addActionListener(BurpExtender);

解决:
cleanRspBodyButton.addActionListener(new ActionListener(){

@Override

公共无效actionPerformed(ActionEvent e){

// TODO自动生成的方法存根

rspBodyArea.setText(“”);

}

效果图

burpsuite插件开发总结

 

0x03常见问题

1.多次加载插件出现内存不足错误

原因:内存被占满了,重启burp或增加burp的内存,在启动Burp时设置JVM的XX参数即可,如:java -XX:MaxPermSize = 1G -jar burp.jar

2,如何调试

jython目前只能想到print大法……

java的当前我也是用println大法,虽然有可以联动ide进行调试的方法,但还是要编译jar,比较麻。

3,py开发的插件用到第三方库,如要求,但即使本机安装了要求库,加载插件时候还是提示找到

原因:jython和python的库不同

解决:

在插件目录放进第三方库即可

或者填入第三方库的位置,如site-package

burpsuite插件开发总结

0x04结语

学习优秀的插件,不用重复造轮子。

参考官方API。

网站地址:https://www.hackzl.cn;发布者:hack之路,转转请注明出处:https://www.hackzl.cn/index.php/2020/12/15/2440/

发表评论

邮箱地址不会被公开。 必填项已用*标注