长亭百川云 - 文章详情

【37c3 番外】给 Netscape Navigator 2.0.2 始祖级 js 引擎找 bug

非尝咸鱼贩

67

2024-07-13

虽然现在除了收藏家和博物馆,已经很难找到还在运行对应软件的系统,不会产生实质影响。为避免破坏读者兴致,本文不会披露任何 bug 细节。

前情提要

在 ccc,参会人可以有“工位”,方便坐下来社交,甚至现场自行组织黑客马拉松。

我们这桌有大佬背了台上世纪 90 年代的 Macintosh Quadra 605——如果我没有认错型号的话。

除了键盘掉了个键,没看出哪不能用的。而中学那台陪我学 Visual Badic 6.0(精简版) 的 XP 台式机早几年就彻底趴窝了,点都点不亮。果然便宜没好货?

不小心拍到了 PoC,马赛克一下

这台 Macintosh 安装了 1996 年发布的  Netscape Navigator 2.0.2,距离史上第一个搭载 Javascript 的 2.0 beta 仅仅过去几个月,可谓是始祖级的 js 引擎。

Javascript 从一开始的网页动效语言,到现在已经从服务端到桌面端甚至物联网上,几乎无所不能。现在的 js 无论是功能还是速度,和最初诞生时的样子都不可同日而语。

现代浏览器早已不仅是一个渲染 html 的工具,其丰富的交互能力几乎约等于一个微型操作系统。例如早在 2011 年发布的 jslinux 就可以直接在浏览器里运行了一个名副其实的系统模拟器。

由于应用广泛,js 引擎的安全性是一个被业界深入研究多年的话题。

不如坐上时光机器,看看 js 刚诞生时的 bug?


ctf 越来越卷了,前几年就发展到直接丢一个 v8 的 diff 就考察写利用。也有反其道而行之挖坟的,Plaid CTF 2020 曾经用 Netscape 0.96 Beta 出过一道题 Back to the Future。

这题程序的格式还是 a.out,只能找一个版本足够老的 Linux 发行版才能运行。详情可以分别阅读 A-0-E 和 Dragon Sector 战队写的题解,没看错的话两个队打了同一个解析 HTTP 协议时产生的栈溢出:

这个 Netscape 版本大约发布于 1994 年,而著名的文章 Smashing The Stack For Fun And Profit 还要再等两年才出来。这个时候 text 段还是 rwx(可读可写可执行)的,可以用 ROP 把自定义的代码覆盖上去然后再跳转到 shellcode 即可。


Back to the future 用的软件环境虽然老,总归还是 Intel 的指令集。

回到这台 Macintosh。它用的 cpu 是摩托罗拉的 MC68020,确实触及到笔者知识盲区了。这是一款 CISC 指令集的 32 位 CPU,有 8 个数据寄存器和 7 个地址寄存器,和一个是栈寄存器。

以下是我在互联网上挖坟找到的指令集参考文档:

后面用到调试器的时候,能大致从助记符上猜到指令的作用,但是要调试直接两眼一抹黑。

在编辑这篇文章的时候我已经回来了,所以摸不到这台真机。那么上哪里去搞一台古董电脑呢?

前面提到 jslinux 可以直接在网页里模拟 x86 的 Linux。老的麦金塔有模拟器版吗?还真有个网页版的 Infinite Mac:

地址 infinitemac.org

虚拟的系统已经预装好了网景 2.0.2,直接双击运行,然后同意用户许可协议即可。

这个网页版的虚拟机似乎没有模拟网络栈,所以无法访问任何在线的网站。但是可以用 SimpleText 编辑器,编辑保存好 html 文件后,拖到浏览器查看。

顺便说一句,jslinux 网站上有个 Windows 2000 的模拟器,用 WebSocket 代理模拟转发了网络请求。所以在上面真的可以 ping 甚至上网冲浪……

