OPcache扩展在PHP5.5.0版本后中已经绑定了,它可以把PHP脚本预编译的字节码存放到缓存中,从而提高性能,加速访问。同时也可以利用它来进行getshell。
本文是对 《binary-webshell-through-opcache-in-php-7》一文的测试。
关于OPcache
在我们指定了一个缓存目录(后面提到)后,php会把编译好的php字节码文件放到这个缓存目录中。这里假设该缓存目录是/var/www/html/opcache
,未访问前,opcache
文件夹为空。接下去我去访问 index.php
后,php会在 opcache
文件夹中创建一个名为md5哈希值的文件夹,其下的目录结构和 index.php
所在目录结构相同,同时生成了 index.php.bin
。
这个index.php.bin
就是 index.php
的缓存文件。并且作为www-data
用户,我们对 5672f68788bcb25b11403b33f5d1497f
具有读写执行权限。这样,我们想办法把这个index.php.bin
替换为包含有恶意代码的index.php.bin
文件,当我们再次去访问index.php
时,php会选择加载这个缓存文件,从而我们达到了getshell的目的。这个思路,感觉跟二进制漏洞中的GOT覆写技术有点神似吧。
环境配置
php版本
|
|
配置OPcache
开启OPcache
在php配置文件 php.ini
的约莫 1745 行左右,找到如下配置:
去掉前面的分号;
,将0
改为1
,如下:
关闭时间戳验证
|
|
修改为
设置OPcache缓存路径
继续向下翻,找到如下配置:
这里我修改后的配置是:
设置缓存文件优先级
|
|
修改为
重启apache
这里我以apache作为web服务器。
重启,使前面修改的php.ini
生效
www目录
index.php
|
|
upload-file.php
|
|
那个。。代码写得很丑。。仅为测试之用:)
phpinfo.php
|
|
getshell
现在开始黑盒测试。。
利用phpinfo获取信息
可知,OPcache缓存路径在 /var/www/html/opcache
中。且服务器端开启了 opcache.file_cache_only
,禁用了opcache.validate_timestamps
。 这是能成功利用的条件。
php7-opcache-override.py
由前可知,在对缓存文件进行操作前,需要经过一个名称是md5哈希值的文件夹。这可以通过 hp7-opcache-override.py 来计算。
得到这个文件夹名为:5672f68788bcb25b11403b33f5d1497f
构建恶意的缓存文件
恶意的缓存文件得先本地生成,然后通过各种方式比如上传等去覆盖服务器上的缓存文件。我们先在本地配置好OPcache,这样才能生成缓存文件。然后本地新建一个 index.php
,内容是一句话木马<?php @eval($_POST[test]);?>
,之后访问它。在对应的缓存文件夹里可以看到index.php.bin
用十六进制编辑器打开,将OPCACHE.
后的那串md5哈希值,替换为前一步骤得到的哈希值:5672f68788bcb25b11403b33f5d1497f ,修改后如下:
覆盖原缓存文件
在覆盖之前,先看看服务器上的原缓存文件长啥样:
这里利用上传来进行覆盖。访问index.php
,选择修改后的index.php.bin
进行上传,上传路径为要覆盖的缓存文件的相对地址 opcache/5672f68788bcb25b11403b33f5d1497f/var/www/html/
。
上传完成后,服务器上的缓存文件已经替换成我们构造的恶意文件了。
菜刀连上
此时再去访问 index.php
,发现已经被修改了,不再是上传的页面。用菜刀连上,密码是 test 。成功getshell。
CTF
前面我们是通过上传来实现覆盖,但实际利用起来肯定没那么简单。利用OPcache来获得webshell的姿势一般都会和其他姿势相结合。比如下面两题CTF题
ASIS CTF 2016 – BinaryCloud
这题是通过上传来覆盖,但后端有各种过滤。
附上writeup
ALICTF 2016 - homework
这题利用sql注入的dumpfile来实现对缓存文件的覆盖。
附上writeup
(Author:chybeta)