乌云漏洞库payload-Burp插件源码分析
2020-03-24 11:18:41 Author: mp.weixin.qq.com(查看原文) 阅读量:131 收藏


文章来源:重生信息安全

前言

最近使用了下这个工具感觉确实很好用在想着自己能不能进行扩展,所以就对其的源码进行了分析,分享一下

 
关于此插件的下载地址是:
https://github.com/boy-hack/wooyun-payload

使用详情如下

下面就直接从其的源码入手,BurpExtender.java的代码分析如下所示,此代码主要是实现burpsuite当中要定义插件的要求
package burp;

import wooyun.GUI;import wooyun.Menu;

import javax.swing.*;import java.io.PrintWriter;import java.util.ArrayList;import java.util.List;

//所有的插件必须实现此接口。实现的类名必须为“BurpExtender”。在 burp包中,必须申明为 public ,并且必须提供一个默认的构造器。//对于IContextMenuFactory接口提供了下面的方法//#!java java.util.List<javax.swing.JMenuItem> createMenuItems(IContextMenuInvocation invocation)public class BurpExtender implements IBurpExtender, IContextMenuFactory { public PrintWriter stdout; public PrintWriter stderr; //这个接口包含许多帮助器方法,这些扩展可以用来帮助处理Burp扩展中出现的各种常见任务。扩展可以调用BurpExtenderCallbacks.getHelpers获取该接口的实例。 public IExtensionHelpers helpers; //使用这个接口burpsuite通过扩展一组扩展使用的回调方法 public IBurpExtenderCallbacks cbs; //当Burp调用扩展提供的带有上下文菜单调用细节的IContextMenuFactory时,将使用此接口。 //自定义上下文菜单工厂可以查询此接口来获取调用事件的详细信息,以便确定应该显示哪些菜单项。 public IContextMenuInvocation context;
@Override //// 实现 IBurpExtender 接口的 registerExtenderCallbacks 方法 public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
String pluginName = "From wooyun search"; //设置扩展插件名 callbacks.setExtensionName(pluginName); //burp扩展的帮助类,有一些字符串转换的功能,例如helpers.base64Encode(parameter.getValue()) this.helpers = callbacks.getHelpers(); this.cbs = callbacks; //输出流,在burp输出内容,可用来调试代码 this.stdout = new PrintWriter(callbacks.getStdout(), true); //错误流,在burp输出内容,可用来调试代码 this.stderr = new PrintWriter(callbacks.getStderr(), true); this.stdout.println("hello burp!"); //Burp 的作者在设计上下文菜单功能中采用了工厂模式的设计模式,扩展可以实现此接口,然后调用 IBurpExtenderCallbacks.registerContextMenuFactory() 注册自定义上下文菜单项的工厂。 callbacks.registerContextMenuFactory(this);// for menus }

@Override //当用户在 Burp 中的任何地方调用一个上下文菜单时,Burp 则会调用这个工厂方法。 //此方法会根据菜单调用的细节,提供应该被显示在上下文菜单中的任何自定义上下文菜单项。 //invocation - 一个实现 IMessageEditorTabFactory 接口的对象, 通过此对象可以获取上下文菜单调用的细节。 public List<JMenuItem> createMenuItems(IContextMenuInvocation invocation) { ArrayList<JMenuItem> menu_list = new ArrayList<JMenuItem>(); this.context = invocation; menu_list.add(new Menu(this)); //此工厂方法将会返回需要被显示的自定义菜单项的一个列表(包含子菜单,checkbox 菜单项等等), //若无菜单项显示,此工厂方法会返回 null 。 return menu_list; }}

关于TableStruct.java的代码,其实就是要显示的一个table表的结构

