文章总结: 该文档详细分析了CVE-2024-2961漏洞利用链,指出glibc的iconv函数在处理ISO-2022-CN-EXT编码时因SS2/SS3切换缺乏缓冲区校验导致1字节溢出。通过PHP的php://filter过滤器和dechunk机制进行堆布局,利用溢出修改内存结构泄漏函数地址,最终覆盖ZENDMM内存管理器的custom_heap函数指针为system()实现远程代码执行。文章从WEB手视角提供了完整的漏洞利用思路和技术细节。 综合评分: 85 文章分类: 漏洞分析,WEB安全,二进制安全,红队,应急响应
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 if ((used & SS2_mask) != 0 && (ann & SS2_ann) != (used << 8)) { const char *escseq; assert (used == CNS11643_2_set); /* XXX */ escseq = "*H"; *outptr++ = ESC; // 0x1B *outptr++ = '$'; // 0x24 *outptr++ = *escseq++; // 0x2A *outptr++ = *escseq++; // 0x48 ann = (ann & ~SS2_ann) | (used << 8);}else if ((used & SS3_mask) != 0 && (ann & SS3_ann) != (used << 8)) { const char *escseq; assert ((used >> 5) >= 3 && (used >> 5) <= 7); escseq = "+I+J+K+L+M" + ((used >> 5) - 3) * 2; *outptr++ = ESC; *outptr++ = '$'; *outptr++ = *escseq++; *outptr++ = *escseq++; ann = (ann & ~SS3_ann) | (used << 8);}
当识别是SS2/SS3的时候在缓存区写入我注视的这一串命令,
而这里并没有校验缓冲区是否够存放,所以会造成缓冲区溢出,
这个理念倒是非常清晰易懂,但是难点是如何利用进行RCE。
在PHP中控制了拥有读文件等操作,在漏洞版本范围内,便可上升为RCE这里要先从PHP的内存管理机制说起,
读文件可以用过滤器php://filter而filter支持dechunk自定义块,
在一块内存中,如果不停发送dechunk也就可以自定义每块的大小,
file_get_contents("php://filter/ dechunk| convert.iconv.latin1.latin1| convert.iconv.latin1.latin1| (重复多次堆喷) 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 struct _zend_mm_custom_heap { void (*_free)(void *ptr); // ← 要改的目标 // ...} custom_heap;
_zend_mm_heap->custom_heap._free = system(); // 攻击者通过 overlap 实现
也就是每次内存释放都会调用当然PHP的内存调用是很频繁的,
最后将要执行的命令放入一个可控的zend_string对象中,
也就是一个挂载其的对象,然后触发一次内存释放,命令也就执行了。
链子到这里也就结束了,依旧是边界类型的漏洞,钻研吧~~
路漫漫路漫漫
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:YMs0ra的安全漫路 YMsora YMsora《CVE-2024-2961 完整 RCE 链详解:1字节 glibc 溢出如何秒杀 PHP(Web手视角)》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论