Dieser Artikel zeigt verschiedene Lösungen für XSS (Cross-Site-Scripting) und wie man SCE ($sceProvider) verwendet und Dienstfunktionen in AngularJS bereinigt, um XSS korrekt zu verarbeiten. Wenn ich etwas Wichtiges verpasst habe, kommentieren/schlagen Sie es bitte direkt. Bitte verzeihen Sie mir auch Tippfehler.
Die folgenden Punkte werden im Mittelpunkt dessen stehen, worüber ich als nächstes sprechen werde:
Verwenden Sie die ng-bind-Direktive, um HTML zu transkodieren
Sie können die ng-bind-Direktive verwenden, um die gesamte Webseite zu transkodieren. Alle HTML-Tags werden transkodiert, sie werden aber weiterhin so angezeigt, wie sie sind. Der folgende Code zeigt die Verwendung von 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>
Das Bild unten beweist die obige Aussage. Beachten Sie den HTML-Code im Eingabefeld. Es ist genau das Gleiche wie auf einer HTML-Seite.
Fügen Sie HTML auf sichere Weise ein oder verwenden Sie die ng-bind-html-Direktive, um Elemente wie „script“ zu ignorieren
Dies ist der Schlüssel zur Lösung von XSS-Angriffen. Dennoch sollten Sie auf Elemente wie „img“ achten (in der Whitelist enthalten; ebenso wie auf leere Elemente), da diese auf Ihren Webseiten verwendet werden können Zeigen Sie jedes Bild (einschließlich illegaler) darauf an, daher kann es sich auch negativ auf Ihre Webseite auswirken. Mit der ng-bind-html-Direktive können AngularJS-JavaScript-Tags wie „script“ direkt ignoriert werden. Die bind-html-Direktive wertet den Ausdruck aus und fügt den resultierenden HTML-Code auf sichere Weise in das Element ein. In Situationen, in denen der Benutzer Eingaben eingibt, die HTML-Inhalte enthalten (z. B. in einem Kommentar), fügen Sie diese in die ng-bind-html-Direktive ein Dadurch wird sichergestellt, dass der Text als Whitelist sicherer HTML-Zeichen codiert wird, wie unten beschrieben. Folgendes ist in der sicheren Liste enthalten (direkt aus dem Quellcode erhalten):
Leeres Element:
Blockelement:
Inline-Elemente:
End-Tag-Element:
Die folgenden beiden Elemente müssen umgangen werden, da ihr Inhalt nicht vertrauenswürdig ist. Wenn Sie sie in diesem Fall anzeigen möchten, müssen Sie den Dienst $sce verwenden und die Methode „trustAsHtml“ von Angular aufrufen, um die unten genannten Elemente auszuführen.
Der unten dargestellte Code demonstriert die Verwendung der ng-bind-html-Direktive.
<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"出现的图片被放到了受信任的列表(白名单)中。
信任并插入整段HTML
警告: 这很危险,并且可能很容易就最终造成你web站点的污染. 只有当你知道并且充分确认时,你才应该使用 trustAsHtml. 如此,你就有充足的信心认为这段文本是可以被信任的, 你应该使用$sce 服务并且调用 trustAsHtml 方法来讲整段HTML插入DOM中。在$sce服务被用来调用 trustAsHtml 方法来信任一段HTML代码时,请留意HTML和其中的JavaScript代码块. 在这种情况下,一段诸如 “” 这样的代码被插入了,它最后可能会也给现有的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元素也带上了红色, 如下所示. 在某些场景中,黑客可能会插入一段带有背景样式越苏,这可能会显示出原本不要被显示的背景,给最终用户带来糟糕的体验.
<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>