No.1
声明
由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测以及文章作者不为此承担任何责任。
雷神众测拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经雷神众测允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。
No.2
前言
这节课的来源是在写fastjson rce检测插件时所遇到的问题并解决后的笔记。
我们知道fastjson的数据是json格式的, 那么前面学的buildParameter就不适用该情况了,会导致使用buildParameter重构参数后报错。
这节课学习 buildHttpMessage 重构json数据,并结合前面课程实现fastjson rce检测插件
No.3
getContentType
此方法用于获取消息正文的内容类型,由IRequestInfo对象调用
官方api:https://portswigger.net/burp/extender/api/burp/IRequestInfo.html#getContentType()
示例代码如下:
reqContentType = analyzedRequest.getContentType()
如果数据是json格式,那么analyzedRequest.getContentType()返回来的值是4。
那么就可以通过reqContentType是否等于4过滤掉不是json格式的数据包,从而使该插件只检测当数据类型是json时才触发。
接下来准备重构数据包。
No.4
stringToBytes()
byte[] stringToBytes(java.lang.String data)
此方法可用于将数据从字符串形式转换为字节数组。该转换不反映任何特定字符集,十六进制表示为0xWXYZ的字符将始终转换为表示形式为0xYZ的字节。它执行与方法相反的转换bytesToString(),并保证使用这两种方法将基于字节的数据转换为String并再次返回,以确保其完整性(反映给定字符集的转换可能不是这种情况)。
官方api:https://portswigger.net/burp/extender/api/burp/IExtensionHelpers.html#stringToBytes(java.lang.String)
官方的解释有点拗口,其实很简单,就是把我们想要提交的字符串内容转换为burp能认识的数据类型。
示例代码如下:将字符串payload转换为burp认识的字节类型,这样newBody的数据类型就变成了byte,就能够在下一个api里使用了。
newBodyPayload = {“age”:25, “name”:”Bob””}
newBody = self._helpers.stringToBytes(newBodyPayload) # 将字符串转换为字节
当构造好payload后,下面准备重构http消息
No.5
buildHttpMessage
byte[] buildHttpMessage(java.util.List headers, byte[] body)
此方法构建包含指定的标头和消息正文的HTTP消息。如果适用,将根据正文的长度添加或更新Content-Length标头。
官方api:https://portswigger.net/burp/extender/api/burp/IExtensionHelpers.html#buildHttpMessage(java.util.List,%20byte[])
buildHttpMessage的第一个参数headers是IRequestInfo对象的getHeaders()方法返回值
示例代码如下:如果不知道analyzedIRequestInfo是什么变量,请回顾前几节课。
reqHeaders = analyzedIRequestInfo.getHeaders()
buildHttpMessage的第二个参数body是IExtensionHelpers.stringToBytes(字符串)的返回值
newBody = self._helpers.stringToBytes(newBodyPayload) # 将字符串转换为字节
准备好两个参数后,传递给buildHttpMessage即可重构http消息
newRequest = self._helpers.buildHttpMessage(reqHeaders, newBody) # 重构json格式的数据不能用buildParameter,要用buildHttpMessage替换整个body重构http消息。
然后接下来同样使用makeHttpRequest发送数据并响应即可。
newIHttpRequestResponse = self._callbacks.makeHttpRequest(httpService, newRequest) # 发送数据
fastjson rce检测插件demo
示例代码如下:
# -*-coding:utf-8 -*-
# 被动扫描fastjson rce检测
from burp import IBurpExtender, IScannerCheck, IScanIssue, IMessageEditorTabFactory, IContextMenuFactory
from burp import IScanIssue
import sys
import time
import os
class BurpExtender(IBurpExtender, IMessageEditorTabFactory, IContextMenuFactory, IScannerCheck):
def registerExtenderCallbacks(self, callbacks):
# Required for easier debugging:
sys.stdout = callbacks.getStdout()
# 用于设置当前扩展的显示名称,该名称将显示在Extender工具的用户界面中。参数:name – 扩展名。。
self._callbacks = callbacks
# 用于获取IExtensionHelpers对象,扩展可以使用该对象执行许多有用的任务。返回:包含许多帮助器方法的对象,用于构建和分析HTTP请求等任务。
self._helpers = callbacks.getHelpers()
# 用于设置当前扩展的显示名称,该名称将显示在Extender工具的用户界面中。参数:name – 扩展名。
self._callbacks.setExtensionName(“Passive Fastjson Check”)
# 注册扫描
callbacks.registerScannerCheck(self)
# 获取请求的url
def get_request_url(self, protocol, reqHeaders):
link = reqHeaders[0].split( )[1]
host = reqHeaders[1].split( )[1]
return protocol + :// + host + link
# 获取请求的一些信息:请求头,请求内容,请求方法,请求参数
def get_request_info(self, request):
analyzedIRequestInfo = self._helpers.analyzeRequest(request) # analyzeRequest用于分析HTTP请求,并获取有关它的各种关键详细信息。生成的IRequestInfo对象
reqHeaders = analyzedIRequestInfo.getHeaders() # 用于获取请求中包含的HTTP头。返回:请求中包含的HTTP标头。
reqBodys = request[analyzedIRequestInfo.getBodyOffset():].tostring() # 获取消息正文开始的请求中的偏移量。返回:消息正文开始的请求中的偏移量。
reqMethod = analyzedIRequestInfo.getMethod() # 获取请求方法
reqParameters = analyzedIRequestInfo.getParameters()
return analyzedIRequestInfo, reqHeaders, reqBodys, reqMethod, reqParameters
# 获取响应的一些信息:响应头,响应内容,响应状态码
def get_response_info(self, response):
analyzedIResponseInfo = self._helpers.analyzeRequest(response) # analyzeResponse方法可用于分析HTTP响应,并获取有关它的各种关键详细信息。返回:IResponseInfo可以查询的对象以获取有关响应的详细信息。
resHeaders = analyzedIResponseInfo.getHeaders() # getHeaders方法用于获取响应中包含的HTTP标头。返回:响应中包含的HTTP标头。
resBodys = response[analyzedIResponseInfo.getBodyOffset():].tostring() # getBodyOffset方法用于获取消息正文开始的响应中的偏移量。返回:消息正文开始的响应中的偏移量。response[analyzedResponse.getBodyOffset():]获取正文内容
# resStatusCode = analyzedIResponseInfo.getStatusCode() # getStatusCode获取响应中包含的HTTP状态代码。返回:响应中包含的HTTP状态代码。
return resHeaders, resBodys
# 获取服务端的信息,主机地址,端口,协议
def get_server_info(self, httpService):
host = httpService.getHost()
port = httpService.getPort()
protocol = httpService.getProtocol()
ishttps = False
if protocol == https:
ishttps = True
return host, port, protocol, ishttps
# 获取请求的参数名、参数值、参数类型(get、post、cookie->用来构造参数时使用)
def get_parameter_Name_Value_Type(self, parameter):
parameterName = parameter.getName()
parameterValue = parameter.getValue()
parameterType = parameter.getType()
return parameterName, parameterValue, parameterType
# 开始检测
def start_run(self, baseRequestResponse):
self.baseRequestResponse = baseRequestResponse
# 获取请求包的数据
request = self.baseRequestResponse.getRequest()
analyzedRequest, reqHeaders, reqBodys, reqMethod, reqParameters = self.get_request_info(request)
reqContentType = analyzedRequest.getContentType() # 获取请求格式,例如json
if reqContentType == 4: # json格式数据
# 获取服务信息
httpService = self.baseRequestResponse.getHttpService()
newBodyPayload = {“age”:25, “name”:”Bob””}
newBody = self._helpers.stringToBytes(newBodyPayload) # 将字符串转换为字节 https://portswigger.net/burp/extender/api/burp/IExtensionHelpers.html#stringToBytes(java.lang.String)
newRequest = self._helpers.buildHttpMessage(reqHeaders, newBody) # 重构json格式的数据不能用buildParameter,要用buildHttpMessage替换整个body重构http消息。https://portswigger.net/burp/extender/api/burp/IExtensionHelpers.html#buildHttpMessage(java.util.List,%20byte[])
newIHttpRequestResponse = self._callbacks.makeHttpRequest(httpService, newRequest) # 发送数据
response = newIHttpRequestResponse.getResponse() # 获取响应包
analyzedIResponseInfo = self._helpers.analyzeRequest(response) # analyzeResponse方法可用于分析HTTP响应,并获取有关它的各种关键详细信息。返回:IResponseInfo可以查询的对象以获取有关响应的详细信息。
resBodys = response[analyzedIResponseInfo.getBodyOffset():].tostring()
newUrl = self._helpers.analyzeRequest(newIHttpRequestResponse).getUrl()
print resBodys
if fastjson in resBodys:
print [+] {}.format(newUrl)
self.save(newUrl)
self.issues.append(CustomScanIssue(
newIHttpRequestResponse.getHttpService(),
newUrl,
[newIHttpRequestResponse],
“FastJson RCE”,
“fastjson”,
“High”))
else:
print [-] {}.format(newUrl)
def doPassiveScan(self, baseRequestResponse):
:param baseRequestResponse: IHttpRequestResponse
:return:
self.issues = []
self.start_run(baseRequestResponse)
return self.issues
def consolidateDuplicateIssues(self, existingIssue, newIssue):
相同的数据包,只报告一份报告
:param existingIssue:
:param newIssue:
:return:
if existingIssue.getIssueDetail() == newIssue.getIssueDetail():
return -1
return 0
class CustomScanIssue(IScanIssue):
def __init__(self, httpService, url, httpMessages, name, detail, severity):
:param httpService: HTTP服务
:param url: 漏洞url
:param httpMessages: HTTP消息
:param name: 漏洞名
:param detail: 漏洞细节
:param severity: 漏洞等级
self._httpService = httpService
self._url = url
self._httpMessages = httpMessages
self._name = name
self._detail = detail
self._severity = severity
def getUrl(self):
return self._url
def getIssueName(self):
return self._name
def getIssueType(self):
return 0
def getSeverity(self):
return self._severity
def getConfidence(self):
return “Certain”
def getIssueBackground(self):
pass
def getRemediationBackground(self):
pass
def getIssueDetail(self):
return self._detail
def getRemediationDetail(self):
pass
def getHttpMessages(self):
return self._httpMessages
def getHttpService(self):
return self._httpService
效果如下:
当正常发送数据包时,响应包没报错
再来看看插件的情况,可以看到响应包里出现了fastjon字符串,说明payload检测出了该漏洞
这里demo用的是写死的payload,自己写的时候根据自己的需求将payload请求的地址改为dnslog的地址。
免责声明:文章内容来自互联网,本站不对其真实性负责,也不承担任何法律责任,如有侵权等情况,请与本站联系删除。
转载请注明出处:Burp Extender Apis 插件开发 (六) https://www.yhzz.com.cn/a/431.html