前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >burp 日志插件从原理到实践

burp 日志插件从原理到实践

作者头像
信安之路
发布2019-05-10 11:23:21
2.9K0
发布2019-05-10 11:23:21
举报
文章被收录于专栏:信安之路信安之路

本文作者:(首次投稿)

Logger++ 是 nccgroup 开源的一个 burp 扩展,主要功能是记录经过 Burp Suite 的所有 HTTP 请求 和 HTTP 响应。

相较于 Burp 自带的 Proxy 组件中的 HTTP History, logger++ 的优势是记录了更完整的流量,并且支持对这些流量进行基于正则表达式的简易分析,对相关流量记录进行着色展示,将流量导入到 elasticsearch 平台等。Burp 基本组件 Proxy 中的 HTTP History 则只记录经过代理的 HTTP 流量,对于 Repeater, Scanner, Intruder 等组件的流量,并不会在它的标签中展示。

对于笔者而言,常用的功能主要有两个:

1、基于正则表达式的简易 HTTP 流量分析

2、记录流量日志 (导出 csv 便于后续代码分析)

代码简要分析

https://github.com/nccgroup/BurpSuiteLoggerPlusPlus/blob/master/src/main/java/burp/BurpExtender.java

从入口 src/main/java/burp/BurpExtender.java 开始看,一开始只是继承 loggerplusplus.LoggerPlusPlus 类。

代码语言:javascript
复制
package burp;
import loggerplusplus.LoggerPlusPlus;

public class BurpExtender extends LoggerPlusPlus{  public static void main(String [] args){    System.out.println("You have built the Logger++. You shall play with the jar file now!");  }}

切换到 src/main/java/loggerplusplus/LoggerPlusPlus.java与记录 HTTP 日志有关的语句是 logManager = new LogManager(loggerPreferences);

代码语言:javascript
复制
    @Override    public void registerExtenderCallbacks(final IBurpExtenderCallbacks callbacks){        //Burp Specific        LoggerPlusPlus.callbacks = callbacks;        LoggerPlusPlus.instance = this;        LoggerPlusPlus.contextMenuFactory = new LoggerContextMenuFactory();
        callbacks.setExtensionName("Logger++");
        filterListeners = new ArrayList<>();        loggerPreferences = new LoggerPreferences(LoggerPlusPlus.this);        logManager = new LogManager(loggerPreferences);        elasticSearchLogger = new ElasticSearchLogger(logManager, loggerPreferences);
        if(!callbacks.isExtensionBapp() && loggerPreferences.checkUpdatesOnStartup()){            MoreHelp.checkForUpdate(false);        }
        buildUI();    }

继续跟踪到 src/main/java/loggerplusplus/LogManager.java

基本思路就是继承和实现 Burp 提供的 IHttpListener 接口 和 IProxyListener 接口,重写 processHttpMessageprocessProxyMessage 方法,存储流经的 HTTP 流量。还有一些对 HTTP 请求/响应 的处理细节可以在 src/main/java/loggerplusplus/LogEntry.java 中的 processRequestprocessResponse 中找到。(其实大部分情况下 Burp 自带的 LoggerPlusPlus.getCallbacks().getHelpers().analyzeRequest(requestResponse) 已经帮我们把需要的字段解析完成了。)

关键代码如下:

