使用AngularJS中的SCE来防止XSS攻击的方法


Posted in Javascript onJune 18, 2015

这篇文章展示了有关XSS(跨站脚本)的不同方案以及怎样使用AngularJS中SCE($sceProvider),sanitize service这些特性来正确处理XSS。如果我遗漏了什么重要的地方请直接评论/建议。同时,错别字请见谅。

以下几点内容将是我接下来要讲述的重点:

  •     全部转码HTML
  •     安全插入HTML的同时忽略类似“script"这样的标签。如果不加以注意,这将一样存在风险同时也会丑化页面,尤其是在有”img“标签的时候。
  •     依赖并插入纯HTML;这也有风险的同时会让网页很难看。

使用ng-bind指令转码HTML

你可以用ng-bind指令来转码整个网页。它将会转码所有HTML标签但是仍然显示本来的样子。下列代码显示了ng-bind的用法。 

<div>
<form>
  <h1>AngularJS XSS Demo Test</h1>
  <hr/>
  <div class="col-md-12">
  <input type="text" ng-model="name" class="form-control col-md-12" ng-change="processHtmlCode()" placeholder="Enter Some HTML Text..."/>
  </div>
</form>
</div>
<hr/>
<div style="padding:20px">
  <span><strong>ng-bind directive: Note that HTML text is entered as it is.</strong></span><br/>
  <span ng-bind="helloMessage">{{helloMessage}}</span>
</div>

下面的图证明了以上言论。注意在输入栏中的HTML代码。它和在HTML页面中完全一样。

使用AngularJS中的SCE来防止XSS攻击的方法

使用安全的方式插入HTML,也可以使用 ng-bind-html 指令忽略掉诸如“script”这样的元素

这是解决XSS攻击的关键. 也就是说,你仍然应该关注诸如“img"这样的元素 ( 作为一部分包含进了白名单中; 还有空元素) 因为它恩能够在你的web页面上展示任何图片 (包括非法的那些), 因此,它也可能会给你的web页面带来不利影响. 使用 ng-bind-html 指令皆可以AngularJS诸如“script”这样的JavaScript标记直接被忽略掉. ng-bind-html 指令会计算表达式,并且用一种安全的方式将结果HTML插入元素中. 对于用户会输入包含了HTML内容(比如在评论中)的情况,放到 ng-bind-html指令中可以确保文本被编码为白名单中的安全HTML字符. 安全字符的白名单被作为 $sanitize 的一部分编码,下面会讲到. 下面这些都被包含进了安全列表中 (直接从源代码中获得):

    空元素:

area,br,col,hr,img,wbr.
详细信息请访问 http://dev.w3.org/html5/spec/Overview.html#void-elements

    块元素:

address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul

    内联元素:

a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var

    结尾标记元素:

colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr,rp,rt.
详细信息请访问 http://dev.w3.org/html5/spec/Overview.html#optional-tags

下面的这两个元素 因为其内容不收信任,需要被规避掉. 在这种情况下,如果你想要展示它们,就要使用 $sce 服务,调用Angular 的 trustAsHtml 方法来执行下面提到的元素.

  •     script
  •     style

如下呈现的代码展示了 ng-bind-html 指令的使用.
 

<div>
<form>
  <h1>AngularJS XSS Demo Test</h1>
  <hr/>
  <div class="col-md-12">
  <input type="text" ng-model="name" class="form-control col-md-12" ng-change="processHtmlCode()" placeholder="Enter Some HTML Text..."/>
  </div>
</form>
</div>
<hr/>
<div style="padding:20px">
  <span>ng-bind-html directive: Note that image is displayed appropriately as a result of text entered in the text field.</span>
  <span ng-bind-html="helloMessage"></span>
</div>

下面这张图片展示了当在文本域中输入HTML代码,Angular用一种安全的方式插入到DOM时,是什么样子的. 注意 “img” 元素是上述列表中空元素的一份子. 因为代码被输入到了文本域中,作为”img"出现的图片被放到了受信任的列表(白名单)中。

