前言

BurpSuite是久负盛名的web应用安全测试工具,在安全圈子中被誉为“神器”。它的核心功能是http代理,并在此基础上提供了丰富的自定义配置选项,协助使用者设计不同的方案进行渗透或者安全监测。此外,除了工具本身提供的功能以外,burpsuite神器提供了一组java编写的应用接口,通过java或基于java的Jython、Jruby,可以实现许多自定义的功能插件。Burpsuite作为web测试的神器,已经人手必备了。用户可以自己开发扩展实现一些特殊的需求。

这里我就用burpsuite实现一个被动式的注入扫描的功能,记录一下,也给其他同学做个参考。

环境

目前burpsuite官方支持用java,python,ruby开发扩展,我这里就用java来开发了,如果用python或者ruby的话,速度及性能是比java差的。

首先需要下载burpsuite的api包,这个在burpsuite客户端已经集成了,直接下载即可。

然后在eclipse中新建项目,把burpsuite的api包导入进来,这样基本的开发环境已经成功了。

API基础

简单介绍一下几个最常用的接口:
interface IBurpExtender: 这个接口所有的扩展都需要实现.
Interface IBurpExtenderCallbacks: 这个接口几乎是必备的。在编写扩展的过程中会经常用到。
Interface IExtensionHelpers: 这个接口是新加的。提供了编写扩展中常用的一些通用函数,比如编解码、构造请求等。这样就不需要重负造轮子了。
Interface IHttpRequestResponse: 这个接口包含了每个请求和响应的细节。在Brupsuite中的每个请求或者响应都是IHttpRequestResponse实例。

SQL注入插件

因为我们要实现被动注入的功能,所以除了实现burpsuite api的IBurpExtender接口外,还要实现IScannerCheck接口。

大致代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class BurpExtender implements IBurpExtender,IScannerCheck {

public IBurpExtenderCallbacks callbacks;
public IExtensionHelpers helpers;
public PrintWriter stdout;
@Override
public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
// TODO Auto-generated method stub

this.callbacks = callbacks;
stdout = new PrintWriter(callbacks.getStdout(),true);
this.helpers = callbacks.getHelpers();

callbacks.setExtensionName("NST SQL CHECK");
callbacks.registerScannerCheck(this);
stdout.println("NST SQL CHECK : www.isnst.com");

}
}

实现IScannerCheck后需要重写被动扫描的函数。

也就是

1
public List<IScanIssue> doPassiveScan(IHttpRequestResponse baseRequestResponse) {}

在这个方法中我们就可以拿到http请求,然后根据我们的payload来重新发包,进行验证sql注入的漏洞。
给出我的部分代码,供参考。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//被动扫描
@Override
public List<IScanIssue> doPassiveScan(IHttpRequestResponse baseRequestResponse) {
// TODO Auto-generated method stub
String method = this.helpers.analyzeRequest(baseRequestResponse).getMethod();
String url = this.helpers.analyzeRequest(baseRequestResponse).getUrl().toString();
byte content_type = this.helpers.analyzeRequest(baseRequestResponse).getContentType();
for (String item : config.blackDomain) {
if(url.contains(item)) {
return null;
}
}

for (String ext : config.blackExt) {
int extend = url.lastIndexOf("?");
int extstart = url.lastIndexOf(".")+1;
String urlext="";
if(extend>extstart) {
urlext = url.substring(extstart, extend);
}else {
int secstart = url.lastIndexOf(".",extend);
try {
urlext = url.substring(secstart+1, extend);
} catch (Exception e) {
urlext = url.substring(extstart, url.length());
}
}
if (urlext.equals(ext)) {
return null;
}
}


List<String> headers = this.helpers.analyzeRequest(baseRequestResponse).getHeaders();
List<IParameter> params = this.helpers.analyzeRequest(baseRequestResponse).getParameters();


//Gen headers
Map<String,String> allheaders = new HashMap<String,String>();
for (String header : headers) {
if (header.contains(":")) {
try {
String[] headerArrayStrings = header.split(":");
if(!headerArrayStrings[1].contains("gzip")) {
allheaders.put(headerArrayStrings[0].trim(), headerArrayStrings[1]);
}
} catch (Exception e) {}
}
}

try {
checkSqli.nstcheckSqli(url, method, allheaders, params,stdout,content_type);
} catch (IOException e) {
e.printStackTrace();
}

return null;
}

这样的话我们就拿到burpsuite给我们传递过来的http request请求的包了。IHttpRequestResponse 里封装了我们的请求包及返回的信息。

然后我们就可以根据payload来尝试是否存在sql注入了。

封装了一个http的get和post的请求函数,基于okhttp。可直接调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* HTTP GET
* @param url
* @param headers
* @return
* @throws IOException
*/
public static String Get(String url,Map<String,String> headers){

try {
OkHttpClient client = new OkHttpClient();
Builder builder = new Request.Builder().url(url);
Iterator<Map.Entry<String, String>> entries = headers.entrySet().iterator();
while (entries.hasNext()) {
Entry<String, String> entry = entries.next();
builder.addHeader(entry.getKey(), entry.getValue());
}
Request request = builder.build();
Response response = client.newCall(request).execute();

return response.body().string();
} catch (IOException e) {
// TODO Auto-generated catch block
return getrandstrs();
}

}

Post也类似,查看okhttp的文档,修改响应的部分就行了。

然后就是检测注入了。

部分代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public static boolean checkerrorsql(String url,String method,Map<String,String> headers,List<IParameter> parameters,PrintWriter stdout,byte content_type) throws IOException {

if(method.equals("GET")) {
for (IParameter iParameter : parameters) {
if(iParameter.getType()==IParameter.PARAM_URL) {
for (String pay : config.error_payloads) {
String paramitem = iParameter.getName()+"="+iParameter.getValue();
String payloaditem = paramitem + pay;
String myurl = url.replace(paramitem, payloaditem);
String html = HTTPClient.Get(myurl, headers);
for (String respflag : config.error_flag) {
if(html.contains(respflag)) {
stdout.println("***************************************");
stdout.println("[+] Error-Base SQLI :");
stdout.println(myurl);
stdout.println("NST SQLI Scaner");
stdout.println("***************************************");
return true;
}
}
}
}
}
}
}

检测报错的注入可通过返回包中是否存在关键字来判断。get和post均可。

而bool注入则根据多个相应包的比较来判断,time-base类型注入直接根据响应时间即可。

最终效果

我们只需要开启burp,然后随便在网站点几个URL请求。然后就坐等注入即可。

如图

插件截图

参考资料

http://www.vuln.cn/6097

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