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(7E) | Address | Control | Protocol | Payload | FCS (CRC)|
| 1 Byte | 1 Byte | 1 Byte | 1~2 Byte| 可变长度 | 2 Byte |
+----------+----------+---------+--------+-------------+----------+
  • 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 1xEVDO 网络。

漏洞类型:

CWE-787: Out-of-bounds Write

描述:

越界写入,产品在预期缓冲区的末尾或开始之前写入数据。

Diagram for CWE-787

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 数据包可能会导致堆栈缓冲区溢出。

补丁:

image-20250506232224602

假设:

  • len 是总缓冲区大小
  • vallen 是已使用的缓冲区大小
  • sizeof(rhostname) 是要添加的内容大小

因为vallen值小于len。所以第一句if (vallen >= len + sizeof(rhostname))的情况永远不会发生,如果后续代码继续执行rhostname的写入,而没有检查内存剩余空间,这就有可能会导致发生内存溢出。

而改成第二句if (len - vallen >= sizeof(rhostname))后,直接计算剩余空间是否足够,只有当剩余空间>=所需空间时,才允许写入,就能阻止rhostname溢出。