diff --git a/src/main/java/hae/Config.java b/src/main/java/hae/Config.java index 74ef3d1..2e73e39 100644 --- a/src/main/java/hae/Config.java +++ b/src/main/java/hae/Config.java @@ -12,6 +12,8 @@ public class Config { public static String status = "404"; + public static String size = "0"; + public static String boundary = "\n\t\n"; public static String[] scope = new String[]{ diff --git a/src/main/java/hae/HaE.java b/src/main/java/hae/HaE.java index dda4e19..df6ee25 100644 --- a/src/main/java/hae/HaE.java +++ b/src/main/java/hae/HaE.java @@ -18,7 +18,7 @@ public class HaE implements BurpExtension { @Override public void initialize(MontoyaApi api) { // 设置扩展名称 - String version = "3.3.2"; + String version = "3.3.3"; api.extension().setName(String.format("HaE (%s) - Highlighter and Extractor", version)); // 加载扩展后输出的项目信息 @@ -30,7 +30,7 @@ public class HaE implements BurpExtension { // 配置文件加载 ConfigLoader configLoader = new ConfigLoader(api); - MessageTableModel messageTableModel = new MessageTableModel(api); + MessageTableModel messageTableModel = new MessageTableModel(api, configLoader); // 注册Tab页(用于查询数据) api.userInterface().registerSuiteTab("HaE", new Main(api, configLoader, messageTableModel)); diff --git a/src/main/java/hae/component/Config.java b/src/main/java/hae/component/Config.java index cb9a40a..d45762c 100644 --- a/src/main/java/hae/component/Config.java +++ b/src/main/java/hae/component/Config.java @@ -66,7 +66,7 @@ public class Config extends JPanel { constraints.gridx = 1; JTabbedPane configTabbedPanel = new JTabbedPane(); - String[] settingMode = new String[]{"Exclude suffix", "Block host", "Exclude status"}; + String[] settingMode = new String[]{"Exclude suffix", "Block host", "Exclude status", "Limit size"}; JPanel settingPanel = createConfigTablePanel(settingMode, "Setting"); JPanel scopePanel = getScopePanel(); JScrollPane scopeScrollPane = new JScrollPane(scopePanel); @@ -153,6 +153,13 @@ public class Config extends JPanel { configLoader.setExcludeStatus(values); } } + + if (selected.equals("Limit size")) { + if (!values.equals(configLoader.getExcludeStatus()) && !values.isEmpty()) { + String[] limit = values.split("\\|"); + configLoader.setLimitSize(limit[limit.length - 1]); + } + } } }; } @@ -175,6 +182,10 @@ public class Config extends JPanel { if (selected.equals("Exclude status")) { addDataToTable(configLoader.getExcludeStatus().replaceAll("\\|", "\r\n"), model); } + + if (selected.equals("Limit size")) { + addDataToTable(configLoader.getLimitSize(), model); + } } }; } @@ -279,13 +290,13 @@ public class Config extends JPanel { settingPanel.add(inputPanel, BorderLayout.CENTER); - addButton.addActionListener(e -> addActionPerformed(e, model, addTextField)); + addButton.addActionListener(e -> addActionPerformed(e, model, addTextField, setTypeComboBox.getSelectedItem().toString())); addTextField.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER) { - addActionPerformed(null, model, addTextField); + addActionPerformed(null, model, addTextField, setTypeComboBox.getSelectedItem().toString()); } } }); @@ -294,7 +305,9 @@ public class Config extends JPanel { Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); try { String data = (String) clipboard.getData(DataFlavor.stringFlavor); - + if (setTypeComboBox.getSelectedItem().toString().equals("Limit size")) { + model.setRowCount(0); + } if (data != null && !data.isEmpty()) { addDataToTable(data, model); } @@ -385,13 +398,16 @@ public class Config extends JPanel { configLoader.setScope(String.join("|", HaEScope)); } - private void addActionPerformed(ActionEvent e, DefaultTableModel model, JTextField addTextField) { + private void addActionPerformed(ActionEvent e, DefaultTableModel model, JTextField addTextField, String comboBoxSelected) { String addTextFieldText = addTextField.getText(); - if (!addTextFieldText.equals(defaultText)) { + if (addTextField.getForeground().equals(Color.BLACK)) { + if (comboBoxSelected.equals("Limit size")) { + model.setRowCount(0); + } addDataToTable(addTextFieldText, model); + addTextField.setText(""); + addTextField.requestFocusInWindow(); } - addTextField.setText(""); - addTextField.requestFocusInWindow(); } private void onlineUpdateActionPerformed(ActionEvent e) { diff --git a/src/main/java/hae/component/board/Databoard.java b/src/main/java/hae/component/board/Databoard.java index 750894a..681a15f 100644 --- a/src/main/java/hae/component/board/Databoard.java +++ b/src/main/java/hae/component/board/Databoard.java @@ -419,8 +419,8 @@ public class Databoard extends JPanel { JTable taskStatusTable = new JTable(taskStatusTableModel); for (Object[] data : dataList) { - int rowCount = taskStatusTable.getRowCount(); - int id = rowCount > 0 ? (Integer) taskStatusTable.getValueAt(rowCount - 1, 0) + 1 : 1; + int rowCount = taskStatusTableModel.getRowCount(); + int id = rowCount > 0 ? (Integer) taskStatusTableModel.getValueAt(rowCount - 1, 0) + 1 : 1; Object[] rowData = new Object[data.length + 1]; rowData[0] = id; System.arraycopy(data, 0, rowData, 1, data.length); diff --git a/src/main/java/hae/component/board/message/MessageTableModel.java b/src/main/java/hae/component/board/message/MessageTableModel.java index 3943a8f..7b69890 100644 --- a/src/main/java/hae/component/board/message/MessageTableModel.java +++ b/src/main/java/hae/component/board/message/MessageTableModel.java @@ -1,7 +1,6 @@ package hae.component.board.message; import burp.api.montoya.MontoyaApi; -import burp.api.montoya.core.ByteArray; import burp.api.montoya.http.message.HttpHeader; import burp.api.montoya.http.message.HttpRequestResponse; import burp.api.montoya.http.message.requests.HttpRequest; @@ -11,6 +10,7 @@ import burp.api.montoya.ui.editor.HttpRequestEditor; import burp.api.montoya.ui.editor.HttpResponseEditor; import hae.Config; import hae.cache.CachePool; +import hae.utils.ConfigLoader; import hae.utils.project.FileProcessor; import hae.utils.string.HashCalculator; import hae.utils.string.StringProcessor; @@ -23,6 +23,8 @@ import javax.swing.table.TableRowSorter; import java.nio.charset.StandardCharsets; import java.text.MessageFormat; import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; @@ -30,15 +32,17 @@ import static burp.api.montoya.ui.editor.EditorOptions.READ_ONLY; public class MessageTableModel extends AbstractTableModel { private final MontoyaApi api; + private final ConfigLoader configLoader; private final MessageTable messageTable; private final JSplitPane splitPane; private final LinkedList log = new LinkedList<>(); private final LinkedList filteredLog; private SwingWorker currentWorker; - public MessageTableModel(MontoyaApi api) { + public MessageTableModel(MontoyaApi api, ConfigLoader configLoader) { this.filteredLog = new LinkedList<>(); this.api = api; + this.configLoader = configLoader; JTabbedPane messageTab = new JTabbedPane(); UserInterface userInterface = api.userInterface(); @@ -435,7 +439,7 @@ public class MessageTableModel extends AbstractTableModel { public class MessageTable extends JTable { private MessageEntry messageEntry; - private SwingWorker currentWorker; + private final ExecutorService executorService; private int lastSelectedIndex = -1; private final HttpRequestEditor requestEditor; private final HttpResponseEditor responseEditor; @@ -444,52 +448,31 @@ public class MessageTableModel extends AbstractTableModel { super(messageTableModel); this.requestEditor = requestEditor; this.responseEditor = responseEditor; + this.executorService = Executors.newSingleThreadExecutor(); } @Override public void changeSelection(int row, int col, boolean toggle, boolean extend) { super.changeSelection(row, col, toggle, extend); - - if (currentWorker != null && !currentWorker.isDone()) { - currentWorker.cancel(true); + int selectedIndex = convertRowIndexToModel(row); + if (lastSelectedIndex != selectedIndex) { + lastSelectedIndex = selectedIndex; + executorService.execute(this::getSelectedMessage); } + } - currentWorker = new SwingWorker<>() { - @Override - protected ByteArray[] doInBackground() { - int selectedIndex = convertRowIndexToModel(row); - if (lastSelectedIndex != selectedIndex) { - lastSelectedIndex = selectedIndex; - messageEntry = filteredLog.get(selectedIndex); + private void getSelectedMessage() { + messageEntry = filteredLog.get(lastSelectedIndex); - HttpRequestResponse httpRequestResponse = messageEntry.getRequestResponse(); + HttpRequestResponse httpRequestResponse = messageEntry.getRequestResponse(); - ByteArray requestByte = httpRequestResponse.request().toByteArray(); - ByteArray responseByte = httpRequestResponse.response().toByteArray(); - - ByteArray[] httpByteArray = new ByteArray[2]; - httpByteArray[0] = requestByte; - httpByteArray[1] = responseByte; - return httpByteArray; - } - - return null; - } - - @Override - protected void done() { - try { - ByteArray[] retByteArray = get(); - if (retByteArray != null) { - requestEditor.setRequest(HttpRequest.httpRequest(messageEntry.getRequestResponse().httpService(), retByteArray[0])); - responseEditor.setResponse(HttpResponse.httpResponse(retByteArray[1])); - } - } catch (Exception ignored) { - } - } - }; - - currentWorker.execute(); + requestEditor.setRequest(HttpRequest.httpRequest(messageEntry.getRequestResponse().httpService(), httpRequestResponse.request().toByteArray())); + int responseSizeWithMb = httpRequestResponse.response().toString().length() / 1024 / 1024; + if ((responseSizeWithMb < Integer.parseInt(configLoader.getLimitSize())) || configLoader.getLimitSize().equals("0")) { + responseEditor.setResponse(httpRequestResponse.response()); + } else { + responseEditor.setResponse(HttpResponse.httpResponse("Exceeds length limit.")); + } } } } diff --git a/src/main/java/hae/component/board/table/Datatable.java b/src/main/java/hae/component/board/table/Datatable.java index 3387c47..f9dcdd3 100644 --- a/src/main/java/hae/component/board/table/Datatable.java +++ b/src/main/java/hae/component/board/table/Datatable.java @@ -23,6 +23,7 @@ import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.lang.reflect.Type; +import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Map; @@ -34,6 +35,7 @@ public class Datatable extends JPanel { private final JTable dataTable; private final DefaultTableModel dataTableModel; private final JTextField searchField; + private final JTextField secondSearchField; private final TableRowSorter sorter; private final JCheckBox searchMode = new JCheckBox("Reverse search"); private final String tabName; @@ -52,7 +54,8 @@ public class Datatable extends JPanel { this.dataTable = new JTable(dataTableModel); this.sorter = new TableRowSorter<>(dataTableModel); - this.searchField = new JTextField(); + this.searchField = new JTextField(10); + this.secondSearchField = new JTextField(10); this.aiEmpoweredMenu = new JPopupMenu(); this.footerPanel = new JPanel(new BorderLayout(0, 5)); @@ -80,11 +83,7 @@ public class Datatable extends JPanel { } } - // 设置灰色默认文本 - String searchText = "Search"; - UIEnhancer.setTextFieldPlaceholder(searchField, searchText); - - // 监听输入框内容输入、更新、删除 + UIEnhancer.setTextFieldPlaceholder(searchField, "Search"); searchField.getDocument().addDocumentListener(new DocumentListener() { @Override public void insertUpdate(DocumentEvent e) { @@ -103,6 +102,25 @@ public class Datatable extends JPanel { }); + UIEnhancer.setTextFieldPlaceholder(secondSearchField, "Second search"); + secondSearchField.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + performSearch(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + performSearch(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + performSearch(); + } + + }); + // 设置布局 JScrollPane scrollPane = new JScrollPane(dataTable); scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); @@ -162,6 +180,8 @@ public class Datatable extends JPanel { optionsPanel.add(Box.createHorizontalStrut(5)); optionsPanel.add(searchField); optionsPanel.add(Box.createHorizontalStrut(5)); + optionsPanel.add(secondSearchField); + optionsPanel.add(Box.createHorizontalStrut(5)); optionsPanel.add(aiEmpoweredButton); footerPanel.setBorder(BorderFactory.createEmptyBorder(2, 3, 5, 3)); @@ -252,29 +272,61 @@ public class Datatable extends JPanel { } private void performSearch() { + RowFilter firstRowFilter = applyFirstSearchFilter(); + RowFilter secondRowFilter = applySecondFilter(); if (searchField.getForeground().equals(Color.BLACK)) { - RowFilter rowFilter = new RowFilter() { - public boolean include(Entry entry) { - String searchFieldTextText = searchField.getText(); - Pattern pattern = null; - try { - pattern = Pattern.compile(searchFieldTextText, Pattern.CASE_INSENSITIVE); - } catch (Exception ignored) { - } - - String entryValue = ((String) entry.getValue(1)).toLowerCase(); - searchFieldTextText = searchFieldTextText.toLowerCase(); - if (pattern != null) { - return searchFieldTextText.isEmpty() || pattern.matcher(entryValue).find() != searchMode.isSelected(); - } else { - return searchFieldTextText.isEmpty() || entryValue.contains(searchFieldTextText) != searchMode.isSelected(); - } - } - }; - sorter.setRowFilter(rowFilter); + sorter.setRowFilter(firstRowFilter); + if (secondSearchField.getForeground().equals(Color.BLACK)) { + List> filters = new ArrayList<>(); + filters.add(firstRowFilter); + filters.add(secondRowFilter); + sorter.setRowFilter(RowFilter.andFilter(filters)); + } } } + private RowFilter applyFirstSearchFilter() { + return new RowFilter() { + public boolean include(Entry entry) { + String searchFieldTextText = searchField.getText(); + Pattern pattern = null; + try { + pattern = Pattern.compile(searchFieldTextText, Pattern.CASE_INSENSITIVE); + } catch (Exception ignored) { + } + + String entryValue = ((String) entry.getValue(1)).toLowerCase(); + searchFieldTextText = searchFieldTextText.toLowerCase(); + if (pattern != null) { + return searchFieldTextText.isEmpty() || pattern.matcher(entryValue).find() != searchMode.isSelected(); + } else { + return searchFieldTextText.isEmpty() || entryValue.contains(searchFieldTextText) != searchMode.isSelected(); + } + } + }; + } + + private RowFilter applySecondFilter() { + return new RowFilter() { + public boolean include(Entry entry) { + String searchFieldTextText = secondSearchField.getText(); + Pattern pattern = null; + try { + pattern = Pattern.compile(searchFieldTextText, Pattern.CASE_INSENSITIVE); + } catch (Exception ignored) { + } + + String entryValue = ((String) entry.getValue(1)).toLowerCase(); + searchFieldTextText = searchFieldTextText.toLowerCase(); + if (pattern != null) { + return searchFieldTextText.isEmpty() || pattern.matcher(entryValue).find(); + } else { + return searchFieldTextText.isEmpty() || entryValue.contains(searchFieldTextText); + } + } + }; + } + public void setTableListener(MessageTableModel messagePanel) { // 表格复制功能 dataTable.setTransferHandler(new TransferHandler() { diff --git a/src/main/java/hae/utils/ConfigLoader.java b/src/main/java/hae/utils/ConfigLoader.java index 4eab136..d1e9bb8 100644 --- a/src/main/java/hae/utils/ConfigLoader.java +++ b/src/main/java/hae/utils/ConfigLoader.java @@ -80,6 +80,7 @@ public class ConfigLoader { r.put("ExcludeSuffix", getExcludeSuffix()); r.put("BlockHost", getBlockHost()); r.put("ExcludeStatus", getExcludeStatus()); + r.put("LimitSize", getLimitSize()); r.put("HaEScope", getScope()); try { Writer ws = new OutputStreamWriter(Files.newOutputStream(Paths.get(configFilePath)), StandardCharsets.UTF_8); @@ -160,6 +161,10 @@ public class ConfigLoader { return getValueFromConfig("ExcludeStatus", Config.status); } + public String getLimitSize() { + return getValueFromConfig("LimitSize", Config.size); + } + public String getScope() { return getValueFromConfig("HaEScope", Config.scopeOptions); } @@ -206,6 +211,10 @@ public class ConfigLoader { setValueToConfig("ExcludeStatus", status); } + public void setLimitSize(String size) { + setValueToConfig("LimitSize", size); + } + public void setScope(String scope) { setValueToConfig("HaEScope", scope); } diff --git a/src/main/resources/rules/Rules.yml b/src/main/resources/rules/Rules.yml index d577b98..0614b75 100644 --- a/src/main/resources/rules/Rules.yml +++ b/src/main/resources/rules/Rules.yml @@ -1,284 +1,284 @@ rules: -- group: Fingerprint - rule: - - name: Shiro - loaded: true - f_regex: (=deleteMe|rememberMe=) - s_regex: '' - format: '{0}' - color: green - scope: any header - engine: dfa - sensitive: true - - name: JSON Web Token - loaded: true - f_regex: (eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9._-]{10,}|eyJ[A-Za-z0-9_\/+-]{10,}\.[A-Za-z0-9._\/+-]{10,}) - s_regex: '' - format: '{0}' - color: green - scope: any - engine: nfa - sensitive: true - - name: Swagger UI - loaded: true - f_regex: ((swagger-ui.html)|(\"swagger\":)|(Swagger UI)|(swaggerUi)|(swaggerVersion)) - s_regex: '' - format: '{0}' - color: red - scope: response body - engine: dfa - sensitive: false - - name: Ueditor - loaded: true - f_regex: (ueditor\.(config|all)\.js) - s_regex: '' - format: '{0}' - color: green - scope: response body - engine: dfa - sensitive: false - - name: Druid - loaded: true - f_regex: (Druid Stat Index) - s_regex: '' - format: '{0}' - color: orange - scope: response body - engine: dfa - sensitive: false -- group: Maybe Vulnerability - rule: - - name: Java Deserialization - loaded: true - f_regex: (javax\.faces\.ViewState) - s_regex: '' - format: '{0}' - color: yellow - scope: response body - engine: dfa - sensitive: false - - name: Debug Logic Parameters - loaded: true - f_regex: ((access=)|(adm=)|(admin=)|(alter=)|(cfg=)|(clone=)|(config=)|(create=)|(dbg=)|(debug=)|(delete=)|(disable=)|(edit=)|(enable=)|(exec=)|(execute=)|(grant=)|(load=)|(make=)|(modify=)|(rename=)|(reset=)|(root=)|(shell=)|(test=)|(toggl=)) - s_regex: '' - format: '{0}' - color: cyan - scope: request - engine: dfa - sensitive: false - - name: URL As A Value - loaded: true - f_regex: (=(https?)(://|%3a%2f%2f)) - s_regex: '' - format: '{0}' - color: cyan - scope: any - engine: nfa - sensitive: false - - name: Upload Form - loaded: true - f_regex: (type\=\"file\") - s_regex: '' - format: '{0}' - color: yellow - scope: response body - engine: dfa - sensitive: false - - name: DoS Paramters - loaded: true - f_regex: ((size=)|(page=)|(num=)|(limit=)|(start=)|(end=)|(count=)) - s_regex: '' - format: '{0}' - color: cyan - scope: request - engine: dfa - sensitive: false -- group: Basic Information - rule: - - name: Email - loaded: true - f_regex: (([a-z0-9]+[_|\.])*[a-z0-9]+@([a-z0-9]+[-|_|\.])*[a-z0-9]+\.((?!js|css|jpg|jpeg|png|ico)[a-z]{2,5})) - s_regex: '' - format: '{0}' - color: yellow - scope: response - engine: nfa - sensitive: false - - name: Chinese IDCard - loaded: true - f_regex: '[^0-9]((\d{8}(0\d|10|11|12)([0-2]\d|30|31)\d{3}$)|(\d{6}(18|19|20)\d{2}(0[1-9]|10|11|12)([0-2]\d|30|31)\d{3}(\d|X|x)))[^0-9]' - s_regex: '' - format: '{0}' - color: orange - scope: response body - engine: nfa - sensitive: true - - name: Chinese Mobile Number - loaded: true - f_regex: '[^\w]((?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[189]))\d{8})[^\w]' - s_regex: '' - format: '{0}' - color: orange - scope: response body - engine: nfa - sensitive: false - - name: Internal IP Address - loaded: true - f_regex: '[^0-9]((127\.0\.0\.1)|(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}))' - s_regex: '' - format: '{0}' - color: cyan - scope: response - engine: nfa - sensitive: true - - name: MAC Address - loaded: true - f_regex: (^([a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5})|[^a-zA-Z0-9]([a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5})) - s_regex: '' - format: '{0}' - color: green - scope: response - engine: nfa - sensitive: true -- group: Sensitive Information - rule: - - name: Cloud Key - loaded: true - f_regex: (((access)(|-|_)(key)(|-|_)(id|secret))|(LTAI[a-z0-9]{12,20})) - s_regex: '' - format: '{0}' - color: yellow - scope: any - engine: nfa - sensitive: false - - name: Windows File/Dir Path - loaded: true - f_regex: '[^\w](([a-zA-Z]:\\(?:\w+\\?)*)|([a-zA-Z]:\\(?:\w+\\)*\w+\.\w+))' - s_regex: '' - format: '{0}' - color: green - scope: response - engine: nfa - sensitive: true - - name: Password Field - loaded: true - f_regex: ((|'|")(|[\w]{1,10})([p](ass|wd|asswd|assword))(|[\w]{1,10})(|'|")(:|=)( - |)('|")(.*?)('|")(|,)) - s_regex: '' - format: '{0}' - color: yellow - scope: response body - engine: nfa - sensitive: false - - name: Username Field - loaded: true - f_regex: ((|'|")(|[\w]{1,10})(([u](ser|name|sername))|(account)|((((create|update)((d|r)|(by|on|at)))|(creator))))(|[\w]{1,10})(|'|")(:|=)( - |)('|")(.*?)('|")(|,)) - s_regex: '' - format: '{0}' - color: green - scope: response body - engine: nfa - sensitive: false - - name: WeCom Key - loaded: true - f_regex: ((corp)(id|secret)) - s_regex: '' - format: '{0}' - color: green - scope: response body - engine: dfa - sensitive: false - - name: JDBC Connection - loaded: true - f_regex: (jdbc:[a-z:]+://[a-z0-9\.\-_:;=/@?,&]+) - s_regex: '' - format: '{0}' - color: yellow - scope: any - engine: nfa - sensitive: false - - name: Authorization Header - loaded: true - f_regex: ((basic [a-z0-9=:_\+\/-]{5,100})|(bearer [a-z0-9_.=:_\+\/-]{5,100})) - s_regex: '' - format: '{0}' - color: yellow - scope: response body - engine: nfa - sensitive: false - - name: Sensitive Field - loaded: true - f_regex: ((\[)?('|")?([\w]{0,10})((key)|(secret)|(token)|(config)|(auth)|(access)|(admin)|(ticket))([\w]{0,10})('|")?(\])?( - |)(:|=)( |)('|")(.*?)('|")(|,)) - s_regex: '' - format: '{0}' - color: yellow - scope: response - engine: nfa - sensitive: false -- group: Other - rule: - - name: Linkfinder - loaded: true - f_regex: (?:"|')(((?:[a-zA-Z]{1,10}://|//)[^"'/]{1,}\.[a-zA-Z]{2,}[^"']{0,})|((?:/|\.\./|\./)[^"'><,;|*()(%%$^/\\\[\]][^"'><,;|()]{1,})|([a-zA-Z0-9_\-/]{1,}/[a-zA-Z0-9_\-/]{1,}\.(?:[a-zA-Z]{1,4}|action)(?:[\?|#][^"|']{0,}|))|([a-zA-Z0-9_\-/]{1,}/[a-zA-Z0-9_\-/]{3,}(?:[\?|#][^"|']{0,}|))|([a-zA-Z0-9_\-]{1,}\.(?:\w)(?:[\?|#][^"|']{0,}|)))(?:"|') - s_regex: '' - format: '{0}' - color: gray - scope: response body - engine: nfa - sensitive: true - - name: Source Map - loaded: true - f_regex: (\.js\.map) - s_regex: '' - format: '{0}' - color: pink - scope: response body - engine: dfa - sensitive: false - - name: Create Script - loaded: true - f_regex: (\{[^{}]*\}\s*\[[^\s]*\]\s*\+\s*"[^\s]*\.js") - s_regex: '"?([\w].*?)"?:"(.*?)"' - format: '{0}.{1}' - color: green - scope: response body - engine: nfa - sensitive: false - - name: URL Schemes - loaded: true - f_regex: ((?![http]|[https])(([-A-Za-z0-9]{1,20})://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|])) - s_regex: '' - format: '{0}' - color: yellow - scope: response body - engine: nfa - sensitive: false - - name: Router Push - loaded: true - f_regex: (\$router\.push) - s_regex: '' - format: '{0}' - color: magenta - scope: response body - engine: dfa - sensitive: false - - name: All URL - loaded: true - f_regex: (https?://[-A-Za-z0-9+&@#/%?=~_|!:,.;\u4E00-\u9FFF]+[-A-Za-z0-9+&@#/%=~_|]) - s_regex: '' - format: '{0}' - color: gray - scope: response body - engine: nfa - sensitive: true - - name: Request URI - loaded: true - f_regex: ' ((?!.*\.js(\?.*)?$)(.*?[^.js$])) ' - s_regex: '' - format: '{0}' - color: gray - scope: request line - engine: nfa - sensitive: false + - group: Fingerprint + rule: + - name: Shiro + loaded: true + f_regex: (=deleteMe|rememberMe=) + s_regex: '' + format: '{0}' + color: green + scope: any header + engine: dfa + sensitive: true + - name: JSON Web Token + loaded: true + f_regex: (eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9._-]{10,}|eyJ[A-Za-z0-9_\/+-]{10,}\.[A-Za-z0-9._\/+-]{10,}) + s_regex: '' + format: '{0}' + color: green + scope: any + engine: nfa + sensitive: true + - name: Swagger UI + loaded: true + f_regex: ((swagger-ui.html)|(\"swagger\":)|(Swagger UI)|(swaggerUi)|(swaggerVersion)) + s_regex: '' + format: '{0}' + color: red + scope: response body + engine: dfa + sensitive: false + - name: Ueditor + loaded: true + f_regex: (ueditor\.(config|all)\.js) + s_regex: '' + format: '{0}' + color: green + scope: response body + engine: dfa + sensitive: false + - name: Druid + loaded: true + f_regex: (Druid Stat Index) + s_regex: '' + format: '{0}' + color: orange + scope: response body + engine: dfa + sensitive: false + - group: Maybe Vulnerability + rule: + - name: Java Deserialization + loaded: true + f_regex: (javax\.faces\.ViewState) + s_regex: '' + format: '{0}' + color: yellow + scope: response body + engine: dfa + sensitive: false + - name: Debug Logic Parameters + loaded: true + f_regex: ((access=)|(adm=)|(admin=)|(alter=)|(cfg=)|(clone=)|(config=)|(create=)|(dbg=)|(debug=)|(delete=)|(disable=)|(edit=)|(enable=)|(exec=)|(execute=)|(grant=)|(load=)|(make=)|(modify=)|(rename=)|(reset=)|(root=)|(shell=)|(test=)|(toggl=)) + s_regex: '' + format: '{0}' + color: cyan + scope: request + engine: dfa + sensitive: false + - name: URL As A Value + loaded: true + f_regex: (=(https?)(://|%3a%2f%2f)) + s_regex: '' + format: '{0}' + color: cyan + scope: any + engine: nfa + sensitive: false + - name: Upload Form + loaded: true + f_regex: (type\=\"file\") + s_regex: '' + format: '{0}' + color: yellow + scope: response body + engine: dfa + sensitive: false + - name: DoS Paramters + loaded: true + f_regex: ((size=)|(page=)|(num=)|(limit=)|(start=)|(end=)|(count=)) + s_regex: '' + format: '{0}' + color: cyan + scope: request + engine: dfa + sensitive: false + - group: Basic Information + rule: + - name: Email + loaded: true + f_regex: (([a-z0-9]+[_|\.])*[a-z0-9]+@([a-z0-9]+[-|_|\.])*[a-z0-9]+\.((?!js|css|jpg|jpeg|png|ico)[a-z]{2,5})) + s_regex: '' + format: '{0}' + color: yellow + scope: response + engine: nfa + sensitive: false + - name: Chinese IDCard + loaded: true + f_regex: '[^0-9]((\d{8}(0\d|10|11|12)([0-2]\d|30|31)\d{3}$)|(\d{6}(18|19|20)\d{2}(0[1-9]|10|11|12)([0-2]\d|30|31)\d{3}(\d|X|x)))[^0-9]' + s_regex: '' + format: '{0}' + color: orange + scope: response body + engine: nfa + sensitive: true + - name: Chinese Mobile Number + loaded: true + f_regex: '[^\w]((?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[189]))\d{8})[^\w]' + s_regex: '' + format: '{0}' + color: orange + scope: response body + engine: nfa + sensitive: false + - name: Internal IP Address + loaded: true + f_regex: '[^0-9]((127\.0\.0\.1)|(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}))' + s_regex: '' + format: '{0}' + color: cyan + scope: response + engine: nfa + sensitive: true + - name: MAC Address + loaded: true + f_regex: (^([a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5})|[^a-zA-Z0-9]([a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5})) + s_regex: '' + format: '{0}' + color: green + scope: response + engine: nfa + sensitive: true + - group: Sensitive Information + rule: + - name: Cloud Key + loaded: true + f_regex: (((access)(|-|_)(key)(|-|_)(id|secret))|(LTAI[a-z0-9]{12,20})) + s_regex: '' + format: '{0}' + color: yellow + scope: any + engine: nfa + sensitive: false + - name: Windows File/Dir Path + loaded: true + f_regex: '[^\w](([a-zA-Z]:\\(?:\w+\\?)*)|([a-zA-Z]:\\(?:\w+\\)*\w+\.\w+))' + s_regex: '' + format: '{0}' + color: green + scope: response + engine: nfa + sensitive: true + - name: Password Field + loaded: true + f_regex: ((|'|")(|[\w]{1,10})([p](ass|wd|asswd|assword))(|[\w]{1,10})(|'|")(:|=)( + |)('|")(.*?)('|")(|,)) + s_regex: '' + format: '{0}' + color: yellow + scope: response body + engine: nfa + sensitive: false + - name: Username Field + loaded: true + f_regex: ((|'|")(|[\w]{1,10})(([u](ser|name|sername))|(account)|((((create|update)((d|r)|(by|on|at)))|(creator))))(|[\w]{1,10})(|'|")(:|=)( + |)('|")(.*?)('|")(|,)) + s_regex: '' + format: '{0}' + color: green + scope: response body + engine: nfa + sensitive: false + - name: WeCom Key + loaded: true + f_regex: ((corp)(id|secret)) + s_regex: '' + format: '{0}' + color: green + scope: response body + engine: dfa + sensitive: false + - name: JDBC Connection + loaded: true + f_regex: (jdbc:[a-z:]+://[a-z0-9\.\-_:;=/@?,&]+) + s_regex: '' + format: '{0}' + color: yellow + scope: any + engine: nfa + sensitive: false + - name: Authorization Header + loaded: true + f_regex: ((basic [a-z0-9=:_\+\/-]{5,100})|(bearer [a-z0-9_.=:_\+\/-]{5,100})) + s_regex: '' + format: '{0}' + color: yellow + scope: response body + engine: nfa + sensitive: false + - name: Sensitive Field + loaded: true + f_regex: ((\[)?('|")?([\w]{0,10})((key)|(secret)|(token)|(config)|(auth)|(access)|(admin)|(ticket))([\w]{0,10})('|")?(\])?( + |)(:|=)( |)('|")(.*?)('|")(|,)) + s_regex: '' + format: '{0}' + color: yellow + scope: response + engine: nfa + sensitive: false + - group: Other + rule: + - name: Linkfinder + loaded: true + f_regex: (?:"|')(((?:[a-zA-Z]{1,10}://|//)[^"'/]{1,}\.[a-zA-Z]{2,}[^"']{0,})|((?:/|\.\./|\./)[^"'><,;|*()(%%$^/\\\[\]][^"'><,;|()]{1,})|([a-zA-Z0-9_\-/]{1,}/[a-zA-Z0-9_\-/]{1,}\.(?:[a-zA-Z]{1,4}|action)(?:[\?|#][^"|']{0,}|))|([a-zA-Z0-9_\-/]{1,}/[a-zA-Z0-9_\-/]{3,}(?:[\?|#][^"|']{0,}|))|([a-zA-Z0-9_\-]{1,}\.(?:\w)(?:[\?|#][^"|']{0,}|)))(?:"|') + s_regex: '' + format: '{0}' + color: gray + scope: response body + engine: nfa + sensitive: true + - name: Source Map + loaded: true + f_regex: (\.js\.map) + s_regex: '' + format: '{0}' + color: pink + scope: response body + engine: dfa + sensitive: false + - name: Create Script + loaded: true + f_regex: (\{[^{}]*\}\s*\[[^\s]*\]\s*\+\s*"[^\s]*\.js") + s_regex: '"?([\w].*?)"?:"(.*?)"' + format: '{0}.{1}' + color: green + scope: response body + engine: nfa + sensitive: false + - name: URL Schemes + loaded: true + f_regex: ((?![http]|[https])(([-A-Za-z0-9]{1,20})://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|])) + s_regex: '' + format: '{0}' + color: yellow + scope: response body + engine: nfa + sensitive: false + - name: Router Push + loaded: true + f_regex: (\$router\.push) + s_regex: '' + format: '{0}' + color: magenta + scope: response body + engine: dfa + sensitive: false + - name: All URL + loaded: true + f_regex: (https?://[-A-Za-z0-9+&@#/%?=~_|!:,.;\u4E00-\u9FFF]+[-A-Za-z0-9+&@#/%=~_|]) + s_regex: '' + format: '{0}' + color: gray + scope: response body + engine: nfa + sensitive: true + - name: Request URI + loaded: true + f_regex: ' ((?!.*\.js(\?.*)?$)(.*?[^.js$])) ' + s_regex: '' + format: '{0}' + color: gray + scope: request line + engine: nfa + sensitive: false