JSONP接口探测插件编写思路

最近有机油有挖掘jsonp接口的需求,最原始的办法就是对每一个页面进行XHR的请求查看,并观察接口是否为jsonp

根据已知经验,我们可以得出:

1.JSONP接口为XHR请求

2.通常URI中有callback参数或者其他可控参数

3.响应体开头为传入的callback值

4.callback输出后为函数名[即需要满足  函数名(数据) >>  cb_fun({"data":"1"})]

...

了解到以上基础信息以后,我们便可以根据以上规则来编写js从而达到自动捕获网站的每一个页面是否存在JSONP接口了,初步思路如下:

1.通过Burp劫持页面响应,插入自己的JS文件

2.在JS对XMLHttpRequest对象进行重写

3.在重写的对象中获取请求URI与响应内容

4.正则判断响应是否满足JSONP格式 (即  函数名(数据))

5.遍历URI中的参数value值并匹配响应体是否以value开头

6.满足4或5任意一条则将数据输出到WebSql与Web控制台

示例代码:

var db = openDatabase('testDB', '1.0', 'Test DB', 2 * 1024 * 1024);
  db.transaction(function (context) {
           context.executeSql('CREATE TABLE IF NOT EXISTS testTable (url unique,desc)');
         });
function addData(url,desc){
      db.transaction(function (context) {
           context.executeSql('INSERT INTO testTable (url,desc) VALUES (?,?)',[url,desc]);
           console.log("save");
      });
}

(function(open) {
    XMLHttpRequest.prototype.open = function() {
        this.addEventListener("readystatechange",
        function() {
            var result = [];
            var url = this.responseURL;
            var rsp = this.response;
            try {
                var mode1 = false;
                var mode2 = false;
                try {
                    //var jsonstr = rsp.match(/^[a-zA-Z0-9_]+\((\S*)\)$/)[1];
                    var jsonstr = rsp.match(/^.*?\((\S*)\)$/)[1];
                    console.log(url+"\t"+jsonstr);
                    var obj = JSON.parse(jsonstr);
                    mode1 = typeof(obj) == "object"
                } catch(e) {
                    console.error();
                }
                try {
                    var kvarr = url.match(/([\\?|&])(.+?)=([^&?]*)/g);
                    for (var i = kvarr.length - 1; i >= 0; i--) {
                        var str = kvarr[i];
                        var v = str.split("=")[1];
                        if (rsp.startWith(v)) {
                            mode2 = true;
                            return
                        }
                    }
                } catch(e) {
                    console.error();
                }
                if (mode1 || mode2) {
                    try {
                        var rspexp = /.*?(name|phone|username|uid|id|password|pwd).*?/i;
                        var isyouyong = rsp.match(rspexp);
                        var desc;
                        if (isyouyong != null && isyouyong.length > 0) {
                            desc = "\t[Successfully found vulnerable jsonp api-100%]";
                            console.info(url + desc);
                        }else{
                            desc = "\t[Found jsonp api-80%]";
                            console.info(url + desc);
                        }
                        //window.postMessage({"test": url}, '*');
                        addData(url,desc);
                    } catch(e) {
                        console.error();
                    }
                }
            } catch(e) {
                console.error();
            }
        },
        false);
        open.apply(this, arguments)
    }
})(XMLHttpRequest.prototype.open);


使用Burp进行JSONP探测感觉有点大材小用,且长时间开着Burp会占用大量内存,于是想着撸一个Chrome插件,看了大约半个小时文档,然后发现通过Chrome插件可以直接往页面注入js文件,不过由于是佛系编写的插件,所以这个插件还不够成熟,算是一个半成品,不过对于我来说,已经够用了,算是解放了一部分双手,附上下载地址:http://file.jeary.org/jsonp.crx

效果如图:(renren网没什么用的jsonp接口【只能用于判断登录状态】)

点击查看原图

PS:

 - 隐私字段目前并不能直接配置正则,不过当JSONP接口的响应中出现上面的字段时会输出API 100%的字样,表示接口满足隐私条件,否则输出为80%,

 - 可以通过将crx文件更改为压缩包格式解压后即可修改

 

待解决的问题:

   1.目前探测的结果是用websql存储,websql是按域存储数据,导致不同网站需要看不同的数据,比较麻烦

   2.自定义配置隐私字段功能目前没有,硬编码在了js里面,想要修改需要修改原文件

   3.如何定义”隐私“字段,是一个需要思考的问题,个人认为仅仅通过字典来匹配的方式太low(应该有更好的办法)


相关计划(负责挖坑,不负责埋)

- JSONP接口探测
- Http-Only Cookie隐私嗅探器
- 敏感信息扫描(响应体中识别)
- 服务器报错信息捕获
- Flash权限反射(可跨域swf扫描)

PS:折腾完以后发现意义并不是特别大,毕竟自己F12逐个XHR请求查看也能达到一样的效果,只是人工稍微费力

Just for fun,Enjoy it.

 

发表评论