package wooyun;
import java.util.HashMap;import java.util.Map;
public class TableStruct { private Map<String, Object[]> ColumnNames; private Map<String, Object[][]> RowDatas; private Map<String, String> ExtraInfo;
TableStruct() { //列名 ColumnNames = new HashMap<String, Object[]>(); //行数据 RowDatas = new HashMap<String, Object[][]>(); //提取的信息 ExtraInfo = new HashMap<String, String>(); }
public void SetExtraInfo(String name, String info) { this.ExtraInfo.put(name, info); }
public String GetExtraInfo(String name) { return this.ExtraInfo.get(name); }

public String[] GetNameSets() { //带参数的toArray方法,则是根据参数数组的类型,构造了一个对应类型的,长度跟ArrayList的size一致的空数组, //虽然方法本身还是以 Object数组的形式返回结果,不过由于构造数组使用的ComponentType跟需要转型的ComponentType一致,就不会产生转型异常。 //java.lang.reflect.Array类提供静态方法来动态创建和访问Java数组 //在Java的反射机制中,通过 数组的 class 对象的getComponentType()方法可以取得一个数组的Class对象, a = (Object[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size); return RowDatas.keySet().toArray(new String[0]); }

public void AddColumnNames(String name, Object[] obj) { this.ColumnNames.put(name, obj); }

public void AddRowDatas(String name, Object[][] obj) { this.RowDatas.put(name, obj); }

public Object[] GetColumnNamesFromTabName(String name) { return this.ColumnNames.get(name); }

public Object[][] GetRowDatasFromTabName(String name) { return this.RowDatas.get(name); }

}

关于GUI.java的代码

package wooyun;
import javax.swing.*;import javax.swing.event.ChangeEvent;import javax.swing.event.ChangeListener;import javax.swing.table.JTableHeader;import javax.swing.table.TableColumnModel;import java.awt.*;
public class GUI { public GUI(TableStruct t) { TabbedPaneFrame jf = new TabbedPaneFrame(t); //创建一个JFrame对象 //设置Title jf.setTitle("WooYun 搜索结果"); //设置大小 jf.setSize(650, 480); //设置窗口相对于指定组件的位置。如果组件当前未显示或者 c 为 null,则此窗口将置于屏幕的中央。 jf.setLocationRelativeTo(null);// jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.setVisible(true); //设置窗口可见 }}
//java的GUI程序的基本思路是以JFrame为基础,它是屏幕上window的对象,能够最大化、最小化、关闭class TabbedPaneFrame extends JFrame {
//JTabbedPane是一种可以放多个面板的并且可以方便切换的容器,选项卡面板。它允许用户通过点击给定标题或图标的选项卡,在一组组件之间进行切换显示 private JTabbedPane tabbedPane; private int count = 0; //定义结构体化的 private TableStruct struct;
public TabbedPaneFrame(TableStruct t) { this.struct = t; // 添加选项卡,进行初始化 tabbedPane = new JTabbedPane(); //获取key的集合 for (String s : struct.GetNameSets()) { //例如可以以下面的方式进行创建 //创建第 1 个选项卡(选项卡只包含 标题) //tabbedPane.addTab("Tab01", createTextPanel("TAB 01")); // 创建第 2 个选项卡(选项卡包含 标题 和 图标) //tabbedPane.addTab("Tab02", new ImageIcon("bb.jpg"), createTextPanel("TAB 02")); // 创建第 3 个选项卡(选项卡包含 标题、图标 和 tip提示) //tabbedPane.addTab("Tab03", new ImageIcon("bb.jpg"), createTextPanel("TAB 03"), "This is a tab."); tabbedPane.addTab(s, null); } // 添加选项卡面板的控件 add(tabbedPane, "Center"); // 添加监听器,添加选项卡选中状态改变的监听器 tabbedPane.addChangeListener(new ChangeListener() { @Override
public void stateChanged(ChangeEvent e) {
// TODO Auto-generated method stub //获取当前被选中的选项卡 int n = tabbedPane.getSelectedIndex(); loadTab(n);
}
}); //设置默认进行加载的方式 loadTab(0);

}
private static String convertToMultiline(String orig) { //replaceAll(String regex, String replacement), //用replacement替换所有的regex匹配项,regex很明显是个正则表达式,replacement是字符串。 return "<html>" + orig.replaceAll("\n", ""); }
private void loadTab(int n) { //获取选定的title String title = tabbedPane.getTitleAt(n); //根据title获取行的数据 Object[][] tableDate = struct.GetRowDatasFromTabName(title); //根据title获取列数据 Object[] name = struct.GetColumnNamesFromTabName(title); //创建表格控件 //JTable table = new JTable(cellData, columnNames); JTable table = new JTable(tableDate, name);
//JPanel:面板组件,非顶层容器 JPanel jp = new JPanel(); //创建一个JPanel对象

JTableHeader head = table.getTableHeader(); // 创建表格标题对象 //dimension是Java的一个类,封装了一个构件的高度和宽度 //setSize是设定的固定大小,而setPreferredSize仅仅是设置最好的大小,这个不一定与实际显示出来的控件大小一致(根据界面整体的变化而变化) head.setPreferredSize(new Dimension(head.getWidth(), 20));// 设置表头大小 //设置自动调整的模式 //AUTO_RESIZE_SUBSEQUENT_COLUMNS 在 UI 调整中,更改后续列以保持总宽度不变,这是默认的行为 table.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS); //利用JTable中的getColumnModel()方法取得TableColumnModel对象;再利用TableColumnModel界面 //所定义的getColumn()方法取TableColumn对象,利用此对象的setPreferredWidth()方法就可以控制字段的宽度. TableColumnModel tc = table.getColumnModel(); tc.getColumn(0).setPreferredWidth(10); table.setRowHeight(22); //获取额外的信息 String ret = struct.GetExtraInfo(title); JLabel jl = new JLabel(convertToMultiline(ret)); //创建一个标签

//BorderLayout表示的就是边界布局 jp.setLayout(new BorderLayout()); // jp.add(jl, "North"); //在JScrollPane里放入JPanel jp.add(new JScrollPane(table), "Center");
//将组件设置为index至component,如果该索引中没有选项卡,则会引发内部异常 tabbedPane.setComponentAt(n, jp); }}

关于Menu.java

package wooyun;

import burp.*;

import javax.swing.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.PrintWriter;import java.net.URL;import java.util.ArrayList;import java.util.List;import java.util.regex.Matcher;import java.util.regex.Pattern;

public class Menu extends JMenuItem {//JMenuItem vs. JMenu

//初始化方法 public Menu(BurpExtender burp) { this.setText(" 从乌云搜索类似漏洞"); // 添加动作监听器 this.addActionListener(new SearchFromWooyun(burp, burp.context)); }}

class SearchFromWooyun implements ActionListener { public IContextMenuInvocation invocation; public IExtensionHelpers helpers; public PrintWriter stdout; public PrintWriter stderr; public IBurpExtenderCallbacks callbacks;

//下面就是其的初始化方法 public SearchFromWooyun(BurpExtender burp, IContextMenuInvocation context) { //通过burpExtender当中的内容给context this.invocation = context; this.helpers = burp.helpers; this.callbacks = burp.cbs; this.stdout = burp.stdout; this.stderr = burp.stderr; }

@Override //在ActionListener中的actionPerformed中定义相应方法处理事件 public void actionPerformed(ActionEvent e) {

//IContextMenuInvocation的getSelectedMessages方法 //此方法可用于检索用户在调用上下文菜单时显示或选择的HTTP请求响应的详细信息。注意:出于性能原因, //从这个方法返回的对象被绑定到Burp UI中消息的原始上下文。例如,如果在代理拦截面板上调用了上下文菜单, //那么由该方法返回的IHttpRequestResponse将反映拦截面板的当前内容,并且当当前消息已被转发或删除时, //这将发生变化。如果您的扩展需要存储的细节信息的上下文菜单中被调用,那么你应该从IHttpRequestResponse查询这些细节的时候调用, //或者你应该使用IBurpExtenderCallbacks.saveBuffersToTempFiles()来创建一个持久的只读副本 //IHttpRequestResponse @return IHttpRequestResponse对象数组代表显示的物品或由用户选择上下文菜单时调用。 //如果没有适用于调用的消息,此方法将返回null。 IHttpRequestResponse[] selectedItems = this.invocation.getSelectedMessages();

//此方法用于检索请求消息 //byte[] getRequest(); byte[] selectedRequest = selectedItems[0].getRequest(); //此方法用于接收此请求响应的HTTP服务。 IHttpService httpService = selectedItems[0].getHttpService();



//**************获取参数 通过IRequestInfo对象*************************// //此方法可用于分析HTTP请求,并获取有关它的各种关键细节。 // IRequestInfo analyzeRequest(byte[] request); IRequestInfo analyzedRequest = this.helpers.analyzeRequest(selectedRequest);//only get the first// String url = analyzedRequest.getUrl().toString(); String pattern = "(GET|POST) ([^ ]*) HTTP/"; //List<String> getHeaders();此方法用于获取请求中包含的HTTP标头。 //获取请求当中的第一个行 String line0 = analyzedRequest.getHeaders().get(0); //利用正则去匹配 Pattern r = Pattern.compile(pattern); Matcher m = r.matcher(line0); String url = ""; if (m.find()) { //获取协议和host,然后获取匹配到的url url = httpService.getProtocol() + "://" + httpService.getHost() + m.group(2); } else { stderr.println("Host:" + httpService.getHost() + " url匹配失败"); return; } List<String> gets = new ArrayList<String>(); List<String> posts = new ArrayList<String>(); List<String> cookies = new ArrayList<String>();
//下面就是获取请求参数 List<IParameter> paraList = analyzedRequest.getParameters(); for (IParameter para : paraList) { byte type = para.getType(); //获取参数的类型 String key = para.getName(); //获取参数的名称 String value = para.getValue(); //获取参数的值 //根据不同的type放到不同的list当中 switch (type) { case 0: gets.add(key); break; case 1: posts.add(key); break; case 2: cookies.add(key); break; } } //参数共有7种格式,0是URL参数,1是body参数,2是cookie参数,6是json格式参数 Wooyun w = null; try { w = new Wooyun(); } catch (Exception e1) { for (StackTraceElement elem : e1.getStackTrace()) { this.stderr.println(elem); } //showMessageDialog():消息对话框 //JOptionPane.showMessageDialog有三种参数设置 // JOptionPane.showMessageDialog(parentComponent, message); // JOptionPane.showMessageDialog(parentComponent, message, title, messageType); // JOptionPane.showMessageDialog(parentComponent, message, title, messageType, icon); //type为1表示messagetType值为1,含义为提示信息 JOptionPane.showMessageDialog(null, "初始化数据库失败", "提示", 1); return; } try { //初始化TableStruct结构,调用Search方法,然后将gets、posts、cookies进行转换为数组 TableStruct ret = w.Search(new URL(url), gets.toArray(new String[gets.size()]), cookies.toArray(new String[cookies.size()]), posts.toArray(new String[posts.size()])); //获取RowDatas当中的所有keySet if (ret.GetNameSets().length == 0) { JOptionPane.showMessageDialog(null, "未发现可用参数", "提示", 1); return; } new GUI(ret); } catch (Exception e1) { for (StackTraceElement elem : e1.getStackTrace()) { this.stderr.println(elem); } this.stderr.println(e1);

}

}}
关于此项目的Wooyun.java其实就是搜索类,根据源码当中的wooyun.json进行搜索
package wooyun;

import com.alibaba.fastjson.JSONArray;import com.alibaba.fastjson.JSONObject;

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.net.MalformedURLException;import java.net.URL;import java.nio.charset.StandardCharsets;import java.util.*;

import static java.lang.String.join;import static java.lang.String.valueOf;

public class Wooyun { public StringBuilder sb; private String shuimugan; private TableStruct struct;

public Wooyun() throws IOException { //Class.getClassLoader.getResourceAsStream(String path) :默认则是从ClassPath根下获取,path不能以’/'开头,最终是由ClassLoader获取资源。 InputStream is = this.getClass().getClassLoader().getResourceAsStream("wooyun.json"); if (is==null) { throw new NullPointerException(); }// InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("wooyun.json"); sb = new StringBuilder(); //public InputStreamReader(InputStream in,Charset cs) //创建使用给定字符集的 InputStreamReader,下面就是使用的是StandardCharsets.UTF_8字符集 //BufferedReader :提供通用的缓冲方式文本读取 BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); int ch; while ((ch = br.read()) != -1) { sb.append((char) ch); } shuimugan = "https://shuimugan.com/bug/view?bug_no="; struct = new TableStruct(); } //自己定义了一个数组的连接函数 private static Object[] concat(Object[] a, Object[] b) { Object[] c = new Object[a.length + b.length]; System.arraycopy(a, 0, c, 0, a.length); System.arraycopy(b, 0, c, a.length, b.length); return c; }



/* 输入:一段url,host,get参数,cookie参数,post参数 返回: path统计,host统计,各种参数统计 漏洞类型占比(path,host) */ //相应的搜索函数 public TableStruct Search(URL url, String[] GetParams, String[] CookieParams, String[] PostParams) { JSONArray jobj; //参数是Stringbuffer的toString方法 //转换为jsonobject对象 jobj = JSONArray.parseArray(sb.toString()); //如果用“.”作为分隔的话,必须是如下写法,String.split("\\."),这样才能正确的分隔开,不能用String.split("."); //获取路径 String[] path_array = url.getPath().split("/"); String path = path_array[path_array.length - 1]; //从url当中获取host String host = url.getHost();

Map<String, Integer> pathTJMap = new TreeMap<String, Integer>(); List<Object[]> pathList = new ArrayList<Object[]>();

Map<String, Integer> hostTJMap = new TreeMap<String, Integer>(); List<Object[]> hostList = new ArrayList<Object[]>();

Map<String, Integer> getMap = new TreeMap<String, Integer>(); Map<String, Integer> cookieMap = new TreeMap<String, Integer>(); Map<String, Integer> postMap = new TreeMap<String, Integer>();

for (Object object : jobj) { JSONObject jsonObject = (JSONObject) object; //获取漏洞的类型 String BugType = jsonObject.getString("type"); if (BugType.equals("")) { BugType = "不知名的漏洞类型"; } String BugID = jsonObject.getString("bugid"); String Title = jsonObject.getString("title");

JSONArray urls = jsonObject.getJSONArray("url"); JSONArray targets = jsonObject.getJSONArray("target"); JSONArray get_params = jsonObject.getJSONArray("params"); JSONArray cookie_params = jsonObject.getJSONArray("cookie_params"); JSONArray post_params = jsonObject.getJSONArray("post_params"); for (Object obj_url : urls) try { URL _url = new URL((String) obj_url); String[] path_array2 = _url.getPath().split("/"); if (path_array2.length > 0) { String _path = path_array2[path_array2.length - 1]; //此处就是判断url是否是一样的 if (!_path.equals("") && _path.equalsIgnoreCase(path)) { int count = 1; if (pathTJMap.containsKey(BugType)) { count = pathTJMap.get(BugType) + 1; } pathTJMap.put(BugType, count); pathList.add(new Object[]{BugType, Title, shuimugan + BugID, _url.toString()}); break; } } } catch (MalformedURLException | ArrayIndexOutOfBoundsException ignored) { } for (Object _target : targets) { String target = (String) _target; //判断host是否是一样的 if (target.equalsIgnoreCase(host)) { int count = 1; if (hostTJMap.containsKey(BugType)) { count = hostTJMap.get(BugType) + 1; } hostTJMap.put(BugType, count);// hostList.add("[" + BugType + "] " + Title + " 漏洞链接:" + shuimugan + BugID); hostList.add(new Object[]{BugType, Title, shuimugan + BugID}); } }

String flag = "!!flag{aabbc}!!"; if (GetParams.length > 0) { Set<String> param = new HashSet<String>(); //根据get的参数进行判断 for (Object _get : get_params) { String target = (String) _get; for (String get2 : GetParams) { if (target.equalsIgnoreCase(get2)) { param.add(get2); } } } if (param.size() > 0) { String[] ret = {BugType, Title, join(",", param), shuimugan + BugID};

getMap.put(join(flag, ret), param.size()); }

} //根据cookie参数进行判断 if (CookieParams.length > 0) { Set<String> param = new HashSet<String>(); for (Object _get : cookie_params) { String target = (String) _get; for (String get2 : CookieParams) { if (target.equalsIgnoreCase(get2)) { param.add(get2); } } } if (param.size() > 0) { String[] ret = {BugType, Title, join(",", param), shuimugan + BugID}; cookieMap.put(join(flag, ret), param.size()); }

} //根据post参数进行判断 if (PostParams.length > 0) { Set<String> param = new HashSet<String>(); for (Object _get : post_params) { String target = (String) _get; for (String get2 : PostParams) { if (target.equalsIgnoreCase(get2)) { param.add(get2); } } } if (param.size() > 0) { String[] ret = {BugType, Title, join(",", param), shuimugan + BugID}; postMap.put(join(flag, ret), param.size()); }

}

}



List<Map.Entry<String, Integer>> patTJlist = new ArrayList<Map.Entry<String, Integer>>(pathTJMap.entrySet());

Collections.sort(patTJlist, new Comparator<Map.Entry<String, Integer>>() { @Override public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) { return o2.getValue() - o1.getValue(); } });

List<Map.Entry<String, Integer>> hostTJlist = new ArrayList<Map.Entry<String, Integer>>(hostTJMap.entrySet());

//调用函数进行排序 //Collections是一个工具类,sort是其中的静态方法,是用来对List类型进行排序的 Collections.sort(hostTJlist, new Comparator<Map.Entry<String, Integer>>() { @Override public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) { //// 返回值为int类型,大于0表示正序,小于0表示逆序 return o2.getValue() - o1.getValue(); } });

List<Map.Entry<String, Integer>> getList = new ArrayList<Map.Entry<String, Integer>>(getMap.entrySet());

getList.sort(new Comparator<Map.Entry<String, Integer>>() { @Override public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) { return o2.getValue() - o1.getValue(); } });

List<Map.Entry<String, Integer>> cookieList = new ArrayList<Map.Entry<String, Integer>>(cookieMap.entrySet());

cookieList.sort(new Comparator<Map.Entry<String, Integer>>() { @Override public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) { return o2.getValue() - o1.getValue(); } });

List<Map.Entry<String, Integer>> postList = new ArrayList<Map.Entry<String, Integer>>(postMap.entrySet());

postList.sort(new Comparator<Map.Entry<String, Integer>>() { @Override public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) { return o2.getValue() - o1.getValue(); } });