据说 JavaScript 之父 Brendan Eich 在 34 岁时花了 10 天,就实现了这门对互联网发展至关重要的编程语言的第一个雏形。好险,再晚几个月就 35 岁了。

我们玩的环境并不是真正的初代 js,而是稍晚几个月的。

在 archive.org 上可以找到来自 1997 年的文档:

https://web.archive.org/web/19970613234917/http://home.netscape.com:80/eng/mozilla/2.0/handbook/javascript/index.html

这个早期版本的 JavaScript 已经有了相当多目前常用的函数,例如 Math 对象、Date 类等。居然还有 setTimeout,做字符小动画都够了。

在看到有 eval 的时候我还在想能不能解析 JSON。结果这个版本还没有开始支持对象字面量,{} 和 [] 语法都报错。穿越失败。

另外今天绝大多数数组的方法(包括 push 和排序)都不存在,就更别想在上面找 bug 了。

Mozilla 放出过 Netscape 的源码,但这个版本比 2.0 已经高出不少。(具体是几有没有大佬知道的?)

这里有人在 GitHub 上保存了一个镜像,虽然不是官方的地址:

https://github.com/jrmuizel/mozilla-cvs-history/tree/781c48087175615674b38b31fcc0aae17f0651b6/js/src

经过一番手工测试,还真找到了几个可以崩溃的 bug。

这台真机上安装了 MacsBug,崩掉之后直接进入调试器界面。

可以看到当年的 JavaScript 引擎模块名叫 mocha,和 js 的正史对上了。似乎符号被 strip 掉了,加上目前大多数人都没学过摩托罗拉的这个指令集,就难搞。

由于 MacsBug 调试器的安装过程要求复制到系统文件夹并重启。网页版的 Infinite Mac 只模拟了一个外部存储设备 Saved HD,此外其他任何分区的文件系统改动都像 ramdisk 一样不会持久化,点“关机”或者刷新网页就没了。

这个网页版模拟器是开源的:

https://github.com/mihaip/infinite-mac

实际上是这个项目 Basilisk II,移植到 wasm 上:

https://basilisk.cebix.net/

我暂时还没有研究 Basilisk II 怎么用,以及对持久化的支持会不会更好一些。

总之,网页版的模拟器暂时没搞定调试。一旦产生未被映射的无效地址访问,就会像这样:

所以调试是个大问题。

不过在 ccc 期间,还是有人现场搞出了任意地址读写:

不过还没到弹计算器的一步。

当年的系统不像现在有一堆东西要绕过。这个 cpu 只有两个特权级别,supervisor 和 user。大佬说这个系统是直接以 supervisor 模式运行的,就是只要能在浏览器执行代码,就是最高权限了(这个说法没找到参考来源,暂时无法求证)。

可是 1996 年的 bug,弹了计算器又能怎么样呢?还不如跟老师去学 electdon

(不是,一个烂梗还玩到 2024 年)

参考资料

  1. PlaidCTF 2020 Writeup (A*0*E)
    https://github.com/A-0-E/writeups/blob/master/plaidctf-2020/README.md#back-to-the-future

  2. PlaidCTF 2020: Back to the Future
    https://blog.dragonsector.pl/2020/04/plaidctf-2020-back-to-future.html

  3. Infinite Mac
    https://infinitemac.org/1996/System%207.5.3

  4. Javascript 2.0 Reference (archive.org)
    https://web.archive.org/web/19970709154140/http://home.netscape.com/eng/mozilla/2.0/handbook/javascript/index.html

  5. Motorola 68000 - Wikipedia
    https://en.wikipedia.org/wiki/Motorola\_68000

  6. Debugging Macintosh Software With MacSbug
    https://vintageapple.org/macbooks/pdf/Debugging\_Macintosh\_Software\_with\_MacsBug\_1991.pdf
    https://archive.org/details/mac\_Debugging\_Macintosh\_Software\_with\_MacsBug\_1991

  7. Simon’s Computing stuff - Using MacsBug
    https://smfr.org/computing/archaic/macsbug.html

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2