PHP…

0x01 Opcache 简介

Opcache(从PHP5.5.0开始):

字节码缓存。
PHP是解释型语言,构建在Zend 虚拟机之上,PHP解释器在执行PHP脚本时会解析PHP脚本代码,把PHP代码编译成一系列Zend操作码(由于每个操作码都是一个字节长,所以又叫字节码,字节码可以直接被Zend虚拟机执行),然后执行字节码。每次请求PHP文件都是这样,这会消耗很多资源,如果每次HTTP请求都必须不断解析、编译和执行PHP脚本,消耗的资源更多。如果PHP源码不变,相应的字节码也不会变化,显然没有必要每次都重新生成Opcode.下面是启用Opcode缓存之前和之后的流程图

0x02 攻击详情

原理:

由于生成的缓存文件存在可被替换的可能,这样就可能出现后门

缓存目录(PHP7.0出现):

1
opcache.file_cache=/tmp/opcache

例如访问个index.php,就会在缓存目录下生成/tmp/opcache/[system_id]/[web_path]/index.php.bin.
其中system_id和PHP版本、Zend Extension Build、各种数据类型长度(php7以上的数据种类发生改变)有关,system_id的计算;web_path可以通过phpinfo获取.
关于缓存目录的权限:

可见web用户是可以替换其中的文件的.

攻击实验:

1
2
3
4
文件上传不被限制
php.ini配置:
opcache.validate_timestamps = 0
opcache.file_cache_only = 1

关于opcache.validate_timestampsopcache.file_cache_only

首先一个上传页面

其中override_me.php

本地搭建相同版本的PHP项目.

之后将override.php.bin的system_id修改为服务端的system_id.

之后将override.php.bin上传.

关于opcache.file_cache_only=0opcache.validate.timestamps=1的绕过

opcache.file_cache_only=0
此时内存缓存和文件缓存同时打开,内存缓存优先于文件缓存,该攻击方法失效,除非服务器能够进行重启.但是还可以利用框架中那些已经被抛弃的文件,这种文件并没有在内存中产生缓存,例如Wordpress框架中的registration-functions.php.

opcache.validate.timestamps=1
此时启用了时间戳认证功能,将会把请求的源文件和缓存文件的header中的时间戳匹配,不同则删除缓存文件并创建新的缓存文件.绕过场景和先前的opcache.file_cache_only=0相同,有些文件时间戳不会发生改变.

0x03 One’s Strom

php版本会导致缓存文件的格式不相同.

使用vld扩展调试php-Opcache文件

1
2
-d vld.active 表示是否子在php执行时启用vld
-d vld.execute 表示是否执行这段脚本

注:可以在启用php服务器时添加扩展

关于php5的APC

php5时存在APC(可选缓存),分为系统缓存和用户数据缓存.

参考链接:
Binary Webshell Through OPcache in PHP 7
现代 PHP 新特性系列(六) —— Zend Opcache
php-src

(ง •_•)ง