参考链接等
https://www.cnblogs.com/xhds/p/13239331.html
https://www.anquanke.com/post/id/83844
https://chybeta.github.io/2017/05/13/%E5%88%A9%E7%94%A8PHP%E7%9A%84OPcache%E6%9C%BA%E5%88%B6getshell/
https://www.gosecure.net/blog/2016/04/27/binary-webshell-through-opcache-in-php-7/
题目
https://github.com/tothi/ctfs/tree/master/alictf-2016/homework
2022强网杯uploadpro
https://www.ctfiot.com/116586.html
工具
https://github.com/GoSecure/php7-opcache-override
https://github.com/M0x0is3ry/php8-opcache-override
原理
OPcache是一种通过解析的PHP脚本预编译的字节码存放在共享内存中来避免每次加载和解析PHP脚本的开销,解析器可以直接从共享内存读取已经缓存的字节码,从而大大提高了PHP的执行效率。
简单来说,就是第一次访问的时候,会生成一个对应的二进制文件,例如访问1.php,就会生成1.php.bin
后面只要你访问1.php,实际上都是在执行1.php.bin,而我们可以通过上传恶意二进制文件,覆盖1.php.bin,那么再次访问1.php时,就会执行恶意二进制文件,到达getshell的目的
如果目标题目给了一个phpinfo页面,可以获得opcache配置,以及后续计算systemid所需信息
并且还有一个任意文件上传的页面,那么我们就可以对其二进制文件进行覆盖,使页面的二进制文件变成我们上传的恶意文件。
php7
如果站点存在一个phpinfo文件,通过文件可以得到opcache缓存目录,php版本号,zend拓展版本号等多个数据,可以用来计算system_id
随便找个php7。并且要有opcache拓展
配置cli的php.ini,也就是本地php对应的配置
开启php内置web服务,访问页面
即可获得一个二进制文件
zend_extension=opcache.so
opcache.validate_timestamps=0 ;关闭时间戳验证
opcache.file_cache="/tmp/opcache" ;设置缓存储存未知
opcache.file_cache_only=1 ;设置缓存优先级
此时我们需要去生成一个恶意二进制文件来覆盖1.php.bin,这样我们去访问1.php时,则会加载恶意二进制文件
生成恶意二进制文件需要phpinfo页面的一些信息,我们将phpinfo页面的信息保存到info.html中,并使用脚本计算systemid
用上面同样的方式生成一个恶意二进制文件,并更改其systemid
对应的php文件
具体的生成过程之前就操作过了
将恶意二进制文件覆盖掉原来的二进制文件
再次访问
拿下!
php8
本质上就是换了一个systemid的生成方式,因为我不太会逆向方面的知识,所以只能贴一下别的师傅的操作了https://www.yuque.com/misery333/sz1apr/ah97rk23alsgx3n1
绕过时间戳验证
改为1,开启时间戳认证
https://www.php.net/manual/zh/opcache.configuration.php#ini.opcache.validate-timestamps
如果启用了时间戳验证,OPcache 将检查请求的 PHP 源文件的时间戳,并将其与缓存文件的时间戳头字段进行比较。如果它们不匹配,则丢弃缓存文件并创建一个新文件。
简单来说就是需要二进制文件与原文件的时间戳要对上
通过任意文件下载,从原二进制文件中获取时间戳,修改恶意二进制文件的时间戳并上传覆盖,再次访问页面即可
操作
开启服务,访问1.php并获取其二进制文件
使用配套的010 opcache脚本提取时间戳,并修改恶意文件的时间戳
保存,改名为1.php.bin并上传覆盖原二进制文件
成功