兄弟姐妹们,今天咱们不聊虚的,我就要把前几天踩的一个大坑,UAF后释放分块传输,这事儿从头到尾给您唠明白喽!哎,说多了都是泪啊,但我觉得不写出来,对不起我掉的这几根头发!
起因: 那天晚上,我正美滋滋地测试一个自认为固若金汤的Web应用,这应用呢,用的是老掉牙的C语言写的后端,那内存管理,啧啧,全靠程序员自觉,我寻思着,这年头谁还靠自觉啊?灵感一来,我就想到了分块传输(Chunked Transfer Encoding)这个老朋友。
您想啊,HTTP分块传输,本来就是服务器把响应拆成一堆“小方块”发给客户端,每个块前面还有个十六进制的长度标记,这玩意儿本身没问题,但要是跟UAF(Use-After-Free,释放后使用) 搅合在一起,那可就热闹了。
冲突与发现: 我当时构造了一个特别刁钻的请求,愣是让服务器在解析第一个块的时候,就因为某个字段不合格,把存放数据的内存块给free()掉了,按道理,服务器接下来应该报错返回,这事儿就完了。结果呢? 这破服务器居然没彻底退出解析逻辑,它在处理完错误后又傻乎乎地回头去读那个已经被释放的内存区域!
这就相当于啥呢?就好比你租了个房子,退租了,房东把钥匙都收走了,结果你半夜喝多了,又跑回去拿备用钥匙开门,还往人家已经租给别人的新房客床上躺!这不扯呢么!
情绪爆发点: 我当时看着抓包工具里那个“第二次”返回的分块传输数据,人都傻了。好家伙! 那个被释放的内存(UAF后释放)里,居然残留着上一次合法请求的部分数据,甚至可能包含其他用户会话的敏感标记!攻击者完全可以利用这个缝隙,通过精心构造的分块,逼迫服务器把“垃圾堆”里的残影吐出来。
最气人的是,这种漏洞在日志里看起来就是正常的200 OK,只是传输的块数量多了点、大小怪了点,您说气不气人? 就像你明明没偷东西,但口袋里突然多了别人的钱包,你还没法解释!
细节复盘: 后来我仔细琢磨,这UAF后释放分块传输能成立,核心在于两个“没想到”,第一,没想到服务器在错误处理分支里没有打断链接的上下文状态;第二,没想到分块传输的续传机制这么“头铁”,错误后还能接着前一个块的长度继续读下一块,这俩一叠加,漏洞就成了。
这让我想起以前搞CTF,总觉得UAF在堆上利用才高大上,谁能想到在HTTP协议解析层也能玩出花来?真是活到老,学到老,坑到老啊!这要是被恶意攻击者盯上,直接就能当个“内存读取器”用,指不定能把服务器里的密码哈希或者密钥字符串给一行行抠出来。
总结警告: 所以啊,各位写网络服务的同僚,尤其是跟epoll、malloc打交道的,千万长点心,别光盯着业务逻辑,协议解析的边界和内存生命周期管理,那就是生死线!分块传输不是原罪,但UAF后释放是,两者结合,就是一颗定时炸弹。
好了好了,不说了,我得去把那个服务器补丁打上,顺便再把代码审计报告写得惨烈一点,哎,这年头,攻防就是心理战,拼的就是谁比谁更细致!

友情提示: 对Web安全、二进制漏洞感兴趣的朋友,想一起交流学习网络安全技术,可以加QQ:123456789(备注“学习安全”),咱们一起进步!

