XSS : $sce.trustAsHtml 执行 <img> 'onerror' js代码

XSS : $sce.trustAsHtml executes <img> 'onerror' js code

我正在尝试使用 ng-bind-html 和 $sce.trustAsHtml 来阻止不安全内容的执行。

但是如果我把一些js放在标签里面(例如onerror="alert(123)" ), 正在执行不安全的内容。

var app = angular.module('app', []);

app.controller('test', function($scope, $sce, $timeout) {
  $scope.text = $sce.trustAsHtml('<ul><b>onLoad<img src=x onload="alert(\'onload\')"/></b></ul>'+'<ul><b>onError<img src=x onerror="alert(\'onerror\')"/></b><ul>'+'<ul><b>onClick<img src=x onclick="alert(\'onclick\')"/></b></ul>');
});
<script src="https://code.angularjs.org/1.7.4/angular.min.js"></script>
<div ng-app="app" ng-controller="test">
  Run time binding of HTML
  <div ng-bind-html="text"></div>
</div>

请问有没有人建议如何防止这里js代码的执行?

编辑

根据@Quentin 的建议[和,我删除了 trustAsHtml 调用并允许清理,仍然是 ng-bind-html 指令在 $watch 中调用 trustAsHtml 并出现错误。

var app = angular.module('app', []);

app.controller('test', function($scope) {
  $scope.text = '<ul><b>onLoad<img src=x onload="alert(\'onload\')"/></b></ul>'+'<ul><b>onError<img src=x onerror="alert(\'onerror\')"/></b><ul>'+'<ul><b>onClick<img src=x onclick="alert(\'onclick\')"/></b></ul>';
});
<script src="https://code.angularjs.org/1.7.4/angular.min.js"></script>
<div ng-app="app" ng-controller="test">
  Run time binding of HTML
  <div ng-bind-html="text"></div>
</div>

var ngBindHtmlDirective = ['$sce', '$parse', '$compile', function($sce, $parse, $compile) {
  return {
    restrict: 'A',
    compile: function ngBindHtmlCompile(tElement, tAttrs) {
      var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml);
      var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function sceValueOf(val) {
        // Unwrap the value to compare the actual inner safe value, not the wrapper object.
        return $sce.valueOf(val);
      });
      $compile.$$addBindingClass(tElement);

      return function ngBindHtmlLink(scope, element, attr) {
        $compile.$$addBindingInfo(element, attr.ngBindHtml);

        scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() {
          // The watched value is the unwrapped value. To avoid re-escaping, use the direct getter.
          var value = ngBindHtmlGetter(scope);
          element.html($sce.getTrustedHtml(value) || '');
        });
      };
    }
  };
}];

抛出以下错误

Error: [$sce:unsafe] Attempting to use an unsafe value in a safe context.
https://errors.angularjs.org/1.7.3/$sce/unsafe
    at angular.js:138
    at htmlSanitizer (angular.js:20119)
    at getTrusted (angular.js:20320)
    at Object.sce.(:8080/lia/anonymous function) [as getTrustedHtml] (http://localhost:9000/js/angularjs/lib/angular/angular.js:21040:16)
    at ngBindHtmlWatchAction (angular.js:27610)
    at Scope.$digest (angular.js:19102)
    at Scope.$apply (angular.js:19462)
    at bootstrapApply (angular.js:1944)
    at Object.invoke (angular.js:5121)
    at doBootstrap (angular.js:1942)

我正在使用 angular v1.7.4。 你能帮我一下吗?

查看 documentation:

You may also bypass sanitization for values you know are safe. To do so, bind to an explicitly trusted value via $sce.trustAsHtml.

trustAsHtml 与您想要的 完全相反。不要在这里使用它。