前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >乌云漏洞库payload-Burp插件源码分析

乌云漏洞库payload-Burp插件源码分析

作者头像
重生信息安全
发布2020-04-26 14:28:28
8960
发布2020-04-26 14:28:28
举报
文章被收录于专栏:重生信息安全重生信息安全

前言

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


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

使用详情如下

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

代码语言:javascript
复制
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表的结构

代码语言:javascript
复制
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的代码

代码语言:javascript
复制
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

代码语言:javascript
复制
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进行搜索

代码语言:javascript
复制
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结构,根据某些特定的参数进行搜索扩展

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 重生信息安全 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 总结
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档