利用Bambda优化HTTP视角:提升Web安全测试效率
当你打开一个HTTP请求或响应时,会本能地寻找什么?可疑的参数名?CORS头?还是请求来源或潜在目的的线索?每个HTTP消息对不同观察者可能讲述不同的故事,但现代网站发送成千上万的请求,很容易忽略关键内容。为此,Burp Suite最近添加了对自定义列的支持,允许你个性化HTTP请求中哪些元素显示在表格中。以下是一个简单示例,从请求体中解析GraphQL操作并显示在列中:
1
|
return requestResponse.request().parameterValue("operationName", HttpParameterType.JSON);
|
幕后,这些功能是通过称为bambda的代码片段实现的。这一功能强大到几乎令人不知所措,因此我们想分享研究团队创建的一些列,从简单实用到较为复杂。熟悉Java的读者可能会注意到我们没有刻意避免空指针异常——这是因为它们在行级别被处理,因此通常不会引起问题。
实用Bambda示例
请求来源页面
理解HTTP请求序列的流程对发现许多高级漏洞至关重要,这使其稍微容易一些。
1
|
return requestResponse.request().headerValue("Referer");
|
响应来源的Web服务器
也许我有一个针对特定代理的WAF绕过或缓存投毒攻击。
1
|
return requestResponse.response().headerValue("Server");
|
HTTP版本
我应该优先考虑请求走私还是竞争条件?我的10,000字目录暴力破解需要多长时间?
1
|
return requestResponse.request().httpVersion();
|
请求目标IP地址的所有者
也许我应该以他们的基础设施为目标。反向DNS是个好东西。
1
2
|
String ipAddress = requestResponse.httpService().ipAddress();
return java.net.InetAddress.getByName(ipAddress).getCanonicalHostName();
|
是否在范围内?
你不想意外地攻击范围之外的内容。
1
|
return requestResponse.request().isInScope();
|
请求的GraphQL操作名称
通常可以通过URL一眼看出请求的操作,但GraphQL是个不方便的例外。这个脚本解决了这个问题。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
String paramName = "operationName";
if(requestResponse.request().hasParameter(paramName, HttpParameterType.JSON)) {
return requestResponse.request().parameterValue(paramName, HttpParameterType.JSON);
}
String query = requestResponse.request().parameterValue("query", HttpParameterType.JSON);
if(query.contains("{") || query.contains("(")) {
var queryParts = query.split("\\{|\\(");
return queryParts[0];
}
return "";
|
Base64解码后的会话Cookie
像JWT这样的编码签名令牌无处不在,总是值得仔细查看。这个脚本需要根据你的目标进行定制。
1
2
3
4
5
6
7
8
9
10
11
12
|
if (!requestResponse.hasResponse()) {
return "";
}
var extract = "session";
var response = requestResponse.response();
var optionalCookie = response.cookies().stream().filter(cookie -> cookie.name().equals(extract)).findFirst();
if(optionalCookie.isEmpty()) return "";
var value = optionalCookie.get().value();
var parts = value.split("\\.");
if(parts.length != 3) return "";
var payload = parts[1];
return utilities().base64Utils().decode(payload, Base64DecodingOptions.URL);
|
哪些Cookie禁用了SameSite?
在策划CSRF或XSS攻击时,了解是否有Cookie禁用了SameSite很有用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
if(requestResponse.response() == null) {
return "";
}
if(!requestResponse.response().hasHeader("Set-Cookie")){
return "";
}
ArrayList<String> cookieNames = new ArrayList<>();
Pattern pattern = Pattern.compile("^ ([^=]+).+; SameSite=None", Pattern.CASE_INSENSITIVE);
List<HttpHeader> headers = requestResponse.response().headers();
for(HttpHeader header : headers) {
Matcher matcher = pattern.matcher(header.value());
while(matcher.find()) {
cookieNames.add(matcher.group(1));
}
}
return String.join(", ", cookieNames);
|
响应是否有不良CSP?
这个自定义列Bambda允许你优先测试部署了不安全CSP指令(如unsafe-inline或unsafe-eval)的易受攻击端点。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
if(requestResponse.response() == null) {
return "";
}
if(!requestResponse.response().hasHeader("Content-Security-Policy")) {
return "No CSP";
}
String csp = requestResponse.response().headerValue("Content-Security-Policy");
ArrayList<String> vulnerableDirectives = new ArrayList<>();
String[] directivesToCheck = new String[]{"unsafe-inline", "unsafe-eval"};
for(int i=0;i<directivesToCheck.length;i++) {
if(csp.contains(directivesToCheck[i])) {
vulnerableDirectives.add(directivesToCheck[i]);
}
}
return String.join(", ", vulnerableDirectives);
|
通过排序自定义列进行优先级排序
你可以通过自定义列对整个表格进行排序,这有助于确定要优先处理哪些请求。随着时间的推移,我个人可能会编写一个巨大的bambda,从0到100评分请求的可攻击性,但目前这里有两个简单示例:
请求有多少参数?
有时,你只是想尽快找到最大的攻击面。
1
|
return requestResponse.request().parameters().size();
|
响应中有多少’HTTP_‘出现?
这可能表明环境变量泄漏,或者可以调整以查找各种其他有趣的字符串。
1
2
3
4
5
|
if (!requestResponse.hasResponse()) {
return 0;
}
String lookFor = "HTTP_";
return utilities().byteUtils().countMatches(requestResponse.response().body().getBytes(), lookFor.getBytes());
|
执行Shell命令
也许下次吧。
通过利用Bambda,安全研究人员可以更高效地分析和优先处理HTTP请求,从而提升Web安全测试的整体效率和效果。