burpsuite的插件初探

阿凡达2018-08-01 11:48

一、前言

偶然间,看到一篇ks文章,对burpsuite在安全方面的研究进行了概括,burpsuite作为一款安全软件,不仅在安全方面有重要的作用,在日常的开发测试中,也有很大的用途。用户可以通过burp方便的对某些指定的url进行请求的收集、修改、重放,虽然没有某些Chrome插件的体验那么优秀,但是对于某些特定的用途还是很有用的。
虽然burp具备强大的功能和可定制性,但是如果我们想要做出某些特殊的操作怎么办?这个时候,就需要用到burp的插件功能了。本文简单描述了burp插件编写的入门教程和简单的demo代码。

二、环境的设置
在上一篇ks文章中,通过设定全局代理的方式对访问进行了拦截,本文使用Chrome浏览器+SwitchyOmega插件的方式进行一些测试和开发的辅助。
1.启动burpsuite,设定burpsuite的监听端口为8081,并关闭请求中断功能。
2.设置扩展的SwitchyOmega的 burp的代理
3.单独设定SwitchyOmega的某些域名走 auto switch(图中,选择netease.com 走 auto switch 通道)
4.配置auto switch,进行进一步的筛选,某些特定的url才能走burp通道,否则直接放行
5.此时,某些特定的网站的内容已经通过burp的代理进行通信,已经可以开始监控到来往的http流量了,本文以www.ifeng.com 为例,展开插件编程入门。

三、插件编写初探
相关的资料和链接:
官方教程代码: https://github.com/PortSwigger
burp支持java,python,ruby三种语言进行扩展开发,因为公司里使用java的人比较多,这里使用java语言进行样例的开发。 官方教程代码,使用了gradle进行构建,这里使用maven进行构建。下面将会针对http的监控和请求拦截修改进行例子,简要描述插件编写方法:

1.新建maven工程
maven配置官方的burp-extender-api jar包,并新建一个名为burp的包,在此包下建立一个BurpExtender的类,而且必须实现IHttpListener接口。
package burp;

import java.io.PrintWriter;
import java.util.List;

public class BurpExtender implements IHttpListener{
    private IBurpExtenderCallbacks callbacks;
    private PrintWriter stdout;
    private IExtensionHelpers helpers;

    public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks){
        // 存储callback的引用
        this.callbacks = callbacks;
        this.helpers = callbacks.getHelpers();
        // 设置callback的扩展的名称
        callbacks.setExtensionName("devops burp ext");
        // 设置输出引用
        stdout = new PrintWriter(callbacks.getStdout(), true);

        //注册http的引用
        callbacks.registerHttpListener(this);
    }

    // 处理http捕获到的数据
    public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) {
        if(messageIsRequest){
            hookRequest(messageInfo);
        }else{
            hookResponse(messageInfo);
        }
    }

}
实现 IHttpListener的接口,其中,最重要的操作是callbacks.registerXXX,这里只以Http协议进行演示,所以注册了 registerHttpListener接口。相应的,如果注册了Http协议,则需要实现 processHttpMessage方法,对捕获到的数据进行分析。

2.修改返回的Http数据
在processHttpMessage方法中,我们已经对请求或者发送进行了区分,这里介绍对返回的数据进行修改。通过messageInfo.setResponse(byte[] data) 方法,可以对返回的数据进行篡改,但是,因为直接设定的返回的字节数组,所以必须按照Http协议的格式重新组装数组。好在burp的api已经提供了相应的接口,方便我们对Http协议的数组进行组装。
    //更新 body页面的内容
    private byte[] updateBodyContent(byte[] payload,byte[] newBodyContent){
        IResponseInfo ir = helpers.analyzeResponse(payload);
        List headers = ir.getHeaders();
        for(int i = 0; i< headers.size();++i){
            if(headers.get(i).indexOf("Content-Length") != -1){
                headers.set(i,"Content-Length: "+newBodyContent.length);
                break;
            }
        }
        return helpers.buildHttpMessage(headers,newBodyContent);
    }
这段代码中,参数payload 表示原有的Http数据报的内容,newBodyContent表示新的Html页面的内容。首先需要先把Http的header提取出来,因为新修改的bodycontent,会改变原有的header里,content-length的大小,所以,这里单独对这个content-length进行修改,然后通过burp的helpers对新的报文进行重新组装。

3.修改准备发送的Http数据
如果需要对发送的数据进行修改,则需要额外的操作,因为修改的请求,即可能是GET参数,也可能是POST参数,也可能是cookie,也可能是header,这里对burp提供的api进行一层封装,以方便对这些数据的修改。
    //增加get参数
    private byte[] addGetPara(byte[] payload,String key,String val){
        IParameter ip = helpers.buildParameter(key,val,IParameter.PARAM_URL);
        return helpers.addParameter(payload,ip);
    }

    //增加post参数
    private byte[] addPostPara(byte[] payload,String key,String val){
        IParameter ip = helpers.buildParameter(key,val,IParameter.PARAM_BODY);
        return helpers.addParameter(payload,ip);
    }

    //更新get参数
    private byte[] updateGetPara(byte[] payload,String key,String val){
        IParameter ip = helpers.buildParameter(key,val,IParameter.PARAM_URL);
        return helpers.updateParameter(payload,ip);
    }

    //更新post 参数
    private byte[] updatePostPara(byte[] payload,String key,String val){
        IParameter ip = helpers.buildParameter(key,val,IParameter.PARAM_BODY);
        return helpers.updateParameter(payload,ip);
    }

    //新增一个cookie
    private byte[] addCookie(byte[] payload,String key,String val){
        IParameter ip = helpers.buildParameter(key,val,IParameter.PARAM_COOKIE);
        return helpers.addParameter(payload,ip);
    }

    //更新一个cookie
    private byte[] updateCookie(byte[] payload,String key,String val){
        IParameter ip = helpers.buildParameter(key,val,IParameter.PARAM_COOKIE);
        return helpers.updateParameter(payload,ip);
    }



    //更新一个header,如果不存在,则增加
    private byte[] updateHeader(byte[] payload,String key,String val){
        IResponseInfo ir = helpers.analyzeResponse(payload);
        int bodyOffset = ir.getBodyOffset();
        List headers = ir.getHeaders();
        byte[] bodyByte = new byte[payload.length - bodyOffset];
        System.arraycopy(payload,bodyOffset,bodyByte,0,payload.length - bodyOffset);
        boolean exist = false;
        for(int i = 0; i< headers.size();++i){
            if(headers.get(i).indexOf(key) != -1){
                headers.set(i,key + ": "+val);
                exist = true;
                break;
            }
        }
        if(!exist){
            headers.add(key + ": "+val);
        }
        return helpers.buildHttpMessage(headers,bodyByte);
    }
最终版的DEMO代码,在这里  https://g.hz.netease.com/caoyuanye/burp-ext  

4.编译加载

编译之后,会生成一个jar文件,在burpsuite中,点击Extender菜单,选择Java进行加载,就可以将新的插件加载进burpsuite中。此时访问设定的被burp进行拦截的网站,就可以发现已经起到了预想的作用。我们开发的插件能够成功的对请求的参数和返回的结果分别进行修改。

四、总结 
至此,基本可以实现Http发送数据和接收数据的拦截和修改了,虽然有很多优秀的工具已经能够做到自动化的处理。但是面对特殊的需求,能够自行定制软件对数据的请求参数和返回结果进行定制,仍旧是一个比较实用的方法。

本文来自网易实践者社区,经作者曹原野授权发布。