Alpine Linux 之漏洞利用(二):软件包管理器漏洞分析 - 嘶吼 RoarTalk – 网络安全行业综合服务平台,4hou.com

Alpine Linux 之漏洞利用(二):软件包管理器漏洞分析

luochicun 漏洞 2017-07-19 09:04:47
314766
收藏

导语:在Alpine Linux 漏洞利用的第一部分《Alpine Linux:从漏洞发现到代码执行》,我对Alpine Linux的软件包管理器中的两个关键漏洞, CVE-2017-9669和CVE-2017-9671做了深入的分析。

1500366177576938.jpg

在Alpine Linux 漏洞利用的第一部分《Alpine Linux:从漏洞发现到代码执行》,我对Alpine Linux的软件包管理器中的两个关键漏洞, CVE-2017-9669和CVE-2017-9671做了深入的分析。

今天这部分,我会对这两个漏洞的发现过程进行详细描述,并演示如何实现远程执行代码。

第一步是把部署环境中导致 漏洞的所有内容都进行复制,由于这是一个可用性测试(sanity check),所以必须首先做,只有完成这一步才能尝试进行复杂的有效载荷。我的fuzzer的 漏洞文件直接从apk_tar_parse中的文件处理程序中读取,但是在实际情况下,文件将从tar.gz服务器读取。

为了模仿一个中间人攻击的场景,我使用了Docker的主机功能,以便对要添加到映像的主机文件的映射进行自定义。另外,我还启动了一个nginx映像,以从本地目录(使用-v)来服务我的文件。

我从fuzzer的 漏洞目录中压缩了 漏洞的tar,并将其放在服务目录中:

cat crash | gzip -9 > ~/docker/files/alpine/v3.6/main/x86_64/APKINDEX.tar.gz

运行的映像:

docker run -ti --add-host dl-cdn.alpinelinux.org:172.17.0.2 alpine:3.6

执行“apk更新”后,我收到一个细分化的漏洞。这意味着漏洞是可重复的,现在是时候调试执行,并讨论如何利用漏洞。

我写了一个小Dockerfile,它下载命令间的依赖关系,并从源代码编译apk-tools包。我添加了CFLAGS -g和-O0标志以包括所有调试符号,让调试变得更简单。我从这个Docker文件构建了一个映像,并使用-privileged运行,以允许gdb禁用ASLR。

我运行了“gdb --args apk update”,并得到了预期的segfault。 gdb在 free()上的漏洞,这意味着这可能是一个堆溢出,并且在一个简短的调试会话后,我发现了第一次调用blob_realloc的漏洞,在此,我建议你查看源文件archive.c

我制作了一个简单的文件,通过拥有一个negative size(32位有符号整型范围内的-1 或0o77777777777)的块文件( block file)来触发漏洞:

1.png

我压缩了文件,并在服务器中运行了apk文件。此时,当复制entry.name缓冲区的空终止字符串时会产生漏洞,这是因为entry.name没有分配,所以它指向null。同时entry.size是0xffffffffffffffff,即未映射的地址,意味着任何复制的尝试都会导致segfault:

2.png

译者注:代码中的一个问题是entry.size被隐式转换为64位, get_octal函数返回一个int,但entry.size的类型为off_t

我制作了另一个文件,这个文件有两个tar块,一个是正确地分配一个大小为I的缓冲区,另一个文件则利用分配的缓冲区来使用漏洞。

我调试了漏洞执行(而不是对blob_realloc的调用),并按预期缓冲区被首先分配,然后在第二个块的解析过程中被用作复制目标。不过要注意的是,要使发现变得更容易,应该调用gzip_read(来自is-> read),它会将块从源流复制到目标流,一旦源流用完就停止,所以它只会复制一样数据。

了解和利用堆

现在,我就有了一个缓冲区溢出,并控制大小和内容。虽然,理论上,可能有许多方法来实现代码执行,但事实上,在经过大量验证后,其中大多数集中在glibc。

然而,Alpine使用的是musl libc而不是glibc。这无疑有不同的方式来利用它,在此,我不再赘述。由于我的目标只是为了提供POC来实现远程执行,所以本文,我只会尝试一些更简单的办法。

如果我可以在堆上找到任何有用的东西,就会进行覆盖来操纵执行流程。例如,我可以覆盖一个检查签名的标志,然后安装一个我想要的包,或者更改一些要安装的包的数据等。