使用AngularJS中的SCE来防止XSS攻击的方法

信任并插入整段HTML

警告: 这很危险,并且可能很容易就最终造成你web站点的污染. 只有当你知道并且充分确认时,你才应该使用 trustAsHtml. 如此,你就有充足的信心认为这段文本是可以被信任的, 你应该使用$sce 服务并且调用 trustAsHtml 方法来讲整段HTML插入DOM中。在$sce服务被用来调用 trustAsHtml 方法来信任一段HTML代码时,请留意HTML和其中的JavaScript代码块. 在这种情况下,一段诸如 “<style>.hello{color:red}</style>” 这样的代码被插入了,它最后可能会也给现有的HTML元素加上样式。这可能不是很好。人们也可能采用那种方式用非法的图片替换背景图片.
 

<script type="text/javascript">
  angular.module('HelloApp', ["ngSanitize"])
  .controller('HelloCtrl', ['$scope', '$sce', function($scope, $sce){
    $scope.name="";
    $scope.processHtmlCode  =  function() {
      $scope.helloMessage = "<h1>" + $scope.name + "</h1>";  
      $scope.trustedMessage = $sce.trustAsHtml( $scope.name );
    }
  }])
 
  </script>
<!-- Pay attention to class hello which is coded in UI and as a result, element is painted in red-->
<div style="padding:20px">
    <span class="hello"><strong>ng-bind directive: Note that HTML text is entered as it is.</strong></span><br/>
    <span class="hello" ng-bind="helloMessage">{{helloMessage}}</span>
</div>
<hr/>
<div style="padding:20px">
    <span>Note that script tag is executed as well.</span>
    <span ng-bind-html="trustedMessage"></span>
</div>

下面的图片展示了当在文本域中输入将要被插入DOM中的HTML样式代码时,会是什么样子. 这里的结果就是, 其它的HTML元素也带上了红色, 如下所示. 在某些场景中,黑客可能会插入一段带有背景样式越苏,这可能会显示出原本不要被显示的背景,给最终用户带来糟糕的体验.

使用AngularJS中的SCE来防止XSS攻击的方法 

<html>
<head>
  <title>Hello AngularJS</title>
  <link rel="stylesheet" type="text/css" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.3/angular.min.js"></script>
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.3/angular-sanitize.min.js"></script>
</head>
<body class="container" ng-app="HelloApp" ng-controller="HelloCtrl">
  <div>
    <form>
      <h1>AngularJS XSS Demo Test</h1>
      <hr/>
      <div class="col-md-12">
        <input type="text" ng-model="name" class="form-control col-md-12" ng-change="processHtmlCode()" placeholder="Enter Some HTML Text..."/>
      </div>
    </form>
    <hr/>
  </div>
  <hr/>
  <div style="padding:20px">
    <span class="hello"><strong>ng-bind directive: Note that HTML text is entered as it is.</strong></span><br/>
    <span class="hello" ng-bind="helloMessage">{{helloMessage}}</span>
  </div>
  <hr/>
  <div style="padding:20px">
    <span>Note that script tag is executed as well.</span>
    <span ng-bind-html="trustedMessage"></span>
  </div>
  <hr/>
  <div style="padding:20px">
    <span>ng-bind-html directive: Note that image is displayed appropriately as a result of text entered in the text field.</span>
    <span ng-bind-html="helloMessage"></span>
  </div>
  <hr/>
  <script type="text/javascript">
  angular.module('HelloApp', ["ngSanitize"])
  .controller('HelloCtrl', ['$scope', '$sce', function($scope, $sce){
    $scope.name="";
    $scope.processHtmlCode  =  function() {
      $scope.helloMessage = "<h1>" + $scope.name + "</h1>";  
      $scope.trustedMessage = $sce.trustAsHtml( $scope.name );
    }
  }])
 
  </script>