// 输出 path 部分 if (pathList.size() > 0) { StringBuilder ret = new StringBuilder(String.format("相同路径:%s 下历史漏洞及漏洞类型:\n", path)); int index = 0; for (Map.Entry<String, Integer> entry : patTJlist) { ret.append(entry.getKey()).append(":").append(entry.getValue()).append("    "); index++; if (index % 3 == 0) { ret.append("\n"); } if (index >= 6) { break; } } struct.SetExtraInfo("Path", ret.toString()); struct.AddColumnNames("Path", new Object[]{"ID", "漏洞类型", "漏洞标题", "乌云镜像地址", "漏洞页面"});// struct.AddRowDatas(); Object[][] rows = new Object[pathList.size()][]; for (int i = 0; i < pathList.size(); i++) { Object[] obj = concat(new Object[]{valueOf(i)}, pathList.get(i)); rows[i] = obj; } struct.AddRowDatas("Path", rows); }

// 输出host部分 if (hostList.size() > 0) { StringBuilder ret = new StringBuilder(String.format("相同Host:%s 下历史漏洞及漏洞类型:\n", host)); int index = 0; for (Map.Entry<String, Integer> entry : hostTJlist) { ret.append(entry.getKey()).append(":").append(entry.getValue()).append("    "); index++; if (index % 3 == 0) { ret.append("\n"); } if (index >= 6) { break; } } struct.SetExtraInfo("Host", ret.toString()); struct.AddColumnNames("Host", new Object[]{"ID", "漏洞类型", "漏洞标题", "乌云镜像地址"}); Object[][] rows = new Object[hostList.size()][]; for (int i = 0; i < hostList.size(); i++) { Object[] obj = concat(new Object[]{valueOf(i)}, hostList.get(i)); rows[i] = obj; } struct.AddRowDatas("Host", rows);

}

