我有一个翻译密钥,它实际上是一个HTML代码,既编码又未编码。
$scope.translations = {
"html_code" : "<script>alert('Alert!');</script>",
"html_code_full" : "<script>alert('Alert!');</script>",
"greeting" : "Welcome!"
}
当我使用这些值在视图中显示翻译的文本时,我使用两种方法:
- 作为指令
<span translate>{{translations.html_code}}</span>
- 作为过滤器
{{translations.html_code|translate}}
我尝试对translations.html_code_full
做同样的事情.下面是用于查看的代码:
translations.html_code = {{translations.html_code|translate}}
translations.html_code = <span translate>{{translations.html_code}}</span>
translations.html_code_full = {{translations.html_code_full|translate}}
translations.html_code_full = <span translate>{{translations.html_code_full}}</span>
这是我得到的输出:
translations.html_code = <script>alert('Alert!');</script>
translations.html_code = <script>alert('Alert!');</script>
translations.html_code_full = <script>alert('Alert!');</script>
translations.html_code_full =
很明显,指令实现将翻译密钥编码为 HTML,但过滤器不是。为什么指令与过滤器实现之间的输出存在这种差异?如果它正在渲染 HTML,为什么我没有收到警报?
这是我为演示创建的 plunk。
AngularJS框架工作正在保护您的应用程序免受XSS攻击。
截至 2007 年,在网站上执行的跨站点脚本约占赛门铁克记录的所有安全漏洞的 84%。
-- 维基百科 - 跨站点脚本
那你到底想做什么?也许我们可以向您展示如何以安全的方式做到这一点。
对我来说,翻译库并没有涵盖所有实例。所以我需要涵盖一个普通的脚本攻击和一个 Angular 瞄准的攻击。 我们将 URL 的一部分读取为密钥,然后将其显示为一条消息,以便在 URL 中受到攻击。
我测试的 2 个 URL:
/mypage.html#/{{{}.")));alert(1)//";}}
mypage.html#/%3Cscript%3Ealert('foo')%20%3C/script%3E
对我来说,如果在页面中使用翻译指令而不是过滤器,第一个将被正确转义。第二个是在页面中使用指令时成功的攻击,但在使用过滤器时被正确转义。
最后,在将值分配给 scope 变量之前,我逃脱、翻译并检查了控制器。所以现在页面中没有翻译指令或过滤器。
function translateParam(paramData, defaultKey){
var deferred = $q.defer();
var trusted = $sce.trustAsHtml(paramData);
$translate(trusted).then(
function(translatedString){
if(translatedString == trusted){
//no key has been found so show a default
deferred.resolve($translate.instant(defaultKey));
}
else{
//the key has been found correclty
deferred.resolve(translatedString);
}
}
);
return deferred.promise;
}
//called like this
$scope.error = translateParam('keyFromURL','defaultKeyInTranslateFile');
您需要注射$q,$sce和$translate。 对我来说,这是最安全可靠的解决方案。