</body>
</html>
Javascript 相关文章推荐
javascript下判断一个对象是否具有指定名称的属性的的代码
Jan 11 Javascript
js中onload与onunload的使用示例
Aug 25 Javascript
jQuery点缩略图弹出层显示大图片
Feb 13 Javascript
Bootstrap学习笔记之css组件(3)
Jun 07 Javascript
BootStrap智能表单实战系列(七)验证的支持
Jun 13 Javascript
浅谈EasyUI常用控件的禁用方法
Nov 09 Javascript
js监听input输入框值的实时变化实例
Jan 26 Javascript
浅谈手写node可读流之流动模式
Jun 01 Javascript
JS中的算法与数据结构之列表(List)实例详解
Aug 16 Javascript
深入探索VueJS Scoped CSS 实现原理
Sep 23 Javascript
js+css实现全屏侧边栏
Jun 16 Javascript
vue pages 多入口项目 + chainWebpack 全局引用缩写说明
Sep 21 Javascript
初步认识JavaScript函数库jQuery
Jun 18 #Javascript
用JavaScript显示浏览器客户端信息的超相近教程
Jun 18 #Javascript
浅谈Jquery核心函数
Jun 18 #Javascript
$.extend 的一个小问题
Jun 18 #Javascript
纯js实现无限空间大小的本地存储
Jun 18 #Javascript
JS实现当前页居中分页效果的方法
Jun 18 #Javascript
javascript中Date()函数在各浏览器中的显示效果
Jun 18 #Javascript
You might like
Terran历史背景
2020/03/14 星际争霸
php中iconv函数使用方法
2008/05/24 PHP
PHP编写daemon process 实例详解
2016/11/13 PHP
php的4种常用运行方式详解
2016/12/22 PHP
Laravel 6.2 中添加了可调用容器对象的方法
2019/10/22 PHP
IE中直接运行显示当前网页中的图片 推荐
2006/08/31 Javascript
JS读取cookies信息(记录用户名)
2012/01/10 Javascript
jQuery获取(选中)单选,复选框,下拉框中的值
2014/02/21 Javascript
使用typeof判断function是否存在于上下文
2014/08/14 Javascript
基于jQuery实现多标签页切换的效果(web前端开发)
2016/07/24 Javascript
vue中使用GraphQL的实例代码
2019/11/04 Javascript
jQuery Datatables 动态列+跨列合并实现代码
2020/01/30 jQuery
Node.js中文件系统fs模块的使用及常用接口
2020/03/06 Javascript
Node Mongoose用法详解【Mongoose使用、Schema、对象、model文档等】
2020/05/13 Javascript
[03:28]2014DOTA2国际邀请赛 EG战队官方纪录片
2014/07/21 DOTA
python实现探测socket和web服务示例
2014/03/28 Python
Python实现在Linux系统下更改当前进程运行用户
2015/02/04 Python
使用Python脚本操作MongoDB的教程
2015/04/16 Python
python 2.6.6升级到python 2.7.x版本的方法
2016/10/09 Python
matplotlib 纵坐标轴显示数据值的实例
2018/05/25 Python
对Python 数组的切片操作详解
2018/07/02 Python
Python饼状图的绘制实例
2019/01/15 Python
windows10 pycharm下安装pyltp库和加载模型实现语义角色标注的示例代码
2020/05/07 Python
使用Nibabel库对nii格式图像的读写操作
2020/07/01 Python
iframe在移动端的缩放的示例代码
2018/10/12 HTML / CSS
加拿大健康、婴儿和美容产品在线购物:Well.ca
2016/11/30 全球购物
Eyeko美国:屡获殊荣的睫毛膏、眼线笔和眉妆
2018/07/05 全球购物
现金会计岗位职责
2013/12/05 职场文书
安全资料员岗位职责
2013/12/14 职场文书
18岁生日感言
2014/01/12 职场文书
安全生产先进个人材料
2014/02/06 职场文书
春游踏青活动方案
2014/08/14 职场文书
厨师长岗位职责范本
2014/08/25 职场文书
关于运动会的广播稿(10篇)
2014/09/12 职场文书
nginx反向代理时如何保持长连接
2021/03/31 Servers
Django 如何实现文件上传下载
2021/04/08 Python