以安全的视角浅谈新生代专为AI设计的语言Mojo
基本类型List
基本类型的定义都可以在官方stblib[3]中找到。这里重点介绍一下List,它对标Python中的List。它的基本定义为
即struct的字段分布是顺序的。值得注意是List的操作中并没有越界检测以及释放后将data pointer置NULL,已经用户反应了的此类问题[4]. 官方打算支持但是目前还没有时间。这一点是非常震惊我的,这意味OOB和UAF在Mojo是很容易做的
基本类型List
基本类型的定义都可以在官方stblib[3]中找到。这里重点介绍一下List,它对标Python中的List。它的基本定义为
即struct的字段分布是顺序的。值得注意是List的操作中并没有越界检测以及释放后将data pointer置NULL,已经用户反应了的此类问题[4]. 官方打算支持但是目前还没有时间。这一点是非常震惊我的,这意味OOB和UAF在Mojo是很容易做的
通过 DOM Clobbering 劫持 Service Worker
该importScripts()函数是此漏洞的核心 - 它允许 SW 从不同的域检索 JavaScript。在下面的示例中,攻击者可以控制主机查询参数,从而完全控制导入的脚本,从而完全控制网站响应。
为了利用这些类型的漏洞,您需要两个组件:
一——控制传递给 SW 的查询字符串参数。
二 - importScripts()SW 内部的函数调用可能会受到查询字符串参数的影响。
该importScripts()函数是此漏洞的核心 - 它允许 SW 从不同的域检索 JavaScript。在下面的示例中,攻击者可以控制主机查询参数,从而完全控制导入的脚本,从而完全控制网站响应。
为了利用这些类型的漏洞,您需要两个组件:
一——控制传递给 SW 的查询字符串参数。
二 - importScripts()SW 内部的函数调用可能会受到查询字符串参数的影响。
CVE-2023-3824: 幸运的Off-by-one (two?)
这个函数用于phar://协议下读取文件夹中的内容. 这段代码出现的一些问题:
后面的memset已经假设了buf的大小是sizeof(php_stream_dirent). 因此函数开头理因有一个关于它的检查, 却没有看见. 然而这个问题在这里其实不大, 因为在PHP中所有引用这个函数的地方, 传入的count和sizeof(php_stream_dirent) 都是保持一致的. 当然这样的做法依然是不对的, 因为需要考虑PHP第三方库对其的使用规范.
注意这里我们只考虑Linux的下利用情况, 全篇亦是如此. 在Linux下sizeof(php_stream_dirent)为4096. 当文件夹中存在一个文件名长度为4096的文件时, 在第13行这里即有to_read == 4096, 从而第14行这里的判断顺利通过了 (i.e., count == ZSTR_LEN(str_key) == 4096). 考虑第21行这里的结尾NULL字符写入, 我们知道传入的buffer大小为4096, 再往后写就肯定overflow了. 有趣是它写NULL的位置也错了, 应该在d_name[to_read]写NULL, 而不是to_read + 1. 这样就给我们带来在buf + 4097处写零的机会.
这个函数用于phar://协议下读取文件夹中的内容. 这段代码出现的一些问题:
后面的memset已经假设了buf的大小是sizeof(php_stream_dirent). 因此函数开头理因有一个关于它的检查, 却没有看见. 然而这个问题在这里其实不大, 因为在PHP中所有引用这个函数的地方, 传入的count和sizeof(php_stream_dirent) 都是保持一致的. 当然这样的做法依然是不对的, 因为需要考虑PHP第三方库对其的使用规范.
注意这里我们只考虑Linux的下利用情况, 全篇亦是如此. 在Linux下sizeof(php_stream_dirent)为4096. 当文件夹中存在一个文件名长度为4096的文件时, 在第13行这里即有to_read == 4096, 从而第14行这里的判断顺利通过了 (i.e., count == ZSTR_LEN(str_key) == 4096). 考虑第21行这里的结尾NULL字符写入, 我们知道传入的buffer大小为4096, 再往后写就肯定overflow了. 有趣是它写NULL的位置也错了, 应该在d_name[to_read]写NULL, 而不是to_read + 1. 这样就给我们带来在buf + 4097处写零的机会.
供应商信息大部分情况下作为标识信息作用,但是后续的文章中会发现有些驱动靠识别指定的供应商和产品ID来触发。目前只是模拟鼠标/键盘设备,它们不依靠这些ID触发,所以可以随意修改
在接口描述符中,字段的含义如下所示:
bNumEndpoints定义了设备端点的数量,在USB协议中,端点的通信是单向的,在这里定义了两个端点描述符,一个表示的是输入,一个表示的是输出。
bInterfaceClass定义了接口的类型,在上图中定义的是一个HID设备,所以主机会再去读取HID描述符。
bInterfaceProtocol定义了接口协议为键盘,这样就会让键盘的HID驱动来处理后续通信
bNumEndpoints定义了设备端点的数量,在USB协议中,端点的通信是单向的,在这里定义了两个端点描述符,一个表示的是输入,一个表示的是输出。
bInterfaceClass定义了接口的类型,在上图中定义的是一个HID设备,所以主机会再去读取HID描述符。
bInterfaceProtocol定义了接口协议为键盘,这样就会让键盘的HID驱动来处理后续通信
你好 Lucee!让我们再次破解苹果?
尝试 1——请求处理和 REST 映射
在我们之前的研究中检查了 Lucee 的管理面板后,我们发现它非常封闭。未经身份验证的情况下,您只能访问四个 CFM 文件,因此在那里没有太多空间可以找到错误。我们需要深入研究 Lucee 如何处理请求。我们正在寻找特定的路径、参数、标头等,以了解如何处理请求。
在查看了 web.xml 文件后,我们通过 IntelliJ 设置了 JVM 调试器并添加了 Lucee 的源代码。我们计划通过在 Request::exe() 处设置断点来开始检查代码。这样,我们可以一点一点地检查代码,看看 Lucee 如何处理请求
尝试 1——请求处理和 REST 映射
在我们之前的研究中检查了 Lucee 的管理面板后,我们发现它非常封闭。未经身份验证的情况下,您只能访问四个 CFM 文件,因此在那里没有太多空间可以找到错误。我们需要深入研究 Lucee 如何处理请求。我们正在寻找特定的路径、参数、标头等,以了解如何处理请求。
在查看了 web.xml 文件后,我们通过 IntelliJ 设置了 JVM 调试器并添加了 Lucee 的源代码。我们计划通过在 Request::exe() 处设置断点来开始检查代码。这样,我们可以一点一点地检查代码,看看 Lucee 如何处理请求