CVE-2024-2961完整RCE链详解:1字节glibc溢出如何秒杀PHP(Web手视角)

admin 2026-04-22 04:41:34 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文详细解析了CVE-2024-2961漏洞的完整RCE利用链,该漏洞源于glibc的iconv函数在ISO-2022-CN-EXT编码处理SS2/SS3切换时缺乏缓冲区边界检查,导致1字节溢出。攻击者可通过PHP的dechunk过滤器进行堆喷,污染内存布局后修改zendstring的len属性泄漏函数地址,最终覆盖zendmmheap结构的custom_heap函数指针为system()实现任意命令执行。文章从Web安全视角提供了完整的漏洞利用思路和技术细节。 综合评分: 85 文章分类: 漏洞分析,WEB安全,二进制安全,红队,渗透测试


cover_image

CVE-2024-2961 完整 RCE 链详解:1字节 glibc 溢出如何秒杀 PHP(Web手视角)

原创

YMsora YMsora

YMs0ra的安全漫路

2026年4月22日 00:32 浙江

在小说阅读器读本章

去阅读

这里算是我为数不多接触到pwn的一次,

但是我这次机会想到,我有必要进行对pwn的学习

当然,这次是PHP的多链引发的想法,涉及了一个PWN相关影响深远的CVE,CVE-2025-2961.

我会用WEB手也通俗易懂的语言来讲解,这个CVE网上相关文章也很多,我也就阐述一下自己观点

这个CVE的是发生在iconv函数中,并且基本上是在转义函数可控的情况下发生的,

这里先说说前置概念,这个缓冲区溢出是因为ISO-2022-CN-EXT的SS2/SS3切换缺乏缓冲区校验引起的

ISO-2022-CN-EXT是一个老旧的中文字符编码形式,

假设这个编码是一个柜子,那么SS2,SS3就是抽屉,用来存个别字符的柜子

我们先看一看简化的关键源码,

else&nbsp;if&nbsp;((used & SS2_mask) !=&nbsp;0&nbsp;&& (ann & SS2_ann) != (used <<&nbsp;8)) {&nbsp; &nbsp;&nbsp;const&nbsp;char&nbsp;*escseq;&nbsp; &nbsp; assert (used ==&nbsp;CNS11643_2_set);&nbsp;/* XXX */&nbsp; &nbsp; escseq =&nbsp;"*H";&nbsp; &nbsp; *outptr++ = ESC; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 0x1B&nbsp; &nbsp; *outptr++ =&nbsp;'$'; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 0x24&nbsp; &nbsp; *outptr++ = *escseq++; &nbsp; &nbsp;// 0x2A&nbsp; &nbsp; *outptr++ = *escseq++; &nbsp; &nbsp;// 0x48&nbsp; &nbsp; ann = (ann & ~SS2_ann) | (used <<&nbsp;8);}else&nbsp;if&nbsp;((used & SS3_mask) !=&nbsp;0&nbsp;&& (ann & SS3_ann) != (used <<&nbsp;8)) {&nbsp; &nbsp;&nbsp;const&nbsp;char&nbsp;*escseq;&nbsp; &nbsp; assert ((used >>&nbsp;5) >=&nbsp;3&nbsp;&& (used >>&nbsp;5) <=&nbsp;7);&nbsp; &nbsp; escseq =&nbsp;"+I+J+K+L+M"&nbsp;+ ((used >>&nbsp;5) -&nbsp;3) *&nbsp;2;&nbsp; &nbsp; *outptr++ = ESC;&nbsp; &nbsp; *outptr++ =&nbsp;'$';&nbsp; &nbsp; *outptr++ = *escseq++;&nbsp; &nbsp; *outptr++ = *escseq++;&nbsp; &nbsp; ann = (ann & ~SS3_ann) | (used <<&nbsp;8);}

当识别是SS2/SS3的时候在缓存区写入我注视的这一串命令,

而这里并没有校验缓冲区是否够存放,所以会造成缓冲区溢出,

这个理念倒是非常清晰易懂,但是难点是如何利用进行RCE。

在PHP中控制了拥有读文件等操作,在漏洞版本范围内,便可上升为RCE这里要先从PHP的内存管理机制说起,

读文件可以用过滤器php://filter而filter支持dechunk自定义块,

在一块内存中,如果不停发送dechunk也就可以自定义每块的大小,

file_get_contents("php://filter/&nbsp; &nbsp; dechunk|&nbsp; &nbsp; convert.iconv.latin1.latin1|&nbsp; &nbsp; convert.iconv.latin1.latin1|&nbsp; &nbsp; (重复多次堆喷)&nbsp; &nbsp; convert.iconv.UTF-8.ISO-2022-CN-EXT/resource=/etc/passwd");

也就是空闲内存,然后当中插入受害块,

也就是ISO-2022-CN-EXT的SS2/SS3进行编码转换命令时分到的块,

而有几个特殊的汉字会使其溢出,这样就会溢出到相邻块,

也就会污染相邻块的最低位,往往是0x48,

也就是说最低位0000变为0x48,这样内存释放时free_solts的这部分内存指向就变了,

链表被毒化之后,攻击者利用堆喷(简略概括),

将许多空闲内存都挂上string对象,而其中是有len属性的,

当正常执行一次构造字符串时,地址偏移让正常写字符串的操作写入了len字段这样len的长度可以被改的超级大,

这样就泄漏了大量系统函数的地址接下来就是RCEPHP的内存管理器是ZENDMM,他是一个大内存池,它控制分配这些内存的供给与释放,

而其中_zend_mm_heap结构的子结构custom_heap控制内存释放的指针它控制着内存释放的时候指向的函数指针,

如此一来我调用dechunk结合之前泄漏的地址,任意写入custom_heap,将指针覆盖为system()的地址

//简化结构typedef&nbsp;struct&nbsp;_zend_mm_custom_heap {&nbsp; &nbsp;&nbsp;void&nbsp;(*_free)(void&nbsp;*ptr); &nbsp;&nbsp;// ← 要改的目标&nbsp; &nbsp;&nbsp;// ...} custom_heap;
_zend_mm_heap->custom_heap._free = system(); &nbsp;// 攻击者通过 overlap 实现

也就是每次内存释放都会调用当然PHP的内存调用是很频繁的,

最后将要执行的命令放入一个可控的zend_string对象中,

也就是一个挂载其的对象,然后触发一次内存释放,命令也就执行了。

链子到这里也就结束了,依旧是边界类型的漏洞,钻研吧~~

路漫漫路漫漫


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:YMs0ra的安全漫路 YMsora YMsora《CVE-2024-2961 完整 RCE 链详解:1字节 glibc 溢出如何秒杀 PHP(Web手视角)》

群友靶机之Twelve 网络安全文章

群友靶机之Twelve

文章总结: 该文档记录了对Twelve靶机的完整渗透测试过程。通过信息收集发现靶机开放22、80和1212端口,其中1212端口的Base-12转换器存在Jin
评论:0   参与:  0