CVE-2020-8597 pppd stack buffer overflow in eap_response

2020-03-24 约 290 字 预计阅读 2 分钟

声明:本文 【CVE-2020-8597 pppd stack buffer overflow in eap_response】 由作者 shuozhang 于 2020-03-24 09:50:01 首发 先知社区 曾经 浏览数 287 次

感谢 shuozhang 的辛苦付出!

0x0 背景

pppd是一个通过串行接口连接的点对点协议(PPP)

github地址 :https://github.com/paulusmack/ppp

在ppp 2.4.2 - 2.4.8版本有一个栈溢出漏洞,我试着分析了整个过程

0x1复现整个过程

准备两台ubuntu的虚拟机(我用的virtualbox),设置启用串口功能。分别在两台虚拟机上git clone一份ppp,并回滚到有漏洞版本,编译安装。例如

git clone https://github.com/paulusmack/ppp.git
cd ppp
git checkout ppp-2.4.8
./configure
make
make install

开启服务端的md5认证(MD5-Challenge)

打开文件/etc/ppp/chap-secrets添加下面内容

admin   *       password        *

服务端启动pppd程序

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程序

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

下图我们发现程序没有崩溃,服务端打印出的username只有255个字节,我们输入的username255+5个字节,可惜这不是服务端对接收的内容进行的验证,这是在客户端限制了用户输入的用户名长度

0x2 漏洞分析

pppd进行MD5-Challenge的时候,通过eap_chap_response把密码hash、用户名和用户名长度一起发送到了服务端,用户名保存在一个256大小的栈变量中。

所以在我们上边的测试中,其实只发送了255长度的username到服务端。

6     typenum = id;
   5     MD5_Update(&mdContext, &typenum, 1);
   4     MD5_Update(&mdContext, (u_char *)secret, secret_len);
   3     BZERO(secret, sizeof (secret));
   2     MD5_Update(&mdContext, inp, vallen);
   1     MD5_Final(hash, &mdContext);
1454     ** eap_chap_response(esp, id, hash, esp->es_client.ea_name,
   1         esp->es_client.ea_namelen);
   2     break;
787    eap_authwithpeer(unit, user);
20 void
  19 eap_authwithpeer(unit, localname)
  18 int unit;
  17 char *localname;
  16 {
  15   eap_state *esp = &eap_states[unit];
  14
  13   /* Save the peer name we're given */
  12   esp->es_client.ea_name = localname;
  11   esp->es_client.ea_namelen = strlen(localname);
  10
   9   esp->es_client.ea_state = eapListen;
   8
   7   /*
   6    * Start a timer so that if the other end just goes
   5    * silent, we don't sit here waiting forever.
   4    */
   3   if (esp->es_client.ea_timeout > 0)
   2     TIMEOUT(eap_client_timeout, (void *)esp,
   1         esp->es_client.ea_timeout);
257  }
extern char user[MAXNAMELEN];/* Our name for authenticating ourselves */
extern char passwd[MAXSECRETLEN]; /* Password for PAP or CHAP */
#define MAXNAMELEN  256 /* max length of hostname or name for auth */

服务端接收的时候,vallen是已经处理的长度,len是接收的总长度,sizeof (rhostname)是username最大的长度和客户端一样256的数组,所以if判断手误了?

最后MD5-Challenge没处理好长度验证。当发送大于256长度的字符串时,发生益处。

if (vallen >= len + sizeof (rhostname)) {
          dbglog("EAP: trimming really long peer name down");
          BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1;
          rhostname[sizeof (rhostname) - 1] = '\0';
        } else {
          BCOPY(inp + vallen, rhostname, len - vallen);
          rhostname[len - vallen] = '\0';
        }

0x3 其他

想要触发服务端崩溃,可以像参考链接中的博主一样,直接修改eap_chap_response中的username送的内容。也可以像另一位博主一样,wireshark抓包,修改数据包中username内容,在写脚本发包到服务端,

0x4一半翻译一半补充的参考链接

https://gist.github.com/nstarke/551433bcc72ff95588e168a0bb666124

关键词:[‘安全技术’, ‘漏洞分析’]


author

旭达网络

旭达网络技术博客,曾记录各种技术问题,一贴搞定.
本文采用知识共享署名 4.0 国际许可协议进行许可。

We notice you're using an adblocker. If you like our webite please keep us running by whitelisting this site in your ad blocker. We’re serving quality, related ads only. Thank you!

I've whitelisted your website.

Not now