This commit is contained in:
EvilOS
2020-03-24 18:15:37 +08:00
parent 14b43d9625
commit 7863d9640d
20 changed files with 418 additions and 2 deletions

233
HaE/HaE.py Normal file
View File

@@ -0,0 +1,233 @@
# -*- coding:utf-8 -*-
# Author: Vulkey_Chen
# Blog: gh0st.cn
# Team: MSTSEC
import json, re, jsbeautifier
from burp import IBurpExtender, ITab, IHttpListener, IMessageEditorTabFactory, IMessageEditorTab
from javax.swing import JPanel, JLabel, JButton, JTextArea, JTextField, JCheckBox, JTabbedPane, JScrollPane, SwingConstants
from java.awt import BorderLayout
from java.io import PrintWriter
# color list
colors = ['red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'pink', 'magenta', 'gray']
# config
configFile = "config.json"
# 获取配置文件内容
def getConfig():
config = ""
with open(configFile, 'r') as content:
config = json.load(content)
return config
# 寻找内容
def findContent(info, message):
info = getConfig()
results = {}
for i in info:
regex = re.compile(info[i]['regex'])
regexRes = regex.findall(message)
if regexRes != []:
results[i] = ','.join(list(set(regexRes)))
return results
class BurpExtender(IBurpExtender, ITab,IHttpListener, IMessageEditorTabFactory):
def registerExtenderCallbacks(self, callbacks):
self._callbacks = callbacks
self._helpers = callbacks.getHelpers()
callbacks.setExtensionName("HaE(Highlighter and Extractor)")
self._stdout = PrintWriter(callbacks.getStdout(), True)
callbacks.registerHttpListener(self)
callbacks.registerMessageEditorTabFactory(self)
print 'HaE(Highlighter and Extractor)\nAuthor: Vulkey_Chen\nBlog: gh0st.cn\nTeam: MSTSEC'
self._callbacks.customizeUiComponent(self.getUiComponent())
self._callbacks.addSuiteTab(self)
self.endColors = []
def getTabCaption(self):
return 'HaE'
def createNewInstance(self, controller, editable):
return MarkINFOTab(self, controller, editable)
def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
if messageIsRequest:
return
content = messageInfo.getResponse()
r = self._helpers.analyzeResponse(content)
msg = content[r.getBodyOffset():].tostring()
# msg 为响应正文信息
info = getConfig()
results = findContent(info, msg)
colorList = []
if results != {}:
for i in results:
if info[i]['highlight'] == 1 :
if info[i]['color'] == 'red':
messageInfo.setHighlight(info[i]['color'])
break
else:
colorList.append(info[i]['color'])
if not messageInfo.getHighlight():
colorsList = [colors.index(i) for i in colorList]
colorsList.sort()
# print(colorsList)
self.helper(colorsList)
endColor = [colors.index(x) for x in self.endColors]
# print(endColor)
messageInfo.setHighlight(colors[min(endColor)])
# 颜色升级
def helper(self, mylist):
l = len(mylist)
i = 0
stack = []
while i < l:
if not stack:
stack.append(mylist[i])
i += 1
else:
if mylist[i] != stack[-1]:
stack.append(mylist[i])
i += 1
else:
stack[-1] -= 1
i += 1
if len(stack) == len(set(stack)):
self.endColors = [colors[i] for i in stack]
else:
self.helper(stack)
def addConfig(self, event):
nameText = self.nameTextField.getText()
regexText = self.regexTextField.getText()
colorText = self.colorTextField.getText()
isHighlight = int(self.highlightCheckBox.isSelected())
isExtract = int(self.extractCheckBox.isSelected())
if colorText in colors:
with open(configFile, 'r+') as content:
dicts = json.load(content)
# 解决r+写入问题
content.seek(0,0)
content.truncate()
if nameText in dicts:
self.tipString.setText("Name is existed!")
elif not(isHighlight or isExtract):
self.tipString.setText("Highlight or Extract?")
else:
dicts[nameText] = {"regex": regexText, "highlight": isHighlight, "extract": isExtract, "color": colorText}
content.write(jsbeautifier.beautify(json.dumps(dicts)))
#print(dicts)
self.tipString.setText("Save Successfully!")
else:
self.tipString.setText("Not in colors list.")
def reloadConfig(self, event):
with open(configFile, 'r') as content:
self.configTextArea.setText(content.read())
def getUiComponent(self):
self.HaEPanel = JPanel()
self.HaEPanel.setBorder(None)
self.HaEPanel.setLayout(BorderLayout(0, 0))
self.panel = JPanel()
self.HaEPanel.add(self.panel, BorderLayout.NORTH)
self.panel.setLayout(BorderLayout(0, 0))
self.tabbedPane = JTabbedPane(JTabbedPane.TOP)
self.panel.add(self.tabbedPane, BorderLayout.CENTER)
self.setPanel = JPanel()
self.tabbedPane.addTab("Set", None, self.setPanel, None)
self.setPanel.setLayout(BorderLayout(0, 0))
self.setPanel_1 = JPanel()
self.setPanel.add(self.setPanel_1, BorderLayout.NORTH)
self.nameString = JLabel("Name")
self.setPanel_1.add(self.nameString)
self.nameTextField = JTextField()
self.setPanel_1.add(self.nameTextField)
self.nameTextField.setColumns(10)
self.regexString = JLabel("Regex")
self.setPanel_1.add(self.regexString)
self.regexTextField = JTextField()
self.setPanel_1.add(self.regexTextField)
self.regexTextField.setColumns(10)
self.extractCheckBox = JCheckBox("Extract")
self.setPanel_1.add(self.extractCheckBox)
self.highlightCheckBox = JCheckBox("Highlight")
self.setPanel_1.add(self.highlightCheckBox)
self.setPanel_2 = JPanel()
self.setPanel.add(self.setPanel_2)
self.colorString = JLabel("Color")
self.setPanel_2.add(self.colorString)
self.colorTextField = JTextField()
self.setPanel_2.add(self.colorTextField)
self.colorTextField.setColumns(5)
self.addBottun = JButton("Add", actionPerformed=self.addConfig)
self.setPanel_2.add(self.addBottun)
self.tipString = JLabel("");
self.setPanel_2.add(self.tipString)
self.configPanel = JPanel()
self.tabbedPane.addTab("Config", None, self.configPanel, None)
self.configPanel.setLayout(BorderLayout(0, 0))
self.configString = JLabel("This is config file content.")
self.configString.setHorizontalAlignment(SwingConstants.CENTER)
self.configPanel.add(self.configString, BorderLayout.NORTH)
self.configTextArea = JTextArea()
self.configTextArea.setEnabled(False)
self.configTextArea.setTabSize(4)
self.configTextArea.setLineWrap(True)
self.configTextArea.setRows(20)
self.configPanel.add(self.configTextArea, BorderLayout.SOUTH)
self.scrollPane = JScrollPane(self.configTextArea)
self.configPanel.add(self.scrollPane, BorderLayout.SOUTH)
self.reloadButton = JButton("Reload", actionPerformed=self.reloadConfig)
self.configPanel.add(self.reloadButton, BorderLayout.CENTER)
return self.HaEPanel
class MarkINFOTab(IMessageEditorTab):
def __init__(self, extender, controller, editable):
self._extender = extender
self._helpers = extender._helpers
self._editable = editable
self._txtInput = extender._callbacks.createTextEditor()
self._txtInput.setEditable(editable)
def getTabCaption(self):
return "MarkINFO"
def getUiComponent(self):
return self._txtInput.getComponent()
# 非响应 没有匹配到不返回Tab标签页
def isEnabled(self, content, isRequest):
r = self._helpers.analyzeResponse(content)
msg = content[r.getBodyOffset():].tostring()
info = getConfig()
if not isRequest:
content = findContent(info, msg)
if content != {}:
for i in content:
if info[i]['extract'] == 1 :
return True
# 设置Tab的内容
def setMessage(self, content, isRequest):
# 判断是否有内容
if content:
if not isRequest:
r = self._helpers.analyzeResponse(content)
msg = content[r.getBodyOffset():].tostring()
info = getConfig()
contents = findContent(info, msg)
result = ""
for i in contents:
if info[i]['extract'] == 1 :
result += "[{}] {}\n".format(i,contents[i])
self._txtInput.setText(result)
else:
return False

26
HaE/config.json Normal file
View File

@@ -0,0 +1,26 @@
{
"Email": {
"color": "yellow",
"highlight": 1,
"regex": "[\\w-]+(?:\\.[\\w-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?",
"extract": 1
},
"Chinese IDCard": {
"color": "orange",
"highlight": 1,
"regex": "[1-9]\\d{5}(?:19|20)\\d\\d(?:0[1-9]|1[012])(?:0[1-9]|[12]\\d|3[01])\\d{3}(?:\\d|X)",
"extract": 1
},
"Chinese Mobile": {
"color": "yellow",
"highlight": 1,
"regex": "[^0-9]+(1[3-9]\\d{9})[^0-9]+",
"extract": 1
},
"Internal IP Address": {
"color": "yellow",
"highlight": 1,
"regex": "(?:10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})|(?:172\\.(?:(?:1[6-9])|(?:2\\d)|(?:3[01]))\\.\\d{1,3}\\.\\d{1,3})|(?:192\\.168\\.\\d{1,3}\\.\\d{1,3})",
"extract": 1
}
}

161
README.md
View File

@@ -1,2 +1,159 @@
# HaE
HaE - BurpSuite Highlighter and Extractor
# HaE - 信息高亮与提取者
## 前言
HaEHighlight and Extractor是基于MarkINFO插件地址https://github.com/gh0stkey/BurpSuite-Extender-MarkInfo )的基础进行重构。
用处:
- 高亮标记请求,针对高亮的请求进行深度挖掘
- 敏感信息泄露发现
## 设计想法
语言Python
![-w902](images/15845160387850.jpg)
功能:
- 自定义正则
- 自定义高亮颜色
- 自定义高亮或提取
## 设计过程
### 可视化界面
UI设计基于Eclipse可视化设计基于Java Swing
![-w1143](images/15845162741518.jpg)
然后将Java代码转换为Python代码即可**有很多坑~**
使用BurpSuite接口`ITab`创建Tab
![-w1276](images/15845160114052.jpg)
### 高亮颜色
将BurpSuite的所有高亮颜色集成仅支持`red, orange, yellow, green, cyan, blue, pink, magenta, gray`
![-w96](images/15844769689459.jpg)
![-w518](images/15845164967615.jpg)
### 配置文件格式
选用JSON格式格式为
```
name: {"regex": regexText, "highlight": isHighlight, "extract": isExtract, "color": colorText}
```
### 颜色优先级和升级
定义Colors变量
`colors = ['red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'pink', 'magenta', 'gray']`
利用下标的方式进行优先级排序当满足2个同颜色条件则以优先级顺序上升颜色。例如**两个正则,颜色为橘黄色,该请求两个正则都匹配到了,那么将升级为红色**
## 使用方法
贴一些案例,仅供参考,还有更多玩法,可以自我琢磨~
### 环境设置
进入Extender - Options - Python Environment
![-w840](images/15845168078333.jpg)
载入Jython的Jar包以及载入python的包路径。
加载插件选择HaE.py文件
![-w858](images/15845168915243.jpg)
加载成功:
![-w743](images/15845169108559.jpg)
### RUN IT
#### 添加自定义正则
```
名字Email
正则:[\\w-]+(?:\\.[\\w-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?
高亮颜色red
是否高亮和提取:是
```
转到HaE标签页进行设置点击Add按钮即可添加
![-w1278](images/15845171413470.jpg)
HaE - Config查看是否进行配置点击Reload按钮
![-w1277](images/15845172203307.jpg)
#### 高亮请求
在Proxy - HTTP History中可以看见高亮请求响应标签页中含有`MarkINFO`标签,其中将匹配到的邮箱提取了出来
![-w1268](images/15845175423506.jpg)
#### 正则优化参考Demo
在正则匹配手机号、身份证号码的时候(纯数字类)会存在一些误报(这里匹配身份证号码无法进行校验,误报率很高),但手机号处理这一块可以解决:
原正则:
```
(1[3-9]\d{9})
```
误报场景:`12315188888888123`,这时候会匹配到`15188888888`,而实际上这一段并不是手机号,所以完全可以修改正则为:
```
[^0-9]+(1[3-9]\d{9})[^0-9]+
```
也就是要求匹配的手机号前后不能为0-9的数字。
## 实战用法
### CMS指纹识别
例如识别Discuz名字CMS-Discuz正则`Powered by Discuz!`高亮颜色blue
![-w1272](images/15845485039330.jpg)
Add保存到配置文件中
![-w294](images/15845485770190.jpg)
请求识别:
![-w1037](images/15845486471590.jpg)
### OSS对象存储信息泄露
名字INFO-OSS
正则:`[A|a]ccess[K|k]ey[I|i]d|[A|a]ccess[K|k]ey[S|s]ecret`
高亮颜色cyan
![-w1002](images/15845490590739.jpg)
Add保存到配置文件中
![-w482](images/15845490802944.jpg)
请求中识别并提取:
![-w1278](images/15845492243895.jpg)

BIN
images/15844769689459.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
images/15845160114052.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

BIN
images/15845160387850.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

BIN
images/15845162741518.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 KiB

BIN
images/15845164967615.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

BIN
images/15845168078333.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 KiB

BIN
images/15845168915243.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 KiB

BIN
images/15845169108559.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

BIN
images/15845171413470.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 KiB

BIN
images/15845172203307.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

BIN
images/15845175423506.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

BIN
images/15845485039330.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

BIN
images/15845485770190.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
images/15845486471590.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 KiB

BIN
images/15845490590739.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

BIN
images/15845490802944.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
images/15845492243895.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB