本地溢出和远程溢出的区别
缓冲区溢出这事儿,本地说白了就是溢出程序往一块固定大小的内存区域里塞了太多数据,多出来的和远部分漫过了边界,把隔壁邻居的程溢出数据给踩了。踩到哪儿、区别踩了谁,本地决定了这次溢出是溢出"本地"还是"远程"。 先看一个具体的和远例子。假设有个程序在栈上开了个 64 字节的程溢出数组接收用户输入,用的区别是 整个过程,攻击者就坐在那台机器前面,或者在同一个 shell 会话里操作。他输入的数据直接喂给目标进程,不需要经过网络。这类场景就叫本地溢出。 本地溢出的利用条件相对宽松。攻击者通常已经能在这台机器上执行命令,或者至少能以某个低权限用户的身份登录。他要做的是提权——从普通用户变成 root,或者从一个受限进程跳到系统 shell。典型的场景包括: 远程溢出就完全不一样了。数据不再来自本地输入,而是通过网络从另一台机器送过来。攻击者坐在自己的电脑前,目标是一台远在千里之外的服务器。他构造一个恶意数据包,发过去,服务端程序在处理这个包的时候触发溢出,攻击者的代码就在那台服务器上跑起来了。 最典型的案例是 2017 年的 EternalBlue(MS17-010)。Windows 的 SMB 服务在处理特定请求时存在缓冲区溢出,攻击者只需要向目标机器的 445 端口发送一个精心构造的数据包,就能在目标系统上执行任意代码。WannaCry 蠕虫就是靠这个漏洞在几天内感染了全球几十万台机器。攻击者从头到尾没碰过那些机器,连物理接触都没有。 两者的核心差异在攻击面。本地溢出要求攻击者已经拥有某种形式的本地访问权限——哪怕只是一个低权限账户。远程溢出则把门槛降到了"能发包就行"。一台暴露在公网上的服务,如果存在远程溢出漏洞,理论上任何能连上那个端口的人都能尝试利用。这就解释了为什么远程溢出漏洞的 CVSS 评分通常比本地溢出高出一截,也是为什么安全圈里一听到"远程可利用的缓冲区溢出"就格外紧张。 利用难度上,两者也有区别。本地溢出攻击者往往能反复试错,崩了进程再重启一个就行,环境相对可控。远程溢出要考虑网络延迟、数据包大小限制、目标架构差异,payload 的构造更讲究。但反过来,远程溢出的"收益"也更大——攻击者不需要任何前置权限,直接从零到一。 还有个容易被忽略的点:本地溢出不一定比远程溢出"低级"。有些本地溢出漏洞出现在内核态,利用起来极其复杂,需要精确的内存布局操控和竞态条件触发。而某些远程溢出反而简单粗暴,一个畸形 HTTP 请求就能搞定。判断严重程度不能只看本地还是远程,还得看目标进程的权限、利用的可靠性、以及是否需要用户交互。 从防御角度看,两者的缓解思路有重叠也有分叉。栈保护(canary)、ASLR、DEP 这些机制对本地和远程溢出都有抑制作用。但远程溢出还需要在网络层做文章——防火墙规则、入侵检测、协议解析的严格校验。本地溢出则更依赖最小权限原则、SUID 程序的审计、以及系统补丁的及时更新。 搞安全的人心里都清楚,远程溢出是"外面的狼",本地溢出是"家里的老鼠"。狼来了动静大,但老鼠咬起东西来一样要命。strcpy 这种不做长度检查的函数。用户在命令行里敲了 200 个字符,本地前 64 个正常落进数组,溢出剩下的和远 136 个字节就顺着栈往高地址方向一路覆盖——先是保存的寄存器值,然后是程溢出函数的返回地址。如果攻击者精心构造这 136 个字节,区别把返回地址改成自己 shellcode 的入口,程序一返回就跳去执行攻击者的代码了。这就是最经典的栈溢出利用。sudo 某个配置不当的命令、带 SUID 位的程序、或者系统服务里以高权限运行的本地接口。CVE-2021-4034(PwnKit)就是个好例子,pkexec 这个 SUID 程序在处理参数时越界写入,本地用户构造一下环境变量就能拿到 root。攻击者根本不需要网络,本地敲几条命令就成了。
-
上一篇
-
下一篇