使用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 16 Javascript
aspx中利用js实现确认删除代码
Jul 22 Javascript
自用js开发框架小成 学习js的朋友可以看看
Nov 16 Javascript
js 通用javascript函数库整理
Aug 14 Javascript
自定义的一个简单时尚js下拉选择框
Nov 20 Javascript
完美兼容各大浏览器的jQuery仿新浪图文淡入淡出间歇滚动特效
Nov 12 Javascript
jQuery实现的向下图文信息滚动效果
May 03 Javascript
jQuery Validate 数组 全部验证问题
Jan 12 Javascript
深入理解Node中的buffer模块
Jun 03 Javascript
微信小程序picker组件简单用法示例【附demo源码下载】
Dec 05 Javascript
使用Object.defineProperty如何巧妙找到修改某个变量的准确代码位置
Nov 02 Javascript
Vue 2.0 中依赖注入 provide/inject组合实战
Jun 20 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
咖啡的化学
2021/03/03 咖啡文化
PHP4和PHP5共存于一系统
2006/11/17 PHP
CentOS6.5 编译安装lnmp环境
2014/12/21 PHP
PHP面向对象程序设计重载(overloading)操作详解
2019/06/13 PHP
Laravel使用RabbitMQ的方法示例
2019/06/18 PHP
html下载本地
2006/06/19 Javascript
Jquery AJAX 用于计算点击率(统计)
2010/06/30 Javascript
jquery 鼠标滑动显示详情应用示例
2014/01/24 Javascript
jquery form 加载数据示例
2014/04/21 Javascript
javascript 寻找错误方法整理
2014/06/15 Javascript
js获取浏览器基本信息大全
2014/11/27 Javascript
JavaScript SHA512&amp;SHA256加密算法详解
2015/08/11 Javascript
Vue.js快速入门教程
2016/09/07 Javascript
Ajax使用原生态JS验证用户名是否存在
2020/05/26 Javascript
JQuery控制DIV的选取实现方法
2016/09/18 Javascript
js html5 css俄罗斯方块游戏再现
2016/10/17 Javascript
基于js实现二级下拉联动
2016/12/17 Javascript
javascript简单写的判断电话号码实例
2017/05/24 Javascript
Vue + better-scroll 实现移动端字母索引导航功能
2018/05/07 Javascript
vue的for循环使用方法
2019/02/12 Javascript
详解jQuery设置内容和属性
2019/04/11 jQuery
[39:07]LGD vs VP 2018国际邀请赛淘汰赛BO3 第二场 8.21
2018/08/22 DOTA
Python cookbook(数据结构与算法)让字典保持有序的方法
2018/02/18 Python
Python对接六大主流数据库(只需三步)
2019/07/31 Python
使用CSS实现弹性视频html5案例实践
2012/12/26 HTML / CSS
html5借用repeating-linear-gradient实现一把刻度尺(ruler)
2019/09/09 HTML / CSS
Evisu官方网站:日本牛仔品牌,时尚街头设计风格
2016/12/30 全球购物
夏威夷灵感服装及配饰:Reyn Spooner
2018/09/18 全球购物
写一个在SQL Server创建表的SQL语句
2012/03/10 面试题
大学秋游活动方案
2014/02/11 职场文书
个人担保书格式范文
2014/05/12 职场文书
甜品蛋糕店创业计划书
2014/09/21 职场文书
2015年基层党组织公开承诺书
2015/01/21 职场文书
《田忌赛马》教学反思
2016/02/19 职场文书
Python机器学习之底层实现KNN
2021/06/20 Python
JavaScript设计模式之原型模式详情
2022/06/21 Javascript