// 输出Get参数部分 String flag_split = "!!flag\\{aabbc\\}!!"; if (getList.size() > 0) { struct.SetExtraInfo("Get Params", "Get参数历史漏洞:"); struct.AddColumnNames("Get Params", new Object[]{"ID", "漏洞类型", "漏洞标题", "影响参数", "漏洞链接"}); Object[][] data = new Object[getList.size()][5]; for (int i = 0; i < getList.size(); i++) { Map.Entry<String, Integer> entry = getList.get(i); data[i] = concat(new Object[]{String.valueOf(i)}, (Object[]) entry.getKey().split(flag_split)); } struct.AddRowDatas("Get Params", data); }

if (cookieList.size() > 0) { struct.SetExtraInfo("Cookie Params", "Cookie参数历史漏洞:"); struct.AddColumnNames("Cookie Params", new Object[]{"ID", "漏洞类型", "漏洞标题", "影响参数", "漏洞链接"}); Object[][] data = new Object[cookieList.size()][5]; for (int i = 0; i < cookieList.size(); i++) { Map.Entry<String, Integer> entry = cookieList.get(i); data[i] = concat(new Object[]{String.valueOf(i)}, (Object[]) entry.getKey().split(flag_split)); } struct.AddRowDatas("Cookie Params", data);

} if (postList.size() > 0) { struct.SetExtraInfo("Post Params", "Post参数历史漏洞:"); struct.AddColumnNames("Post Params", new Object[]{"ID", "漏洞类型", "漏洞标题", "影响参数", "漏洞链接"}); Object[][] data = new Object[postList.size()][5]; for (int i = 0; i < postList.size(); i++) { Map.Entry<String, Integer> entry = postList.get(i); data[i] = concat(new Object[]{String.valueOf(i)}, (Object[]) entry.getKey().split(flag_split)); } struct.AddRowDatas("Post Params", data);

} return struct; }

}

总结


 
了解了此插件的工作原理,我们其实也可以自己进行构造自己的json结构,根据某些特定的参数进行搜索扩展

推荐文章++++

*对乌云漏洞库payload的整理以及Burp辅助插件

*乌云——任意密码重置总结


文章来源: http://mp.weixin.qq.com/s?__biz=MzAxMjE3ODU3MQ==&amp;mid=2650460315&amp;idx=2&amp;sn=aedb223b5e60762082377fcbaa6b562b&amp;chksm=83bbb57fb4cc3c696b538c4d5b5d6563663434d2c09ee05d580651cd4d89bbee8b4f2b0ded32#rd
如有侵权请联系:admin#unsafe.sh