代码语言:javascript
复制
    @Override    public void processHttpMessage(final int toolFlag, final boolean messageIsRequest, final IHttpRequestResponse requestResponse) {        // Only process scanner messages which contain the request and response.        if(!messageIsRequest) {            final LogEntry logEntry = new LogEntry();            processHttpMessage(logEntry, toolFlag, requestResponse);        }    }
    // Wrapper to allow a custom LogEntry to be passed as a parameter    // Custom LogEntry used when importing proxy history.    // messageIsRequest is removed as not needed.    public void processHttpMessage(final LogEntry logEntry, final int toolFlag, final IHttpRequestResponse requestResponse){        executorService.submit(new Runnable() {            @Override            public void run() {                if(toolFlag != IBurpExtenderCallbacks.TOOL_PROXY || logEntry.isImported){                    if(requestResponse == null || !prefs.isEnabled()) return;                                        IRequestInfo analyzedReq = LoggerPlusPlus.getCallbacks().getHelpers().analyzeRequest(requestResponse);                    URL uUrl = analyzedReq.getUrl();                                        if (isValidTool(toolFlag) && (!prefs.isRestrictedToScope() || LoggerPlusPlus.getCallbacks().isInScope(uUrl))){                        // We will not need to change messageInfo so save to temp file                        IHttpRequestResponse savedReqResp = LoggerPlusPlus.getCallbacks().saveBuffersToTempFiles(requestResponse);                        logEntry.processRequest(toolFlag, savedReqResp, uUrl, analyzedReq, null);                        if(requestResponse.getResponse() != null) logEntry.processResponse(savedReqResp);                        // Check entry against colorfilters.                        for (ColorFilter colorFilter : prefs.getColorFilters().values()) {                            logEntry.testColorFilter(colorFilter, false);                        }
                        addNewRequest(logEntry, true); // Complete Request and Response Added                        for (LogEntryListener logEntryListener : logEntryListeners) {                            logEntryListener.onResponseUpdated(logEntry);                        }                    }                }            }        });    }
    @Override    public void processProxyMessage(final boolean messageIsRequest, final IInterceptedProxyMessage proxyMessage) {        //REQUEST AND RESPONSE SEPARATE        final LogEntry.PendingRequestEntry logEntry;        if(messageIsRequest){            logEntry = new LogEntry.PendingRequestEntry();        }else{            synchronized (pendingRequests) {                logEntry = pendingRequests.remove(proxyMessage.getMessageReference());            }        }        executorService.submit(new Runnable() {            @Override            public void run() {                if(proxyMessage == null || !prefs.isEnabled()) return;                IHttpRequestResponse requestResponse = proxyMessage.getMessageInfo();                IRequestInfo analyzedReq = LoggerPlusPlus.getCallbacks().getHelpers().analyzeRequest(requestResponse);                URL uUrl = analyzedReq.getUrl();                int toolFlag = LoggerPlusPlus.getCallbacks().TOOL_PROXY;                if (isValidTool(toolFlag) && (!prefs.isRestrictedToScope() || LoggerPlusPlus.getCallbacks().isInScope(uUrl))){                    if(messageIsRequest){                        //New Proxy Request                        //We need to change messageInfo when we get a response so do not save to buffers                        logEntry.processRequest(toolFlag, requestResponse, uUrl, analyzedReq, proxyMessage);                        for (ColorFilter colorFilter : prefs.getColorFilters().values()) {                            logEntry.testColorFilter(colorFilter, false);                        }                        synchronized (pendingRequests) {                            pendingRequests.put(proxyMessage.getMessageReference(), logEntry);                        }                        addNewRequest(logEntry, false); // Request added without response                    }else{                        // Existing Proxy Request, update existing                        if (logEntry != null) {                            updatePendingRequest(logEntry, requestResponse);                        } else {                            lateResponses++;                            if(totalRequests > 100 && ((float)lateResponses)/totalRequests > 0.17){                                MoreHelp.showWarningMessage(lateResponses + " responses have been delivered after the Logger++ timeout. Consider increasing this value.");                                //Reset late responses to prevent message being displayed again so soon.                                lateResponses = 0;                            }                        }                    }                }            }        });    }

功能说明

主界面

先看下 Logger++ 的基本界面,其实和 Proxy 中的 HTTP History 基本一致,稍微新增了一些字段。

正常经过代理的流量 Tool 字段都是 Proxy;Repeater, Intruder 等工具发出的请求也会进行记录。

如果 Tool 为 Scanner 是 Burp 自带的扫描器发送的请求;Tool 为 Extender 是其他 Burp 插件发送的请求。在这个场景插件发出的请求都是来自 Active Scan++,利用这个特性你可以使用 Logger++ 以 "黑盒" 的方式分析 Burp 一些的扫描能力增强插件的原理 / payload

Proxy / Repeater / Intruder 案例:

Scanner / Extender 案例:

记录上图时的插件情况

基于正则表达式的简易流量分析

过滤器也是 Logger++ 中一个很方便的功能。笔者通常会使用这个功能,来寻找一些敏感信息泄露和潜在的漏洞请求(这里提供的规则并不是 100% 能确定漏洞的,只是作为一个辅助手段,还需要进一步手工验证)。在该工具的 Filter Library 里也有几个不错的过滤器示例可以参考。

关于过滤器支持的其他字段可以在 Logger++ 的项目 wiki 里查到,链接如下

https://github.com/nccgroup/BurpSuiteLoggerPlusPlus/wiki/Filter-Fields

这里提供一些过滤器的示例作为抛砖引玉

信息泄露 (内网 IP) 规则 #1

Internal IP Address

RESPONSE == /(10(\.(25[0-5]|2[0-4][0-9]|1[0-9]{1,2}|[0-9]{1,2})){3}|((172\.(1[6-9]|2[0-9]|3[01]))|192\.168)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{1,2}|[0-9]{1,2})){2})/

