使用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 相关文章推荐
jquery ajax学习笔记2 使用XMLHttpRequest对象的responseXML
Oct 16 Javascript
js获取某月的最后一天日期的简单实例
Jun 22 Javascript
JavaScript—window对象使用示例
Dec 09 Javascript
浅谈页面装载js及性能分析方法
Dec 09 Javascript
JavaScript代码性能优化总结篇
May 15 Javascript
jquery实现下拉框左右选择功能
Feb 21 Javascript
非常实用的vue导航钩子
Mar 20 Javascript
js+css实现打字效果
Jun 24 Javascript
vue生成文件本地打开查看效果的实例
Sep 06 Javascript
Vue中跨域及打包部署到nginx跨域设置方法
Aug 26 Javascript
有关vue 开发钉钉 H5 微应用 dd.ready() 不执行问题及快速解决方案
May 09 Javascript
vue项目打包后提交到git上为什么没有dist这个文件的解决方法
Sep 16 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
php session 检测和注销
2009/03/16 PHP
php过滤所有恶意字符(批量过滤post,get敏感数据)
2014/03/18 PHP
php和html的区别点详细总结
2019/09/24 PHP
php array 转json及java 转换 json数据格式操作示例
2019/11/13 PHP
YII2框架中ActiveDataProvider与GridView的配合使用操作示例
2020/03/18 PHP
JSON 入门指南 想了解json的朋友可以看下
2009/08/26 Javascript
用JSON做数据传输格式中的一些问题总结
2011/12/21 Javascript
node.js中的fs.symlinkSync方法使用说明
2014/12/15 Javascript
编写自己的jQuery提示框(Tip)插件
2015/02/05 Javascript
NodeJs实现定时任务的示例代码
2017/12/05 NodeJs
详解Vue-cli webpack移动端自动化构建rem问题
2018/04/07 Javascript
浅谈Vue数据响应
2018/11/05 Javascript
vue 右键菜单插件 简单、可扩展、样式自定义的右键菜单
2018/11/29 Javascript
webpack4手动搭建Vue开发环境实现todoList项目的方法
2019/05/16 Javascript
编写更好的JavaScript条件式和匹配条件的技巧(小结)
2019/06/27 Javascript
JS call()及apply()方法使用实例汇总
2020/07/11 Javascript
详解ES6中class的实现原理
2020/10/03 Javascript
[02:28]DOTA2 2017国际邀请赛小组赛回顾
2017/08/09 DOTA
[01:15:56]2018DOTA2亚洲邀请赛3月30日 小组赛A组 TNC VS Newbee
2018/03/31 DOTA
Django中的CACHE_BACKEND参数和站点级Cache设置
2015/07/23 Python
详解使用pymysql在python中对mysql的增删改查操作(综合)
2017/01/18 Python
对Python 检查文件名是否规范的实例详解
2019/06/10 Python
Python3 虚拟开发环境搭建过程(图文详解)
2020/01/06 Python
Python txt文件常用读写操作代码实例
2020/08/03 Python
python GUI计算器的实现
2020/10/09 Python
美国知名的在线旅游服务网站:Priceline
2016/07/23 全球购物
夏威夷航空官网:Hawaiian Airlines
2016/09/11 全球购物
中国海淘族值得信赖的海淘返利网站:55海淘
2017/01/16 全球购物
设计师大码女装:11 Honoré
2020/05/03 全球购物
餐厅筹备计划书
2014/04/25 职场文书
本科应届生自荐信
2014/06/29 职场文书
乡镇民主生活会发言材料
2014/10/20 职场文书
Python爬虫数据的分类及json数据使用小结
2021/03/29 Python
开机音效回归! Windows 11重新引入开机铃声
2021/11/21 数码科技
python三子棋游戏
2022/05/04 Python
Go语言编译原理之变量捕获
2022/08/05 Golang