Maison > Article > interface Web > Comment empêcher les attaques XSS à l'aide de SCE dans AngularJS_AngularJS
Cet article présente différentes solutions pour XSS (cross-site scripting) et comment utiliser le SCE ($sceProvider) et nettoyer les fonctionnalités du service dans AngularJS pour gérer correctement XSS. Si j'ai raté quelque chose d'important, veuillez commenter/suggérer directement. Veuillez également me pardonner les fautes de frappe.
Les points suivants seront au centre de ce dont je parlerai ensuite :
Utilisez la directive ng-bind pour transcoder le HTML
Vous pouvez utiliser la directive ng-bind pour transcoder la page Web entière. Il transcodera toutes les balises HTML mais les affichera telles quelles. Le code suivant montre l'utilisation de 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>
L'image ci-dessous prouve la déclaration ci-dessus. Notez le code HTML dans le champ de saisie. C'est exactement la même chose que dans une page HTML.
Insérez du HTML de manière sécurisée, ou utilisez la directive ng-bind-html pour ignorer les éléments tels que "script"
C'est la clé pour résoudre les attaques XSS. Cela dit, vous devez toujours faire attention aux éléments tels que "img" (inclus dans la liste blanche ; ainsi que les éléments vides) car ils peuvent être utilisés dans vos pages Web. Affichez n'importe quelle image (y compris les images illégales), par conséquent, cela peut également avoir un impact négatif sur votre page Web. En utilisant la directive ng-bind-html, les balises JavaScript AngularJS telles que "script" peuvent être ignorées directement. La directive bind-html évalue l'expression et insère le HTML résultant dans l'élément de manière sûre. Pour les situations où l'utilisateur entrera une entrée contenant du contenu HTML (comme dans un commentaire), placez-la dans la directive ng-bind-html. Cela garantit que le texte est codé comme une liste blanche de caractères HTML sûrs. La liste blanche de caractères sûrs est codée dans le cadre de $sanitize, décrit ci-dessous. Les éléments suivants sont inclus dans la liste sûre (obtenue directement à partir du code source) :
Élément vide :
Les deux éléments suivants doivent être contournés car leur contenu n'est pas fiable. Dans ce cas, si vous souhaitez les afficher, vous devez utiliser le service $sce et appeler la méthode trustAsHtml d'Angular pour exécuter les éléments mentionnés ci-dessous.
下面这张图片展示了当在文本域中输入HTML代码,Angular用一种安全的方式插入到DOM时,是什么样子的. 注意 “img” 元素是上述列表中空元素的一份子. 因为代码被输入到了文本域中,作为”img"出现的图片被放到了受信任的列表(白名单)中。
信任并插入整段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元素也带上了红色, 如下所示. 在某些场景中,黑客可能会插入一段带有背景样式越苏,这可能会显示出原本不要被显示的背景,给最终用户带来糟糕的体验.
<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>