使用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高级程序设计(第3版)学习笔记5 js语句
Oct 11 Javascript
标题过长使用javascript按字节截取字符串
Apr 24 Javascript
JavaScript实现大图轮播效果
Jan 11 Javascript
使用JavaScript实现alert的实例代码
Jul 06 Javascript
Angular中的$watch方法详解
Sep 18 Javascript
vue学习教程之带你一步步详细解析vue-cli
Dec 26 Javascript
vue中使用cookies和crypto-js实现记住密码和加密的方法
Oct 18 Javascript
Three.JS实现三维场景
Dec 30 Javascript
JavaScript寄生组合式继承原理与用法分析
Jan 11 Javascript
vue+高德地图写地图选址组件的方法
May 18 Javascript
如何实现iframe父子传参通信
Feb 05 Javascript
关于对TypeScript泛型参数的默认值理解
Jul 15 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
一个简易需要注册的留言版程序
2006/10/09 PHP
IP攻击升级,程序改进以对付新的攻击
2010/11/23 PHP
php获取表单中多个同名input元素的值
2014/03/20 PHP
php使用百度天气接口示例
2014/04/22 PHP
PHP实现搜索地理位置及计算两点地理位置间距离的实例
2016/01/08 PHP
基于Jquery的表格隔行换色,移动换色,点击换色插件
2010/12/22 Javascript
jQuery实现表格颜色交替显示的方法
2015/03/09 Javascript
jquery+html5制作超酷的圆盘时钟表
2015/04/14 Javascript
详解JavaScript操作HTML DOM的基本方式
2015/10/21 Javascript
JS组件Bootstrap按钮组与下拉按钮详解
2016/05/10 Javascript
javascript超过容器后显示省略号效果的方法(兼容一行或者多行)
2016/07/14 Javascript
React.Js添加与删除onScroll事件的方法详解
2017/11/03 Javascript
redux中间件之redux-thunk的具体使用
2018/04/17 Javascript
JS与jQuery判断文本框还剩多少字符可以输入的方法
2018/09/01 jQuery
详解Vuex下Store的模块化拆分实践
2019/07/31 Javascript
微信小程序封装多张图片上传api代码实例
2019/12/30 Javascript
微信小程序中的video视频实现 自定义播放按钮、封面图、视频封面上文案
2020/01/02 Javascript
深入理解Python 代码优化详解
2014/10/27 Python
Python编程中的文件操作攻略
2015/10/16 Python
Python对接 xray 和微信实现自动告警
2019/09/17 Python
python文件读写代码实例
2019/10/21 Python
django数据模型on_delete, db_constraint的使用详解
2019/12/24 Python
html5的pushstate以及监听浏览器返回事件的实现
2020/08/11 HTML / CSS
MANGO官方网站:西班牙芒果服装品牌
2017/01/15 全球购物
美国女性奢华品牌精品店:INTERMIX
2017/10/12 全球购物
美国领先的在线旅游网站:Orbitz
2018/11/05 全球购物
运动鞋、街头服装、手表和手袋的实时市场:StockX
2020/11/25 全球购物
移动通信行业实习自我鉴定
2013/09/28 职场文书
2013年保送生自荐信格式
2013/11/20 职场文书
小学生作文评语
2014/04/18 职场文书
教师考核评语大全
2014/12/31 职场文书
确保工程质量承诺书
2015/04/29 职场文书
运动会主持词大全
2015/07/02 职场文书
新闻通讯稿范文
2015/07/22 职场文书
关于flex 上下文中自动 margin的问题(完整例子)
2021/05/20 HTML / CSS
Python OpenCV 图像平移的实现示例
2021/06/04 Python