2018Xuca-Warmup之php文件包含问题

2018Xuca一道web热身题,考点是文件包含,比较简单。
下面是源码:

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?php
class emmm
{
public static function checkFile(&$page)
{

$whitelist = ["source"=>"source.php","hint"=>"hint.php","index"=>"index.php"];
if (! isset($page) || !is_string($page)) {
echo "you can't see it1";
return false;
}
if (in_array($page, $whitelist)) {
//echo 'pass1';
return true; //情况一:输入的参数在给定的白名单里面,可以包含成功
}

$_page = mb_substr( //截取字符串
$page,
0,
mb_strpos($page . '?', '?')
);
//echo '<br>'.$_page.'<br>';
if (in_array($_page, $whitelist)) {
echo 'pass2';
return true;
}

$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
}
}

if (! empty($_REQUEST['file']) //存在file参数
&& is_string($_REQUEST['file']) //是字符串
&& emmm::checkFile($_REQUEST['file']) //调用类方法检查
) {

include $_REQUEST['file'];
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
?>

分析

主要是调用类方法对输入的参数进行检查,类方法判断了基本上是三种情况,满足其中一种返回为true都可以调用包含。

情况1是输入的参数在白名单里,直接包含。

情况2是多了个截取字符串,在输入内容后面加了问号,然后又截取问号前面的字符串(没想明白这样做有啥意义)
这就给我们操作留了后门。我们可以这样构造

1
2
file=source.php?../../../../../../../etc/passwd
file=hint.php?../../../../../../..//etc/passwd

斜杠分割的是一个目录,这里source.php?..整个会被认为是一个文件,但是在目录里这个文件并不存在,因此会继续触发后面的导致目录穿越
所以类似这样的payload也是可以的:

1
file=%20source.php?dasdasdasd/../../../../../../etc/passwd

涉及到的漏洞是:phpmyadmin4.8.1远程文件包含漏洞(CVE-2018-12613)

情况3是对得到的参数解码(第二步截取后的),然后再截取。整体的思路就是第一段不出现?,第二段又要出现?。
所以进行二次urlencode编码, %253f 浏览器会自动解码一次变成%3f,再经过代码的urldecode()变成?。
接下来就是文件包含了。这里的文件包含和题目部署环境有关,Windows由于目录命名规则不能带?。
所以只能使用这个方式。