该篇文章主要介绍burp插件开发中常使用的IHttpListener接口。其中包含三部分接口实例:分别是修改请求数据的host重定向请求到其他主机、添加x-forwarded-for请求头、修改响应数据包体(body)。在开始实例介绍之前,我们先了解下IHttpListener接口。
一、IHttpListener接口介绍
IHttpListener接口主要用于监听经过burp的http数据流,包括请求数据及响应数据。我们在插件开发中注册IHttpListener接口后,当请求数据经过burp 的各个模块(如proxy、intruder、scanner、repeater)时,我们可以拦截并修改请求数据中的host、port、protocol、请求头、请求数据包(body)后再发送出数据;同时我们也可以拦截响应数据,对它进行解密或者加密操作后,再返回响应数据。
IHttpListener接口包含的函数processHttpMessage,我们implements接口IHttpListener后,在processHttpMessage函数中去实现具体功能。
public void processHttpMessage(int toolFlag,boolean messageIsRequest,IHttpRequestResponse messageInfo),processHttpMessage包含三个参数toolFlag、messageIsRequest、messageInfo。
-
toolFlag用于标识函数功能作用于哪个模块,其中包含有以下模块,如下所示:
https://portswigger.net/burp/extender/api/burp/iburpextendercallbacks.html
messageIsRequest用于判断当前数据流量是 请求数据(Request)或者是 响应数据(Response),当messageIsRequest为true是请求数据(R equest),messageIsRequest为false是响应数据(Response)。
messageInfo为IHttpRequestResponse接口的实例,可以通过messageInfo获取流量数据(包括请求数据及响应数据)的详细信息(包括请求的host、port、protocol、header(请求头)、body(请求包体)等)
-
IHttpRequestResponse接口包含的函数,如下所示
https://portswigger.net/burp/extender/api/burp/IHttpRequestResponse.html
其中可以通过getHttpService()得到一个http信息包括(host、port、protocol)、通过getRequest()得到请求数据的完整信息、通过getResponse()得到响应数据的完整信息。
二、IHttpListener接口实例
- 修改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);
}
}
-
修改host(m.baidu.com修改为chls.pro)结果如下所示:
添加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
}
}
-
添加x-forwarded-for请求头,伪造客户端IP测试结果如下所示:
- 修改响应数据包体(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);
}
}
-
修改响应数据包体(body),将响应数据包体(body)中的unicode编码转成中文结果如下所示:
综上所述,该篇文章主要介绍了burp插件通过implements IHttpListener接口,对监听到的http(https)数据流量进行基础的修改测试。更多具体app安全分析中使用到的实例将在后面慢慢更新介绍。本篇文章中使用到的测试demo代码可以在公众号中回复"burp demo 2"获取百度云下载链接进行下载。