通过调用像execv或者系统这样的方法来实现代码执行是最简单的方法和最快的方式。但是由于溢出会破坏堆栈,所以我需要重新构建它,或者在内存管理器使用覆盖内存之前调用回调函数(大概就是在调用free() 发生的那个时候)。

我继续检查代码,尝试在堆中找到任何可能在内存中的前一个entry.name的变量。调试一段时间后,我想我实际上可以覆盖的是struct,它用于调用写入流(writes to the stream)的函数。它的类型是apk_istream:

struct apk_istream {
void (*get_meta)(void *stream, struct apk_file_meta *meta);
ssize_t (*read)(void *stream, void *ptr, size_t size);
void (*close)(void *stream);
};

理论上我将覆盖那些到我的目标函数中进行读取的函数,然后找到要覆盖的内容来控制调用的参数。

通过把一个断点放在调用读取,可以计算出我的缓冲区之间的delta是is架构:

3.png

我填写了我精心设计的tar文件0x153a0,它对应16个零字节,以覆盖get_meta,并使用零读取函数指针(每个函数指针是8个字节),这些程序漏洞会在0x0000000000000000处发生。

现在是尝试调用我的目标函数的时候了,为了简单起见,我决定使用一个字符串作为参数,并将其作为shell命令执行。它的地址是0x7ffff7db0956。对于参数,似乎is->read的调用本身就是第一个参数。只要get_meta函数从不被调用,我就可以用我的shell字符串覆盖前8个字节。

我的tar文件的结尾看起来像这样:

4.png

前8个字节是我的shell字符串,后面是系统地址的8个字节,执行情况正如预期一样:

5.png

不过这个有效载荷长度被限制在8个字节,在8字节内,这个解决方案似乎是有效的。但是有时会出现意外的问题,由于is-> read调用以块形式写入,所以可能会有一种情况,即它只写入指针的一部分(只有4个字节),然后继续调用该指针来读取更多的数据,这是我在第一次构建这个POC时遇到的一个问题。

所以为了继续寻找另一个可以覆盖的结构,我恢复了文件最初指针的is架构,并添加了8字节的数据,现在看看我是否得到另一个漏洞(我添加的数据是在0xAA字节之后):

6.png

看来我能用我的数据覆盖gis-> bs指针,你可以检查gunzip.c以准群理解这个bs指针是什么(请参阅struct apk_gzip_istream)。 bs是apk_bstream:

struct apk_bstream {
unsigned int flags;
void (*get_meta)(void *stream, struct apk_file_meta *meta);
apk_blob_t (*read)(void *stream, apk_blob_t token);
void (*close)(void *stream, size_t *size);
};

它虽然以相同的方式使用(也将其自身作为第一个参数),但它给出了另外8个字节(标志)用于shell字符串。现在可以通过将指针覆盖到堆上的某个位置来运行代码。

为方便起见,我把地址放在32字节之前。该地址将为0x5555559682a0(is-0x20)。如上所述,它的前16个字节将由我的shell字符串。之后,我会把系统的地址覆盖到读取地址。

有效载荷看起来像这样:

7.png

红色代表gis-> bs-> flags和gis-> bs-> get_meta,用shell字符串覆盖。

黄色代表gis->bs->read,用系统地址覆盖。

其余的颜色代表  gis->bs->close ,然后是 - > get_meta,这是无关紧要的,因为is函数就是最初的地址。

8.png

总结

通过覆盖堆上的结构体的函数指针,我能够在目标设备上执行代码。我本文的例子中运行echo,但有效载荷可以是任何东西,例如,打开一个带有netcat的远程shell。

值得注意的是,为了找到这个漏洞,我假设攻击者知道执行程序的内存布局。所以作为复制我的漏洞利用的先决条件,ASLR必须被禁止执行(除非你在apk中发现了内存漏洞)。 Gdb会默认情况下执行此操作,因此在运行时不需要手动禁用ASLR。

  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论

 
本站4hou.com,所使用的字体和图片文字等素材部分来源于原作者或互联网共享平台。如使用任何字体和图片文字有侵犯其版权所有方的,嘶吼将配合联系原作者核实,并做出删除处理。
©2024 北京嘶吼文化传媒有限公司 京ICP备16063439号-1 本站由 提供云计算服务