CVE-2020-7248 OpenWRT libubox标记二进制数据序列化漏洞(更新中)

提要

        该文档会一直处于更新当中,当状态为完毕后,才是更新完成。由于网络上关于该漏洞原理的分析文档和资源实在是太少,而本人关于该方向也才是刚入门,能力有限,所以复现需要的时间较长,需要补充和学习的东西较多,若大家有什么建议,欢迎评论区一起讨论进步。

漏洞简介

        OpenWrt是一套针对嵌入式设备的Linux操作系统,libubox是其中的一个提供事件循环、二进制格式处理、Linux链表实现和JSON辅助处理的基础库。

        该漏洞与标记的二进制数据的JSON转换部分(blob)有关。Blob属性有足够大的double类型数值,由blobmsg_format_json处理,会溢出为堆栈上分配的JSON输出指定的缓冲区数组。攻击者可以向blobmsg_format_json提供特制的二进制blob或JSON输入,从而在double值序列到JSON缓冲区时造成堆栈溢出。

        libubox库是OpenWrt项目的核心组件,并在项目的其他部分使用。通过在项目的LXR[1]中查找上述易受攻击的blobmsg_format_json函数,可以看到这些相互依赖关系,该函数揭示了netifd、procd、ubus、rpcd、uhttpd中的引用。也就是说,依赖调用到blobmsg_format_json的有很多其它的部分,我们本次复现主要针对rpcd对这个漏洞的利用。

        简单介绍一下rpcb

参考:

[OpenWrt Wiki] Security Advisory 2020-01-31-2 - libubox tagged binary data JSON serialization vulnerability (CVE-2020-7248)

论文:A Grounded Theory Based Approach to Characterize So! ware" Attack Surfaces

受影响的漏洞版本:

        OpenWrt 18.06.0 - 18.06.6

        OpenWrt 19.07.0-rc1 - 19.07.0

漏洞原理分析

        本次我们选取的漏洞分析环境的版本是Openwrt18.06.5,具体的漏洞的源代码等内容我们在另一篇博客,关于CVE-2020-7982的漏洞复现中,已经提到了代码的位置,如下地址参考:

CVE-2020-7982 OpenWrt 远程命令执行漏洞学习(完结)_openwrt 漏洞-CSDN博客

本次实验要分析的源代码的参考地址如下,后续我们不再赘述

https://git.openwrt.org/?p=project/libubox.git;a=blob;f=blobmsg_json.c;h=ec8b482c30c96a355aca58651632bc509a16bedf;hb=HEAD

根据漏洞的介绍,我们需要先找到libubox的源代码

该项目的地址如下

https://git.openwrt.org/?a=project_list;pf=project

之后我们在blobmsg_json.h中可以找到我们想要的函数blobmsg_format_json

根据函数的内容声明,其会先调用blobmsg_format_json_with_cb这个函数,我们可以在blobmsg_json.c文件中找到这个函数

首先定义了一个strbuf的结构体s,并且初始化内容为0。strbuf 结构体通常用于在C语言中表示可变长度的字符串缓冲区。它通常包含有关缓冲区内容和大小的信息,以便可以方便地进行字符串操作。

一般而言,strbuf 结构体可能包含以下成员:

  • char *buf:指向存储字符串数据的内存缓冲区的指针。
  • size_t len:当前字符串的长度。
  • size_t alloc:分配给缓冲区的内存空间大小。

之后其调用函数setup_strbuf 具体如下图

我们首先先找到blob_attr这个数据结构的结构样式,我们可以找到blob.h这个文件,我们在其中可以看到blob_attr这个结构,如下图所示

其中uint32_t是一个32位,也就是4字节的数据类型,而data是一个可变长度的数据类型,所以一般来说,原始的blob_attr结构的长度应该是32位。

那么首先setup_strbuf函数会调用blob_len函数来进行处理,我们同样可以在blob.h文件中找到函数blob_len,如下图

我们可以根据最开始的引用,

在文件utils.h中找到函数be32_to_cpu的结构,最终我们发现了两个

总的来说,其作用就是定义了一个内联函数 blob_len,用于计算属性的有效载荷长度。通过 be32_to_cpu 宏将 attr->id_len 中的大端字节序转换为CPU本地字节序。CPU本地字节序则表示CPU处理器默认采用的字节序方式。因为不同的CPU架构可能采用不同的字节序,所以需要在不同字节序之间进行转换,以确保数据在不同平台上的正确解释和处理。这具体可以参考计组相关的知识。然后使用按位与操作符和 BLOB_ATTR_LEN_MASK 来提取有效载荷长度,并减去 struct blob_attr 的大小。其中我们在blob.h中看到了

        这样一个定义,BLOB_ATTR_ID_MASK被定义为了0x7f000000,其二进制的形式是1111111000000000000000000000000,根据按位与的运算逻辑,本质就是把有效载荷数据的前7位进行按位与操作,而后续多出来的字节数据都会被置为0,最终其有效长度也是8x4bit=32bit,也就是4B的长度大小。

        最终我们获得了attr的长度,将其赋值给s的len这样一个成员变量。

和其相关的漏洞原理我们也参考了论文中的一些内容

我们在数据包auc.c中可以看到如下的代码:

这段代码是一段 C 语言代码,看起来是基于 libubox 库进行的一些操作。根据代码的上下文,它似乎是在处理 HTTP 请求和响应的元数据信息。第 679 行通过调用 DPRINTF 函数打印出了一个变量 cl 的 status_code 值。第 680 行通过调用 blobmsg_format_json_indent 函数将 cl->meta 中的头部信息格式化为 JSON 并打印出来。第 681 行使用 blobmsg_parse 函数解析了 cl->meta 中的头部信息,并将解析结果存储在 tb 变量中。

我们可以结合libuboxblobmsg_json.h的具体内容来判断。

这个函数blobmsg_format_json_with_cb我们前面已经提到了,所以这里不赘述其内容。

这里除了用到了这个函数,过程中还会用到blobmsg_puts函数

其中对于第147行代码而言,这行代码使用了C语言中的memcpy函数,其目的是将内存区域c的前len个字节复制到s->buf + s->pos所指向的内存区域中。在这里,s是一个结构体或者对象,buf和pos可能是该结构体中的成员变量,用来表示缓冲区和偏移量。那么漏洞就在这里,我们可以构造特殊的JSON数据传入,使其在将double数据序列化到JSON缓冲区的时候,导致缓冲区的溢出

漏洞环境搭建

漏洞复现

payload

$ ubus call luci getFeatures '{ "banik": 00192200197600198000198100200400.1922 }'

漏洞修复

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Simon_Smith

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值