场景回顾

一个表单进行跨域提交的方式有很多,我们使用的采用隐藏iframe,在本域下放一个代理页面,通过服务端配合完成一次完整的请求。

首先,部署proxy.html代理页面。这个页面处理服务端返回的数据,并执行接口的回调函数。接口请求成功后,返回的是:

<script>location.href='http://www.a.com/proxy.html?fun=callback&a=1&b=2&c=3';</script>

proxy页面,解析服务端传回的参数最后执行:

callback({

        a:1,

        b:2,

        c:3

    });

这样就完成了一次,接口请求并且在请求成功后,执行回调。

其次,页面上需要有一个隐藏的iframe,把请求发到这个页面,然后接受返回值。

整体上是这么一个过程,实现了post请求的跨域提交。

proxy.html的代码:

<!doctype html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body><script type="text/javascript">
(function(){
var queryStr = location.search.substring(1).split('&'),oneQueryStr,args = {},g = top,scope = top ,callback;
for(var i in queryStr){
oneQueryStr = queryStr[i].split('=');
if(!callback && oneQueryStr[0] == 'fun'){
callback = oneQueryStr[1];
};
if(oneQueryStr[0]&&oneQueryStr[1]){
args[oneQueryStr[0]] = (oneQueryStr[1]||'').replace(/[><'"{}]/g, '');
} }
callback = callback.split('.'); if( callback[0] === 'document'
|| callback[0] === 'location'
|| callback[0] === 'alert'){
}else{
for(var i = 0,len= callback.length;i<len;i++){
if(i==0 && callback[0]=="parent"){
g = parent;
scope = parent;
}else if(i==0 && callback[0]=="top"){
g = top;
scope = top;
}else{
if(i<len-1){
scope = scope[callback[i]];
}
g = g[callback[i]];
}
} g.call(scope,args);
} })();
</script>
</body></html>

XSS漏洞

很显然,既然页面上执行了接口返回的数据。那么就必须对返回的数据进行过滤,这样才能防止恶意的代码进行攻击。

看了上面proxy.html的代码我们发现,已经处理了fun这个参数的值,不能为alert、document、location这些值。这是通过黑名单机制来进行判断的,一旦命中就无法执行。但是一直存在这么一个问题:我们能防的只是我们所了解的XSS漏洞,如果我们不知道,就需要遇到问题,解决问题,这样显然很被动。

有这么一个攻击案例,即便是我们已经过滤了alert、document这些window下的方法,但是还有我们不知道的方法无法防御,这就增大了我们的维护成本。在我们业务里,带来的问题是:每次调整这个文件,整个公司的业务可能都会被牵扯进来,都要升级很被动。

上面的这个例子就是掉用了页面上给window下扩展的$,这个变量对于前端的同学都不陌生。这个$能干的事情就更多了,简直太可怕了。这个案例只是打印了你的cookie,他可以做很多很多的事情,后果可以预想...

解决方案

还是要过滤fun参数,这个『万恶之源』,采用的方式的白名单+黑名单,双层防护。首先使用白名单进行过滤,白名单设置的是业务所用的函数名,其他的都不信任;其次,白名单如果验证通过后,在进行黑名单验证。为什么还需要这么异步操作呢?主要的担心有这么一个方法,白名单会通过,但是又是无用的方法,这样就可以使用黑名单在此过滤。

后续跟进

我现在的这个处理方式不一定是最好的,也可能存在问题。在这里提出,有两方面的考虑。其一:想要获得更好的方案来解决这个问题;其二:攻击和防守是一个持续的问题,需要一直跟进,逐渐找到合理的解决方案。如果有更好的方案,也希望不吝赐教!

最新文章

  1. sql server中对xml进行操作
  2. CentOS 6.4 查看每个进程的网络流量
  3. 最小生成树 2429: [HAOI2006]聪明的猴子
  4. STM32F0xx_DAC输出电压配置详细过程
  5. 看来是要改用Gecko的节奏,放弃Awesomium吧
  6. iOS开发--调试必备 — NSLog
  7. TDirectory.GetLogicalDrives获取本地逻辑驱动器
  8. Android app自动化测试之Python+Appium环境搭建
  9. bzoj:1673 [Usaco2005 Dec]Scales 天平
  10. 前端的UI设计与交互之图标篇
  11. 【一天一道LeetCode】#303.Range Sum Query - Immutable
  12. Nginx status详解
  13. robotframework中的try exception。断言失败后,后面语句能继续执行
  14. mvc 分页PagedList简单使用
  15. [转] ElasticSearch 常用的查询过滤语句
  16. Hadoop 系列文章(二) Hadoop配置部署启动HDFS及本地模式运行MapReduce
  17. hiho 第七周 完全背包
  18. dp问题 -挑战例题 2017-7-24
  19. Unity3D中随机函数的应用
  20. 关于mysql中storage_engine中 MYISAM 和 INNODB 的选择

热门文章

  1. Hibernate的几种查询方式-HQL,QBC,QBE,离线查询,复合查询,分页查询
  2. PhoneGap 和 PhoneGap Build 是什么?
  3. Android静态变量使用陷阱
  4. Counting Squares_hdu_1264(矩阵).java
  5. Div与table的区别
  6. Gunplot 命令大全
  7. OC-字典&amp;数组运用实例:通讯录的实现
  8. C#图像处理(3):在图像上加条形码
  9. OD调试6—使未注册版软件的功能得以实现
  10. 移动web开发中遇到的一些问题收纳