burp插件开发基础二(JAVA篇)

该篇文章主要介绍burp插件开发中常使用的IHttpListener接口。其中包含三部分接口实例:分别是修改请求数据的host重定向请求到其他主机添加x-forwarded-for请求头修改响应数据包体(body)。在开始实例介绍之前,我们先了解下IHttpListener接口。

一、IHttpListener接口介绍

  1. IHttpListener接口主要用于监听经过burp的http数据流,包括请求数据及响应数据。我们在插件开发中注册IHttpListener接口后,当请求数据经过burp 的各个模块(如proxy、intruder、scanner、repeater)时,我们可以拦截并修改请求数据中的host、port、protocol、请求头、请求数据包(body)后再发送出数据;同时我们也可以拦截响应数据,对它进行解密或者加密操作后,再返回响应数据。

  2. IHttpListener接口包含的函数processHttpMessage,我们implements接口IHttpListener后,在processHttpMessage函数中去实现具体功能。

  3. public void processHttpMessage(int toolFlag,boolean messageIsRequest,IHttpRequestResponse messageInfo),processHttpMessage包含三个参数toolFlagmessageIsRequestmessageInfo

  4. toolFlag用于标识函数功能作用于哪个模块,其中包含有以下模块,如下所示:

    burp插件开发基础二(JAVA篇)_第1张图片
    图片

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

  5. messageIsRequest用于判断当前数据流量是 请求数据(Request)或者是 响应数据(Response),当messageIsRequest为true是请求数据(R equest),messageIsRequest为false是响应数据(Response)。

  6. messageInfo为IHttpRequestResponse接口的实例,可以通过messageInfo获取流量数据(包括请求数据及响应数据)的详细信息(包括请求的host、port、protocol、header(请求头)、body(请求包体)等)

  7. IHttpRequestResponse接口包含的函数,如下所示

    burp插件开发基础二(JAVA篇)_第2张图片
    图片

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

  8. 其中可以通过getHttpService()得到一个http信息包括(host、port、protocol)、通过getRequest()得到请求数据的完整信息、通过getResponse()得到响应数据的完整信息。

二、IHttpListener接口实例

  1. 修改host(m.baidu.com修改为chls.pro),将请求数据重定向发送到其他主机
//implements IHttpListener
public class BurpExtender implements IBurpExtender,IHttpListener{

  private static final String HOST_FROM = "m.baidu.com"; //原主机
  private static final String HOST_TO = "chls.pro";//重定向的主机
  
  private PrintWriter stdout;
  private IExtensionHelpers helpers;
  @Override
  public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) {
    // TODO Auto-generated method stub
    if(messageIsRequest) {//判断请求是 请求数据 则替换host 重定向 host
      //获取一个httpService包含host、port、protocol      
      IHttpService httpService = messageInfo.getHttpService();
      //打印原host
      stdout.println("orig host is: " + httpService.getHost());
      //判断原host是不是m.baidu.com,如果是则替换host
      if(HOST_FROM.equalsIgnoreCase(httpService.getHost())) {
        //使用helpers.buildHttpService新建一个httpService
        //新的httpService中host指定为要替换的host chls.pro
        //使用messageInfo.setHttpService 将拦截到的messageInfo的
        //httpService替换成新建的httpService 完成 host 替换
        messageInfo.setHttpService(helpers.buildHttpService(HOST_TO, httpService.getPort(), httpService.getProtocol()));
        //重新获取httpService 查看host是否替换成功
        httpService = messageInfo.getHttpService();
        //打印出替换后的host、port、protocol
        stdout.println("host is: " + httpService.getHost() + " "
            + "and port is: " + httpService.getPort() + " "
                + "and protocol is: " + httpService.getProtocol());
      }
    }
    
  }

  @Override
  public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
    // TODO Auto-generated method stub
    helpers = callbacks.getHelpers();
    callbacks.setExtensionName("Traffic redirector");
    callbacks.registerHttpListener(this);
    stdout = new PrintWriter(callbacks.getStdout(),true); 
  }
}
  1. 修改host(m.baidu.com修改为chls.pro)结果如下所示:

    burp插件开发基础二(JAVA篇)_第3张图片
    图片
  2. 添加x-forwarded-for请求头,伪造客户端IP测试

