PPP协议漏洞分析
PPP协议的漏洞分析
前言
PPP 协议,全称 Point-to-Point Protocol(点对点协议),是一种工作在 数据链路层(OSI 第二层) 的通信协议,专门用于在两台节点设备之间建立直连链路,以便安全、可靠地传输多种网络层协议(如 IP、IPX、AppleTalk 等)。
🧩 一句话定义:
PPP 是一种用于串行链路的标准封装协议,能提供链路建立、认证、压缩、错误检测和多协议封装能力。
🔧 PPP 的主要功能包括:
功能 | 说明 |
---|---|
多协议支持 | 可传输 IPv4、IPv6、AppleTalk、IPX 等多种网络层协议 |
链路建立与配置 | 使用 LCP(链路控制协议)协商链路参数,如最大帧大小、压缩等 |
身份验证 | 可选使用 PAP 或 CHAP 认证机制,确认连接双方身份 |
网络层协议协商 | 使用 NCP 协议,如 IPCP(用于 IP 地址协商) |
错误检测 | 采用帧校验(如 CRC)保障链路层数据的完整性 |
📦 PPP 帧结构
PPP 的帧结构(基于 HDLC)如下:
+----------+----------+---------+--------+-------------+----------+ |
Flag(01111110):起始/结束标志
Address:固定为 0xFF(广播地址)
Control:固定为 0x03(无序帧)
Protocol:指明上层协议(如 0x0021 表示 IPv4)
Payload:有效负载
FCS:帧校验序列(检测错误)
🌐 常见应用场景
场景 | 说明 |
---|---|
拨号上网(ADSL) | 使用 PPP over Ethernet(PPPoE) |
串口通信 | 两设备通过串口线直接建立点对点连接 |
工业设备、VPN 设备等 | 使用 PPP 实现 IP 通信和认证 |
✅ 总结一句话:
PPP 是面向点对点连接的、功能全面的数据链路层协议,尤其适合在串行线路上封装和传输多种网络层协议,具备链路控制、身份验证与协议协商等核心能力。
1. CVE-2023-20819
漏洞描述:
在 CDMA PPP 协议中,由于缺少边界检查,可能存在越界写入。这可能导致远程权限升级,而无需额外的执行权限。利用不需要用户交互。
CDMA PPP 是指在 CDMA(码分多址)蜂窝移动通信网络 中,使用 PPP(Point-to-Point Protocol)协议 进行数据连接的技术方式,主要用于 早期 2.5G / 3G 移动数据服务 中,如 CDMA2000 1x 或 EVDO 网络。
漏洞类型:
描述:
越界写入,产品在预期缓冲区的末尾或开始之前写入数据。
2. CVE-2022-30133
漏洞描述:
Windows 点对点协议(PPP)远程代码执行漏洞。
漏洞类型:
无
3. CVE-2020-8597
漏洞描述:
在PPP 2.4.2 到 2.4.8 的 PPPD 中,EAP.c 在 eap_request 和 eap_response 函数中存在 RSuneName 缓冲区溢出。
术语 含义 EAP.c
实现 EAP 协议逻辑的源代码文件,通常用于处理认证请求与响应。 eap_request
处理来自服务器的 EAP 请求,如 EAP-Identity、EAP-MD5 等。 eap_response
构造并发送客户端的 EAP 响应消息,作为认证流程的一部分。 RSuneName
字符数组(缓冲区)变量名,用来存储用户名或标识符。
分析:
CVE-2020-8597 是 pppd 中的一个缓冲区溢出漏洞,是由于可扩展身份验证协议 (EAP) 的数据包处理器中存在逻辑缺陷所致。未经身份验证的远程攻击者将特制的 EAP 数据包发送到易受攻击的 PPP 客户端或服务器,可造成拒绝服务情况或获得任意代码执行。由于 pppd 与内核驱动程序一起工作,并且通常以高权限(如 system 甚至 root)运行,因此任何代码执行也可以以这些相同的权限运行。
根据 CERT/CC 的漏洞说明,该逻辑缺陷存在于多个 EAP 函数中。
在 eap_request 和 eap_response 函数中,使用第一个字节作为类型接收指针和长度作为输入。如果此类型是 EAPT_MD5CHAP(4),则它查看嵌入的 1 字节长度字段。实施此检查是为了确保嵌入长度小于整个数据包长度的长度。如果检查成功通过,则位于嵌入长度之后的主机名将复制到本地堆栈缓冲区中。漏洞在于这些函数如何解析代码的逻辑。如果边界检查不正确并继续复制具有任意长度数据的内存,则可能会出现堆栈缓冲区溢出。
eap_input 函数在其代码中包含另一个缺陷,该缺陷无法验证 EAP 是否是在 PPP 中的链路控制协议 (LCP) 阶段协商的。从本质上讲,无论验证失败是由于 LCP 阶段的预共享密码不正确还是由于缺乏对 EAP 的支持,未经身份验证的攻击者都可以发送将被处理的 EAP 数据包。处理此未经验证的 EAP 数据包可能会导致堆栈缓冲区溢出。
补丁:
假设:
len
是总缓冲区大小vallen
是已使用的缓冲区大小sizeof(rhostname)
是要添加的内容大小
因为vallen
值小于len
。所以第一句if (vallen >= len + sizeof(rhostname))
的情况永远不会发生,如果后续代码继续执行rhostname
的写入,而没有检查内存剩余空间,这就有可能会导致发生内存溢出。
而改成第二句if (len - vallen >= sizeof(rhostname))
后,直接计算剩余空间是否足够,只有当剩余空间>=所需空间时,才允许写入,就能阻止rhostname
溢出。