一个跨域请求的XSS续
之前讨论过,在解决post跨域请求时,采用iframe+本域代理页的形式,兼容性(当然是包括IE6啦)是最好的。上次提到,代理页面的作用是:执行本域下的回调函数。就是这个原因,给XSS带来了便利。详细说明,请参考一个跨域请求的XSS漏洞
上次也提到,解决这个问题的根本在于杜绝不合法的函数在页面内执行。上次透了一下懒,对函数名就行了包含匹配。过程如下:
/**
* callback的值为:namespace.function,prefix123456
*/
var filter = [
'namespace',
'prefix'
];
//验证函数,返回true时,return
var validateCallback = function (callback) {
var flag = true;
for(var i=0;i<filter.length;i++) {
if(callback.indexOf(filter[i]) > -1) {
flag = false;
}
}
return flag;
} if(validateCallback(callback)) {
return;
}
从上面的代码可以看出,只有我的白名单的函数才能通过并执行。并且namespace是我定义的命名空间,我只要保证我的函数不会造成XSS就可以了吧。可是我太天真了,没想到还有这么个情况:
<iframe name="namespace" src="http://www.a.com" onload="loadIframe();">
<script>
function loadIframe() {
var iframe = document.createElement('iframe');
iframe.src = 'http://www.a.com/proxy.html?namespace.$.ajax&url="xxx"&dataType="javascript"';
document.body.appendChild(iframe);
}
</script>
这个时候,很轻松的就在a.com下,执行了第三方的js文件,想想都是一件可怕的事情。那为什么它能执行呢?
- 此时的namespace就是iframe的window,我们可以想象document.namespace是什么结果
- 一般情况下,a.com的页面上都会引用jquery或者其他的js库,很方便的调用一个方法执行一个ajax请求一个js文件,并执行
- 更重要的是,它可以操作window上所有的方法
- ……
那怎么解决呢?我最初想到的办法是:不改变现在白名单的情况下,增加域名白名单,只有在域名白名单里的域名才能执行。与此同时,遇到的一个问题是,我无法在proxy中,判断对我请求的域名是否合法。我最初想到的两种获得域名的方式是:document.referrer和parent.document.domain,下面我简单说明这两种形式为什么能判断。
无论通过那种方式限制,最重要的一点不能忘记:合法的请求,不能被限制。如果第三方采用iframe引用的话,犹豫同源策略,parent.document.domain会抛出异常,无法进行判断;至于document.rederrer的问题在于,如果嵌套多层iframe的话,我的reffer是正常的,其实还是非法的引用。
既然这个也被否定了,我到底怎么办呢?难道真的没办法防住这个吗?我又重新思考了一遍,为什么会出现这个xss漏洞呢?最主要的原因还是这个函数名。现在所做的没有对函数名进行严格控制,只是在判断包含关系。所以接下来要做的就是限制死函数名,只能是我的filter里的,可以通过恒等或者是正则匹配完成。
/**
* callback的值为:namespace.function,prefix123456,prefix1231321
*/
var filter = [
'namespace.function',
/^prefix\d$/
];
//验证函数,返回true时,return
var validateCallback = function (callback) {
var flag = true;
for(var i=0;i<filter.length;i++) {
if(typeof filter[i] === 'string') {
if(filter[i] === callback) {
flag = false;
}
}else {
if(filter[i].test(callback)) {
flag = false;
}
}
}
return flag;
} if(validateCallback(callback)) {
return;
}
通过上面的这种形式,暂时解决了这个XSS漏洞。当然这个问题还是一个长期的问题,还是需要长期跟进,遇到问题,随时解决。
最新文章
- [No0000AA]Windows 系统环境变量列表
- GO语言练习:网络编程 ICMP 示例
- 【读书笔记】iOS-安全地传输用户密码的方法
- java.security.NoSuchAlgorithmException: DES KeyGenerator not available
- $.toJSON的用法或把数组转换成json类型
- Hadoop常见的45个问题解答
- Phonegap 3.0 拍照 出错的说明
- Docker入门之三容器
- 个人觉得实用的Python姿势
- three.js使用base64 图片创建Texture纹理
- LinkedList源码分析和实例应用
- bin内置函数
- iBeacon室内定位原理解析【转】
- Ubuntu中编译helloworld驱动
- MongoDB副本集配置系列六:定位MongoDB慢的原因
- SharePoint 2010、2013多个域之间互信(Domain Trust)的设计与实施
- (转)web开发流程
- Homebrew设置代理
- 使用PLSQL Developer和DbVisualizer、SQLDBx查询oracle数据库时出现乱码
- [转]AngularJS 之 Factory vs Service vs Provider
热门文章
- iOS语音识别,语音播报,文字变语音播报,语音变文字
- [深入React] 8.refs
- (转)苹果推送通知服务教程 Apple Push Notification Services Tutorial
- windows服务程序
- Web安全测试之XSS(跨站脚本攻击)
- Ubuntu 14.04 下手动安装Firefox的Flash插件
- Struts的核心配置
- Shell防DDOS攻击原理
- 网页CSS2
- Map Resource Definition 中type为 &#39;ArcGIS Server Local&#39;.