Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
225ee471ec | ||
|
|
5097124867 | ||
|
|
7e0e3054be | ||
|
|
17a84fc19e | ||
|
|
1573d563eb | ||
|
|
515f7b33f0 | ||
|
|
1dc510d576 |
@@ -7,13 +7,11 @@
|
||||
|
||||
## 项目介绍
|
||||
|
||||
**HaE**是基于 `BurpSuite Java插件API` 开发的请求高亮标记与信息提取的辅助型框架式插件,该插件可以通过自定义正则的方式匹配响应报文或请求报文,并对满足正则匹配的请求进行信息高亮与提取。
|
||||
**HaE**是基于 `BurpSuite Java插件API` 开发的请求高亮标记与信息提取的辅助型框架式插件,该插件可以通过自定义正则的方式匹配响应报文或请求报文,并对满足正则匹配的报文进行信息高亮与提取。
|
||||
|
||||

|
||||
现代化Web应用走上前后端分离开发模式,这就导致在日常测试时候会有许多的流量,如果你想要尽可能全面的对一个Web应用进行测试评估,将花费大量精力浪费在无用的报文上;**HaE的出现正是为了解决这一类似场景**,借助HaE你可以**有效的减少**测试的时间,将更多的精力放在**有价值、有意义**的报文上,**提高漏洞挖掘效率**。
|
||||
|
||||
现代化Web应用走上前后端分离开发模式,这就导致在日常测试时候会有许多的请求流量,如果你想要尽可能全面的对一个Web应用进行测试评估,将花费大量精力浪费在无用的请求上;**HaE的出现正是为了解决这一类似场景**,借助HaE你可以有效的减少测试的时间,将更多的精力放在**有价值、有意义**的请求上,**大幅度**的减少无效测试时间,**提高漏洞挖掘效率**。
|
||||
|
||||
**注**: 要想灵活的使用`HaE`,你需要掌握正则表达式阅读、编写、修改能力;由于`Java`正则表达式的库并没有`Python`的优雅或方便,在使用正则的,HaE要求使用者必须使用`()`将所需提取的表达式内容包含;例如你要匹配一个**Shiro应用**的响应报文,正常匹配规则为`rememberMe=delete`,如果你要提取这段内容的话就需要变成`(rememberMe=delete)`。
|
||||
**注**: 要想灵活的使用`HaE`,你需要掌握正则表达式阅读、编写、修改能力;由于`Java`正则表达式的库并没有`Python`的优雅或方便,所以HaE要求使用者必须用`()`将所需提取的表达式内容包含;例如你要匹配一个**Shiro应用**的响应报文,正常匹配规则为`rememberMe=delete`,如果你要提取这段内容的话就需要变成`(rememberMe=delete)`。
|
||||
|
||||
## 使用方法
|
||||
|
||||
|
||||
@@ -30,4 +30,5 @@ dependencies {
|
||||
compile group: 'org.yaml', name: 'snakeyaml', version: '1.28'
|
||||
compile 'net.sourceforge.jregex:jregex:1.2_01'
|
||||
compile 'dk.brics.automaton:automaton:1.11-8'
|
||||
compile 'com.squareup.okhttp:okhttp:2.7.5'
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 188 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 56 KiB |
@@ -3,6 +3,7 @@ package burp;
|
||||
import burp.action.*;
|
||||
import burp.ui.MainUI;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
@@ -33,12 +34,12 @@ public class BurpExtender implements IBurpExtender, IHttpListener, IMessageEdito
|
||||
this.callbacks = callbacks;
|
||||
BurpExtender.helpers = callbacks.getHelpers();
|
||||
|
||||
String version = "2.4";
|
||||
String version = "2.4.2";
|
||||
callbacks.setExtensionName(String.format("HaE (%s) - Highlighter and Extractor", version));
|
||||
// 定义输出
|
||||
stdout = new PrintWriter(callbacks.getStdout(), true);
|
||||
stdout.println("@Core Author: EvilChen");
|
||||
stdout.println("@Architecture Author: 0chencc");
|
||||
stdout.println("@First Author: EvilChen");
|
||||
stdout.println("@Second Author: 0chencc");
|
||||
stdout.println("@Github: https://github.com/gh0stkey/HaE");
|
||||
// UI
|
||||
SwingUtilities.invokeLater(this::initialize);
|
||||
@@ -115,6 +116,7 @@ public class BurpExtender implements IBurpExtender, IHttpListener, IMessageEdito
|
||||
private final IMessageEditorController controller;
|
||||
private Map<String, String> extractRequestMap;
|
||||
private Map<String, String> extractResponseMap;
|
||||
private ArrayList<String> titleList = new ArrayList<>();
|
||||
|
||||
public MarkInfoTab(IMessageEditorController controller, boolean editable) {
|
||||
this.controller = controller;
|
||||
@@ -197,6 +199,7 @@ public class BurpExtender implements IBurpExtender, IHttpListener, IMessageEdito
|
||||
* 创建MarkInfo表单
|
||||
*/
|
||||
public void makeTable(Map<String, String> dataMap) {
|
||||
ArrayList<String> lTitleList = new ArrayList<>();
|
||||
dataMap.keySet().forEach(i->{
|
||||
String[] extractData = dataMap.get(i).split("\n");
|
||||
Object[][] data = new Object[extractData.length][1];
|
||||
@@ -204,14 +207,23 @@ public class BurpExtender implements IBurpExtender, IHttpListener, IMessageEdito
|
||||
data[x][0] = extractData[x];
|
||||
// stdout.println(extractData[x]);
|
||||
}
|
||||
int indexOfTab = this.jTabbedPane.indexOfTab(i);
|
||||
JScrollPane jScrollPane = new JScrollPane(new JTable(data, new Object[] {"Information"}));
|
||||
JScrollPane jScrollPane = new JScrollPane(new JTable(data, new Object[]{"Information"}));
|
||||
lTitleList.add(i);
|
||||
this.jTabbedPane.addTab(i, jScrollPane);
|
||||
// 使用removeAll会导致UI出现空白的情况,为了改善用户侧体验,采用remove的方式进行删除
|
||||
});
|
||||
|
||||
/*
|
||||
* 使用removeAll会导致MarkInfo UI出现空白的情况,为了改善用户侧体验,采用remove的方式进行删除;
|
||||
* 采用全局ArrayList的方式遍历删除Tab,以此应对BurpSuite缓存机制导致的MarkInfo UI错误展示。
|
||||
*/
|
||||
titleList.forEach(t->{
|
||||
int indexOfTab = this.jTabbedPane.indexOfTab(t);
|
||||
if (indexOfTab != -1) {
|
||||
this.jTabbedPane.remove(indexOfTab);
|
||||
this.jTabbedPane.removeTabAt(indexOfTab);
|
||||
}
|
||||
});
|
||||
|
||||
titleList = lTitleList;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ public class ExtractContent {
|
||||
}
|
||||
});
|
||||
|
||||
// host: {Name, List}
|
||||
// 将提取的数据存放到全局变量中
|
||||
if (!host.isEmpty()) {
|
||||
map.keySet().forEach(i -> {
|
||||
Map<String, Object> tmpMap = map.get(i);
|
||||
|
||||
@@ -60,7 +60,6 @@ public class JTabbedPaneCloseButton extends JTabbedPane {
|
||||
|
||||
/** Button */
|
||||
public class CloseButtonTab extends JPanel {
|
||||
|
||||
public CloseButtonTab(final Component tab, String title, Icon icon) {
|
||||
setOpaque(false);
|
||||
FlowLayout flowLayout = new FlowLayout(FlowLayout.CENTER, 3, 3);
|
||||
|
||||
@@ -4,12 +4,15 @@ import burp.Config;
|
||||
import burp.yaml.LoadConfig;
|
||||
import burp.yaml.SetConfig;
|
||||
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
import com.squareup.okhttp.Request;
|
||||
import com.squareup.okhttp.Response;
|
||||
import java.io.FileOutputStream;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.Map;
|
||||
@@ -32,7 +35,7 @@ public class MainUI extends JPanel{
|
||||
setConn.deleteRules(ruleTabbedPane.getTitleAt(ruleTabbedPane.getSelectedIndex()));
|
||||
ruleTabbedPane.remove(ruleTabbedPane.getSelectedIndex());
|
||||
ruleTabbedPane.setSelectedIndex(ruleTabbedPane.getSelectedIndex()-1);
|
||||
}else{
|
||||
} else {
|
||||
SetConfig setConn = new SetConfig();
|
||||
setConn.deleteRules(ruleTabbedPane.getTitleAt(ruleTabbedPane.getSelectedIndex()));
|
||||
ruleTabbedPane.remove(ruleTabbedPane.getSelectedIndex());
|
||||
@@ -41,19 +44,25 @@ public class MainUI extends JPanel{
|
||||
}
|
||||
}
|
||||
|
||||
private void selectFileMouseClicked(MouseEvent e) {
|
||||
JFileChooser selectFile = new JFileChooser();
|
||||
selectFile.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
FileNameExtensionFilter filter = new FileNameExtensionFilter("Yaml File (.yml/.yaml)","yaml", "yml");
|
||||
selectFile.setFileFilter(filter);
|
||||
int selectFrame = selectFile.showDialog(new JLabel(),"Select");
|
||||
if (selectFrame == JFileChooser.APPROVE_OPTION){
|
||||
String configPath = selectFile.getSelectedFile().toString();
|
||||
reloadRule();
|
||||
loadConn.setConfigPath(configPath);
|
||||
configTextField.setText(configPath);
|
||||
private void onlineUpdateActionPerformed(ActionEvent e) {
|
||||
String url = "https://raw.githubusercontent.com/gh0stkey/HaE/gh-pages/Config.yml";
|
||||
OkHttpClient httpClient = new OkHttpClient();
|
||||
Request httpRequest = new Request.Builder().url(url).get().build();
|
||||
try {
|
||||
Response httpResponse = httpClient.newCall(httpRequest).execute();
|
||||
// 获取官方规则文件,在线更新写入
|
||||
String configFile = configTextField.getText();
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(configFile);
|
||||
fileOutputStream.write(httpResponse.body().bytes());
|
||||
JOptionPane.showMessageDialog(null, "Config file updated successfully!", "Error",
|
||||
JOptionPane.INFORMATION_MESSAGE);
|
||||
} catch (Exception ignored) {
|
||||
JOptionPane.showMessageDialog(null, "Please check your network!", "Error",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
new LoadConfig();
|
||||
reloadRule();
|
||||
}
|
||||
|
||||
private void reloadRule(){
|
||||
@@ -70,11 +79,11 @@ public class MainUI extends JPanel{
|
||||
ruleSwitch.setListen(true);
|
||||
}
|
||||
|
||||
private void reloadMouseClicked(MouseEvent e) {
|
||||
private void reloadActionPerformed(ActionEvent e) {
|
||||
reloadRule();
|
||||
}
|
||||
|
||||
private void excludeSuffixSaveMouseClicked(MouseEvent e) {
|
||||
private void excludeSuffixSaveActionPerformed(ActionEvent e) {
|
||||
LoadConfig loadCon = new LoadConfig();
|
||||
loadCon.setExcludeSuffix(excludeSuffixTextField.getText());
|
||||
}
|
||||
@@ -84,7 +93,7 @@ public class MainUI extends JPanel{
|
||||
rulePanel = new JPanel();
|
||||
configTextField = new JTextField();
|
||||
configLabel = new JLabel();
|
||||
selectFileButton = new JButton();
|
||||
onlineUpdateButton = new JButton();
|
||||
reloadButton = new JButton();
|
||||
excludeSuffixLabel = new JLabel();
|
||||
excludeSuffixTextField = new JTextField();
|
||||
@@ -111,35 +120,25 @@ public class MainUI extends JPanel{
|
||||
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
|
||||
new Insets(5, 0, 5, 5), 0, 0));
|
||||
|
||||
configLabel.setText("Config File Path:");
|
||||
configLabel.setText("Config Path:");
|
||||
rulePanel.add(configLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
|
||||
GridBagConstraints.WEST, GridBagConstraints.VERTICAL,
|
||||
new Insets(5, 5, 5, 5), 0, 0));
|
||||
|
||||
selectFileButton.setText("Select File ...");
|
||||
selectFileButton.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
selectFileMouseClicked(e);
|
||||
}
|
||||
});
|
||||
rulePanel.add(selectFileButton, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0,
|
||||
onlineUpdateButton.setText("Online Update");
|
||||
onlineUpdateButton.addActionListener(this::onlineUpdateActionPerformed);
|
||||
rulePanel.add(onlineUpdateButton, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0,
|
||||
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
|
||||
new Insets(5, 0, 5, 5), 0, 0));
|
||||
|
||||
reloadButton.setText("Reload");
|
||||
reloadButton.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
reloadMouseClicked(e);
|
||||
}
|
||||
});
|
||||
reloadButton.addActionListener(this::reloadActionPerformed);
|
||||
rulePanel.add(reloadButton, new GridBagConstraints(3, 0, 1, 1, 0.0, 0.0,
|
||||
|
||||
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
|
||||
new Insets(5, 0, 5, 5), 0, 0));
|
||||
|
||||
excludeSuffixLabel.setText("ExcludeSuffix:");
|
||||
excludeSuffixLabel.setText("Exclude Suffix:");
|
||||
rulePanel.add(excludeSuffixLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0,
|
||||
GridBagConstraints.SOUTHWEST, GridBagConstraints.NONE,
|
||||
new Insets(0, 5, 5, 5), 0, 0));
|
||||
@@ -148,12 +147,7 @@ public class MainUI extends JPanel{
|
||||
new Insets(0, 0, 0, 5), 0, 0));
|
||||
|
||||
excludeSuffixSaveButton.setText("Save");
|
||||
excludeSuffixSaveButton.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
excludeSuffixSaveMouseClicked(e);
|
||||
}
|
||||
});
|
||||
excludeSuffixSaveButton.addActionListener(this::excludeSuffixSaveActionPerformed);
|
||||
rulePanel.add(excludeSuffixSaveButton, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0,
|
||||
GridBagConstraints.SOUTH, GridBagConstraints.HORIZONTAL,
|
||||
new Insets(0, 0, 0, 5), 0, 0));
|
||||
@@ -175,7 +169,7 @@ public class MainUI extends JPanel{
|
||||
ruleSwitch = new TabTitleEditListener(ruleTabbedPane);
|
||||
ruleTabbedPane.addChangeListener(ruleSwitch);
|
||||
ruleTabbedPane.addMouseListener(ruleSwitch);
|
||||
closeTabMenuItem.addActionListener(e -> closeTabActionPerformed(e));
|
||||
closeTabMenuItem.addActionListener(this::closeTabActionPerformed);
|
||||
tabMenu.add(closeTabMenuItem);
|
||||
}
|
||||
|
||||
@@ -184,7 +178,7 @@ public class MainUI extends JPanel{
|
||||
private JPanel rulePanel;
|
||||
private JTextField configTextField;
|
||||
private JLabel configLabel;
|
||||
private JButton selectFileButton;
|
||||
private JButton onlineUpdateButton;
|
||||
private JButton reloadButton;
|
||||
private JLabel excludeSuffixLabel;
|
||||
private JTextField excludeSuffixTextField;
|
||||
|
||||
@@ -2,15 +2,14 @@ package burp.ui;
|
||||
|
||||
import burp.yaml.SetConfig;
|
||||
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.TableModelEvent;
|
||||
import javax.swing.event.TableModelListener;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
import javax.swing.table.TableRowSorter;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
@@ -24,7 +23,7 @@ public class RulePane extends JPanel {
|
||||
private SetConfig setConfig = new SetConfig();
|
||||
private Boolean isEdit = false;
|
||||
|
||||
private void ruleAddMouseClicked(MouseEvent e, JTabbedPane pane) {
|
||||
private void ruleAddActionPerformed(ActionEvent e, JTabbedPane pane) {
|
||||
RuleSetting ruleSettingPanel = new RuleSetting();
|
||||
int showState = JOptionPane.showConfirmDialog(null, ruleSettingPanel, "RuleSetting - Add Rule", JOptionPane.OK_OPTION);
|
||||
if(showState == 0){
|
||||
@@ -42,7 +41,7 @@ public class RulePane extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
private void ruleEditMouseClicked(MouseEvent e, JTabbedPane pane){
|
||||
private void ruleEditActionPerformed(ActionEvent e, JTabbedPane pane){
|
||||
if (ruleTable.getSelectedRowCount() >= 1){
|
||||
RuleSetting ruleSettingPanel = new RuleSetting();
|
||||
ruleSettingPanel.ruleNameTextField.setText(ruleTable.getValueAt(ruleTable.getSelectedRow(), 1).toString());
|
||||
@@ -71,7 +70,7 @@ public class RulePane extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
private void ruleRemoveMouseClicked(MouseEvent e, JTabbedPane pane){
|
||||
private void ruleRemoveActionPerformed(ActionEvent e, JTabbedPane pane){
|
||||
if (ruleTable.getSelectedRowCount() >= 1){
|
||||
int isOk = JOptionPane.showConfirmDialog(null, "Are your sure?", "RuleSetting - Delete Rule", JOptionPane.OK_OPTION);
|
||||
if (isOk == 0){
|
||||
@@ -109,11 +108,11 @@ public class RulePane extends JPanel {
|
||||
//---- addButton ----
|
||||
addButton.setText("Add");
|
||||
|
||||
addButton.addMouseListener(new MouseAdapter() {
|
||||
addButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
isEdit = true;
|
||||
ruleAddMouseClicked(e, pane);
|
||||
ruleAddActionPerformed(e, pane);
|
||||
model = (DefaultTableModel) ruleTable.getModel();
|
||||
isEdit = false;
|
||||
}
|
||||
@@ -125,11 +124,11 @@ public class RulePane extends JPanel {
|
||||
|
||||
//---- editButton ----
|
||||
editButton.setText("Edit");
|
||||
editButton.addMouseListener(new MouseAdapter() {
|
||||
editButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
isEdit = true;
|
||||
ruleEditMouseClicked(e, pane);
|
||||
ruleEditActionPerformed(e, pane);
|
||||
model = (DefaultTableModel) ruleTable.getModel();
|
||||
isEdit = false;
|
||||
}
|
||||
@@ -158,11 +157,11 @@ public class RulePane extends JPanel {
|
||||
//---- removeButton ----
|
||||
removeButton.setText("Remove");
|
||||
|
||||
removeButton.addMouseListener(new MouseAdapter() {
|
||||
removeButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
isEdit = true;
|
||||
ruleRemoveMouseClicked(e, pane);
|
||||
ruleRemoveActionPerformed(e, pane);
|
||||
model = (DefaultTableModel) ruleTable.getModel();
|
||||
isEdit = false;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ public class LoadConfig {
|
||||
|
||||
public LoadConfig() {
|
||||
// 构造函数,初始化配置
|
||||
|
||||
File HaEConfigPathFile = new File(HaEConfigPath);
|
||||
if (!(HaEConfigPathFile.exists() && HaEConfigPathFile.isDirectory())) {
|
||||
HaEConfigPathFile.mkdirs();
|
||||
@@ -146,18 +145,6 @@ public class LoadConfig {
|
||||
return resRule;
|
||||
}
|
||||
|
||||
// 设置配置路径
|
||||
public void setConfigPath(String filePath){
|
||||
Map<String,Object> r = new HashMap<>();
|
||||
r.put("configPath", filePath);
|
||||
r.put("excludeSuffix", getExcludeSuffix());
|
||||
try{
|
||||
Writer ws = new OutputStreamWriter(new FileOutputStream(SettingPath), StandardCharsets.UTF_8);
|
||||
yaml.dump(r, ws);
|
||||
}catch (Exception ex){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// 设置不包含的后缀名
|
||||
public void setExcludeSuffix(String excludeSuffix){
|
||||
|
||||
Reference in New Issue
Block a user