//implements IHttpListener
public class BurpExtender implements IBurpExtender,IHttpListener{

  private IBurpExtenderCallbacks callbacks;
  private IExtensionHelpers helpers;
  private PrintWriter stdout;
  
  @Override
  public void processHttpMessage(int toolFlag, boolean messageIsRequest, 
      IHttpRequestResponse messageInfo) {
    // TODO Auto-generated method stub
    if(toolFlag == this.callbacks.TOOL_PROXY) {//判断当前监听流量数据的模块是否为PROXY模块 
    //如果是PROXY模块 则进入下面的数据处理
      if(messageIsRequest) { //只在请求数据时添加请求头X-Forwarded-For
        try {
        //获取一个IRequestInfo接口实例analyIRequestInfo
        //analyIRequestInfo中
        //包含了 请求数据 的详细信息包括请求数据包体(body)的偏移地址
        //请求数据中的请求头(返回List列表)、请求数据的请求方法(GET、POST等)
        //请求数据中的请求参数(返回List列表
        //请求的URL
        //参考的链接地址 https://portswigger.net/burp/extender/api/burp/IRequestInfo.html
        //我们在此处获取该实例是为了得到请求数据中的请求头列表
        //以及请求数据包体(body)的起始偏移地址
          IRequestInfo analyIRequestInfo = helpers.analyzeRequest(messageInfo);
          //获取整个请求数据内容
          String request = new String(messageInfo.getRequest(),"UTF-8");
          //通过上面的analyIRequestInfo得到请求数据包体(body)的起始偏移
          int bodyOffset = analyIRequestInfo.getBodyOffset();
          //通过起始偏移点得到请求数据包体(body)的内容
          byte[] body = request.substring(bodyOffset).getBytes("UTF-8");
          //通过上面的analyIRequestInfo得到请求数据的请求头列表
          List headers = analyIRequestInfo.getHeaders();//获取http请求头的信息
          //生成X-Forwarded-For请求头 包括请求头的key(X-Forwarded-For)及随机生成的IP
          String xForwardFor = "X-Forwarded-For: "+ RandomIP.randomIPStr();
          //在headers请求头列表中添加X-Forwarded-For请求头
          headers.add(xForwardFor);
          //打印X-Forwarded-For请求头测试
          stdout.println(xForwardFor);
          //使用我们刚添加进去X-Forwarded-For请求头的请求头列表以及
          //上面得到的请求数据包体(body)重新生成一个HttpMessage
          //重新构造了请求数据
          byte[] newRequest = helpers.buildHttpMessage(headers, body);
          //打印出重新构造的请求数据测试
          stdout.println(helpers.analyzeRequest(newRequest).getHeaders());
          //发送重新构造的请求数据 里面已经包含有我们添加的X-Forward-For
          messageInfo.setRequest(newRequest); //设置最终新的请求包 添加xForwardFor 请求头
        }catch(Exception e) {
          stdout.println(e);
        }

      }
    }
  }

  @Override
  public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
    // TODO Auto-generated method stub
    this.callbacks = callbacks;
    helpers = callbacks.getHelpers();
    stdout = new PrintWriter(callbacks.getStdout(),true);
    callbacks.setExtensionName("Random_X-FORWARD-FOR"); //设置插件名称
    callbacks.registerHttpListener(this); //注册HttpListener
  }
}
  1. 添加x-forwarded-for请求头,伪造客户端IP测试结果如下所示:


    burp插件开发基础二(JAVA篇)_第4张图片
    image.png

    burp插件开发基础二(JAVA篇)_第5张图片
    image.png
  1. 修改响应数据包体(body),将响应数据包体(body)中的unicode编码转成中文
//implements IHttpListener
public class BurpExtender implements IBurpExtender,IHttpListener{

  private IBurpExtenderCallbacks callbacks;
  private IExtensionHelpers helpers;
  private PrintWriter stdout;
  private String ExtenderName = "Unicode decoder";
  
  @Override
  public void processHttpMessage(int toolFlag, boolean messageIsRequest, 
      IHttpRequestResponse messageInfo) {
    // TODO Auto-generated method stub
    if(toolFlag == this.callbacks.TOOL_PROXY) {//判断当前监听流量数据的模块是否为PROXY模块
      //如果是PROXY模块 则进入下面的数据处理
      if(!messageIsRequest) { //只处理响应数据 不处理请求数据
      //我们只处理响应数据中的unicode编码 将它们转成中文
        try {
        //获取到整个响应数据
          byte[] response = messageInfo.getResponse();
          //获取一个IResponseInfo接口实例analyzedResponseInfo
          //analyzedResponseInfo中
          //包含了 响应数据 的详细信息包括响应数据包体(body)偏移地址
          //响应数据中的请求头(返回List列表)
          //响应数据中的cookie列表(返回List列表)
          //响应的状态码等
          //参考的链接地址 https://portswigger.net/burp/extender/api/burp/iresponseinfo.html
          //我们在此处获取该实例是为了得到响应数据包体(body)偏移地址
          //以及响应数据的请求头列表
          IResponseInfo analyzedResponseInfo = helpers.analyzeResponse(response);
          //通过上面的analyzedResponseInfo得到响应数据的请求头列表
          List headers = analyzedResponseInfo.getHeaders(); //响应的http头
          //得到完整的响应数据
          String resp = new String(messageInfo.getResponse(),"UTF-8"); //响应整个包
          //通过上面的analyzedResponseInfo得到响应数据包体(body)的起始偏移
          int bodyOffset = analyzedResponseInfo.getBodyOffset();
          //根据响应数据的起始偏移 在 响应数据中得到响应数据包体(body)
          String body = resp.substring(bodyOffset); //响应数据包体
          //将得到的响应数据包体(body)中的unicode编码转成中文
          body = unicodeToString(body); //将响应数据包体中unicode编码字符转成中文
          //打印转换后的响应数据包体(body)内容
          stdout.println(body);
          //转换响应数据包体(body)内容为byte[]
          byte[] bodyByte = body.getBytes("UTF-8"); //将响应数据包体字符串转成byte数组
          //重新构建响应包体(body)数据 并发送到burp中
          //已经将响应数据包体(body)中的unicode编码转成中文
          messageInfo.setResponse(helpers.buildHttpMessage(headers, bodyByte));
        }catch(Exception e) {
          stdout.println(e);
        }

      }
    }
  }

  @Override
  public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
    // TODO Auto-generated method stub
    this.callbacks = callbacks;
    stdout = new PrintWriter(callbacks.getStdout(),true);
    stdout.println(ExtenderName);
    helpers = callbacks.getHelpers();
    
    //设置插件名称
    callbacks.setExtensionName(ExtenderName);
    //注册HttpListener 监听http数据流量 处理请求数据和响应数据
    callbacks.registerHttpListener(this);
  }
  
  public static void main(String[] args) {
    String unicodeStr = "\\u4f60\\u597d\\u554a";
    String result = unicodeToString(unicodeStr);
    System.out.println(result);
  }
}
  1. 修改响应数据包体(body),将响应数据包体(body)中的unicode编码转成中文结果如下所示:


    burp插件开发基础二(JAVA篇)_第6张图片
    image.png

    burp插件开发基础二(JAVA篇)_第7张图片
    image.png
  2. 综上所述,该篇文章主要介绍了burp插件通过implements IHttpListener接口,对监听到的http(https)数据流量进行基础的修改测试。更多具体app安全分析中使用到的实例将在后面慢慢更新介绍。本篇文章中使用到的测试demo代码可以在公众号中回复"burp demo 2"获取百度云下载链接进行下载。

你可能感兴趣的:(burp插件开发基础二(JAVA篇))