- 发现漏洞及背景:去年@swapgs和作者在流行的企业 VPN 解决方案Zscaler中发现一个有趣的漏洞。VPN 客户端使用pacparser库根据预配置的Proxy Auto-Configuration (PAC)文件决定哪些 HTTP 请求应被代理,该漏洞允许从字符串中逃逸并在 PAC 文件的上下文中执行任意 JavaScript。当时发现漏洞时未开发完整的利用程序,只是报告了该漏洞。
SpiderMonkey 漏洞:
- Bug 描述:在 Mozilla 错误跟踪器中找到适合的 SpiderMonkey 漏洞,如 398085 号 Bug,函数中大型 switch 语句存在问题,会导致字节码生成错误,使攻击者可让引擎执行任意字节码,存在安全隐患。当函数总字节码过长时,跳转会出错,可利用此 misaligned jump 执行任意字节码,但限于 3 字节,可通过巧妙选择
IFEQ或IFNE来跳过不必要的字节码。 - 内存损坏:任意字节码执行虽酷,但要做有意义的事需损坏内存,
POP/POP2指令可用于此目的,它们会递减 VM 的堆栈指针且不检查是否下溢堆栈,通过链式POP2可使堆栈指针指向&fp->argv,然后可使用GETARG和SETARG指令读取和写入fp->argv,但会导致堆栈帧损坏使 VM 崩溃,作者改为调用回调函数。 - 构建
addrof原语:在该 SpiderMonkey 版本中,JavaScript 值有多种类型且有类型特定掩码,可通过将指针写入未移除标签的双指针来实现addrof原语,在 JavaScript 世界中读取双精度数并手动转换为字节表示可获取原始指针。 - 泄露有趣信息:通过读取函数指针可泄露二进制在内存中的基地址,利用
addrof原语可读取全局偏移表 (GOT) 条目获取libc基地址,进而获取system()函数地址。 - 获取 Shell:可通过覆盖和调用函数指针来劫持控制流,
JS对象的ops指针是好的候选,但要注意调用参数,幸运的是二进制运行时的上下文对象存储在.bss部分,可通过泄露对象地址并写入控制ops函数的第一个参数来获取 Shell,例如将getProperty()函数指针覆盖为system()并写入"sh\x00"。
- Bug 描述:在 Mozilla 错误跟踪器中找到适合的 SpiderMonkey 漏洞,如 398085 号 Bug,函数中大型 switch 语句存在问题,会导致字节码生成错误,使攻击者可让引擎执行任意字节码,存在安全隐患。当函数总字节码过长时,跳转会出错,可利用此 misaligned jump 执行任意字节码,但限于 3 字节,可通过巧妙选择
- 最终利用程序:提供了
exploit.py和exploit.js文件,exploit.py用于设置相关地址和读取漏洞利用脚本exploit.js,exploit.js中定义了一系列用于处理 IEEE-754 浮点数和字节操作的函数,通过一系列函数调用和字节码操作来实现泄露地址、获取libc地址和获取 Shell 的功能。整个利用过程花费约一周时间,作者认为如果重新创建挑战应提供漏洞票作为提示,使挑战更易接近。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。