如果你需要确定具体匹配的值,可以在 Message Editor 里用正则表达式搜索。

也可以使用 Grep Values 标签来汇总所有请求中符合过滤器筛选内容的字符串值。

如果要新增自定义过滤器,只要点击 Saved Filters, 然后点击 Add Filter 即可,另外在 Options 选项卡中可以批量导入/导出过滤器设置。

信息泄露 (身份证号) #2

RESPONSE == /((\d{6})(18|19|20)?(\d{2})([01]\d)([0123]\d)(\d{3})(\d|X))/

信息泄露 (电子邮件) #3

匹配所有邮箱

RESPONSE == /(([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4}))/

匹配特定邮箱

RESPONSE == /(([A-Za-z0-9_\-\.])+\@test.com)/

模糊关键字匹配邮箱

RESPONSE == /(([A-Za-z0-9_\-\.])+\@(.*)test(.*))/

对结果进行去重

潜在的 CORS 配置不当 #4

RESPONSEHEADERS == /Access-Control-Allow-Origin: null/

RESPONSEHEADERS == /Access-Control-Allow-Origin: \*/

寻找潜在的 SSRF / 开放重定向 #5

开放重定向

根据响应头

ResponseHeaders == /(Location)/

根据参数名称

QUERY == /(url(.*)=)/ || REQUEST == /(url(.*)=)/ QUERY == /(uri(.*)=)/ || REQUEST == /(uri(.*)=)/ QUERY == /(path(.*)=)/ || REQUEST == /(path(.*)=)/ QUERY == /(href(.*)=)/ || REQUEST == /(href(.*)=)/ QUERY == /(redirect(.*)=)/ || REQUEST == /(redirect(.*)=)/

寻找参数中的图片

QUERY == /(img(.*)=)/ || REQUEST == /(img(.*)=)/ QUERY == /(pic(.*)=)/ || REQUEST == /(pic(.*)=)/ QUERY == /(\.png)/ || REQUEST == /(\.png)/ QUERY == /(\.jpg)/ || REQUEST == /(\.jpg)/ QUERY == /(\.gif)/ || REQUEST == /(\.gif)/

寻找潜在的 JSONP 调用 #6

基于参数

REQUEST == /(callback(.*)=)/ || QUERY == /(callback(.*)=)/

基于响应特征

RESPONSE == /(.+\(\[(.*)\]\))/ && RESPONSEHEADERS == /application\/json/

寻找潜在的越权漏洞 #7

REQUEST == /(id(.*)=)/ || QUERY == /(id(.*)=)/

着色过滤器 (color filter)

举一个 内网 IP 泄露检测规则 和 身份证号检测规则 配置的例子

Logger++ => View Logs => Colorize

着色过滤器配置也可以在 Options 中配置批量导入/导出。

着色效果如下

记录流量日志

Logger++ => Options => Export => Save log table as csv.

结语

充分利用 Logger++ 插件的过滤器,能帮助你在海量 HTTP 请求中更方便快捷地定位到某些脆弱的 HTTP 请求。如果你有其他不错的过滤器规则,也欢迎在下面留言。

参考资料

BurpSuiteLoggerPlusPlus Wiki

https://github.com/nccgroup/BurpSuiteLoggerPlusPlus/wiki

Logger++ 示例过滤器

https://github.com/nccgroup/BurpSuiteLoggerPlusPlus/wiki/Example-Filters

Burp Suite 存储日志分析

https://zhuanlan.zhihu.com/p/28284124

Burp Suite神器的日志存储

https://zhuanlan.zhihu.com/p/28231222

经验分享 Burpsuite 插件的使用

https://cloud.tencent.com/developer/article/1015187

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

本文分享自 信安之路 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 代码简要分析
    • 主界面
      • 基于正则表达式的简易流量分析
        • 信息泄露 (内网 IP) 规则 #1
        • 信息泄露 (身份证号) #2
        • 信息泄露 (电子邮件) #3
        • 潜在的 CORS 配置不当 #4
        • 寻找潜在的 SSRF / 开放重定向 #5
        • 寻找潜在的 JSONP 调用 #6
        • 寻找潜在的越权漏洞 #7
      • 着色过滤器 (color filter)
        • 记录流量日志
        • 结语
        • 参考资料
        相关产品与服务
        Elasticsearch Service
        腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档