ホームページ >ウェブフロントエンド >jsチュートリアル >AngularJS_AngularJS で SCE を使用して XSS 攻撃を防ぐ方法

AngularJS_AngularJS で SCE を使用して XSS 攻撃を防ぐ方法

WBOY
WBOYオリジナル
2016-05-16 15:54:211936ブラウズ

この記事では、XSS (クロスサイト スクリプティング) のさまざまなソリューションと、SCE ($sceProvider) を使用して AngularJS のサービス機能をサニタイズして XSS を正しく処理する方法を示します。重要な点を見逃した場合は、直接コメント/提案してください。また、誤字脱字はご容赦ください。

次に説明する内容は次の点に焦点を当てます。

  • すべての HTML をトランスコードします
  • 「script」などのタグを無視して HTML を安全に挿入します。これに注意しないと、特に「img」タグがある場合、これは危険であり、ページが醜くなる可能性があります。
  • 純粋な HTML に依存して挿入することは危険であり、Web ページの見栄えが悪くなります。

ng-bind ディレクティブを使用して HTML をトランスコードする

ng-bind ディレクティブを使用して、Web ページ全体をトランスコードできます。すべての 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 ページとまったく同じです。

2015618103137625.png (1024×197)

安全な方法で HTML を挿入するか、ng-bind-html ディレクティブを使用して「script」などの要素を無視します

これが XSS 攻撃を解決する鍵となりますが、「img」などの要素 (空の要素と同様にホワイトリストの一部として含まれます) は Web ページで使用される可能性があるため、注意を払う必要があります。そのため、ng-bind-html ディレクティブを使用すると、ng-bind-html などの AngularJS JavaScript タグを直接無視できます。 bind-html ディレクティブは式を評価し、結果の HTML を安全な方法で要素に挿入します。ユーザーが HTML コンテンツを含む入力を入力する場合 (コメントなど)、それを ng-bind-html ディレクティブに置きます。これにより、テキストが安全な HTML 文字のホワイトリストとしてエンコードされるようになります。安全な文字のホワイトリストは、以下で説明するように、セーフ リストに含まれます (ソース コードから直接取得されます)。 >

空の要素:

コードをコピー コードは次のとおりです:
area,br,col,hr,img
詳細については、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 、テーブル、ウル
インライン要素:

コードをコピー コードは次のとおりです:
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 をご覧ください

次の 2 つの要素は、コンテンツが信頼されていないため、回避する必要があります。この場合、それらを表示するには、$sce サービスを使用して、Angular の trustAsHtml メソッドを呼び出して、以下の要素を実行する必要があります。

    スクリプト
  • スタイル
以下に示すコードは、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"出现的图片被放到了受信任的列表(白名单)中。

2015618103202003.png (1024×462)

信任并插入整段HTML

警告: 这很危险,并且可能很容易就最终造成你web站点的污染. 只有当你知道并且充分确认时,你才应该使用 trustAsHtml. 如此,你就有充足的信心认为这段文本是可以被信任的, 你应该使用$sce 服务并且调用 trustAsHtml 方法来讲整段HTML插入DOM中。在$sce服务被用来调用 trustAsHtml 方法来信任一段HTML代码时,请留意HTML和其中的JavaScript代码块. 在这种情况下,一段诸如 “c9ccee2e6ea535a969eb3f532ad9fe89.hello{color:red}531ac245ce3e4fe3d50054a55f265927” 这样的代码被插入了,它最后可能会也给现有的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元素也带上了红色, 如下所示. 在某些场景中,黑客可能会插入一段带有背景样式越苏,这可能会显示出原本不要被显示的背景,给最终用户带来糟糕的体验.

2015618103229268.png (1024×254) 

<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>

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。