目录
考点:
CVE:phpmyadmin 4.8.1 远程文件包含漏洞(CVE-2018-12613)
参考:CVE-2018-12613 本地文件包含漏洞复现+漏洞分析 - 先知社区 (aliyun.com)
Payload:
?file=hint.php?/../../../../../ffffllllaaaagggg
?file=source.php%3f/../../../../ffffllllaaaagggg # %3f解码:?
?file=source.php%253f/../../../../ffffllllaaaagggg # %25解码:% ,加上3f又成了%3f
WP:
1.寻找线索
发现只显示一张图片,先f12去看看源码、数据包之类。果然,在源码里面发现了被注释的source.php
在进入source.php之后,发现这是一道php代码审计的题目
2.分析代码,寻找突破点
由于网页里面不好分析,copy下来放到sunbline里面,
<?php
highlight_file(__FILE__);
class emmm{
public static function checkFile(&$page) //&引用参数形式
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page))
{
echo "you can't see it";
return false;
}
if (in_array($page, $whitelist))
{
return true;
}
$_page = mb_substr($page,0,mb_strpos($page . '?', '?'));
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;
}
echo "you can't see it";
return false;
}
}
if (! empty($_REQUEST['file'])
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
) {
//file=hint.php?./../../../../ffffllllaaaagggg
include $_REQUEST['file'];
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
} ?>
这串php代码,大致可以分成两个部分来分析:
第一点部分是定义了一个emmm类,这个类里面又定义了一个名为checkFile的方法
第二部分是代码的运行逻辑部分
3.如何获得flag?
那我们先从第二部分开始分析,理清这个代码逻辑关系
从这个if语句里面可以看到,他接收一个file传参,并且根据三个的判定条件为真的时候,执行include 函数,包含的内容就是我们的传参内容,那么我们的思路点显而易见了,我们需要包含flag所在的文件,这样就能得到最终的flag
让我们来看条件,
! empty($_REQUEST['file'])
request传递过来的参数flie不能为空
is_string($_REQUEST['file'])
这个参数得是字符串
emmm::checkFile($_REQUEST['file'])
将参数file的内容传递给emmm类里的checkFile函数进行操作,最后这个表达式需要为真,猜测这个函数的返回值是布尔类型,我们需要让他返回true
当这三个都满足的情况,我们就能执行include函数,从而包含到flag文件,那么:
尝试构造payload
?file=flag.php
返回了you can't see it
,应该是checkFile没有满足true,现在回过头去分析第一部分,看看如何满足checkFile,让他返回真
开始分析第二部分:
这个函数一共有四个if语句,
第一个if返回flase ,第二个if返回true ,第三个if返回true ,第四个if返回true ,
如果每个if都不满足,输出you can't see it
,并且返回flase
由于我们刚刚输入的?file=flag.php
,一个if都没有满足,于是返回了flase,并且输出了you can't see it
,
排错完毕,接下来看看如何拿到flag,
1.函数体内有一个白名单whitelist ,一个是hint.php,一个是souce.php
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
2.对三个返回true的if进行分析:
if (in_array($page, $whitelist))
{
return true;
}
如果$page(接收的参数)在$whitelist白名单里面,返回true 。本着信息搜集,多多益善的想法,
传参?fiel=hint.php进去
flag不在这,flag在 ffffllllaaaagggg ??,猜测这是个文件名,flag在这下面,ok此时注意,include函数的包含时候,是包含的路径
而我们输入的是hint.php,也就说默认包含的是./hint.php hint.php和souce.php在同级目录下,这个地方又说了flag的文件名,那么这
个时候能不能直接访问ffffllllaaaagggg呢?
显然没那么简单,当然这不是说ffffllllaaaagggg文件不存在,而是它不在当前目录下
回到代码分析,第二个返回true的if是这样的:
$_page = mb_substr($page,0,mb_strpos($page . '?', '?'));
if (in_array($_page, $whitelist))
{
return true;
}
mb_substr()
函数返回字符串的一部分,之前我们学过 substr() 函数,它只针对英文字符,如果要分割的中文文字则需要使用 mb_substr()
$_page = mb_substr( $page, 0 , mb_strpos($page . '?', '?') );
mb_substr()
函数是一个截取字符串的函数,
第一个参数是$page表示要截取的原字符串,也就是我们的传参file的值
第二个参数0 表示起始截取的位置,就是说从第一个位置开始截取
第三个参数 表示末尾截取的位置,
这个地方参数是mb_strpos($page . '?', '?')
这个函数的返回值是一个数字,这个函数表示寻找$page.'?'中第一次出现?
的地方,并且将位置作为返回值,例如我们传递的?file=flag.php,这个函数就会去flag.php?里去寻找第一个出现?的位置,
因此会返回8,带入进去就是$_page = mb_substr( flag.php, 0 , 8);
最后将左边截取的结果flag.php赋值给$_page
再进行if判断,如果$_page
在白名单数组$whitelist里,返回true
第三个if和第二个是差不多的,不过是多进行了一次url解码
那么我们尝试去满足第二个if到达文件包含,
我们根据他的$_page = mb_substr( $page, 0 , mb_strpos($page . '?', '?') );
构造payload:
?file=hint.php?ffffllllaaaagggg这样就能够满足条件返回true,因为他会截取前面的hint.php满足条件返回true
从而包含我们的ffffllllaaaagggg文件,但是我们刚刚说过了,flag这个文件不在当前目录下,
那么我们可以使用../的方式进行目录跃迁,于是,最终payload:
?file=hint.php?/../../../../../ffffllllaaaagggg
3.最终flag
flag{25e7bce6005c4e0c983fb97297ac6e5a}
标签:WarmUp,..,flag,file,php,true,page
From: https://www.cnblogs.com/GaolengDeKecy/p/17870636.html