靶場首頁
打開靶場后,查看源碼即可看到<!--source.php-->

打開source.php頁面
代碼如下
<?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'])
) {
include $_REQUEST['file'];
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
?>
審計php代碼
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
得到另一個地址/hint.php,打開以后提示我們flag在ffffllllaaaagggg里面

接下來,繼續審計source.php代碼
if (! empty($_REQUEST['file']) //$_REQUEST['file']值非空
&& is_string($_REQUEST['file']) //$_REQUEST['file']值為字符串
&& emmm::checkFile($_REQUEST['file']) //能夠通過checkFile函數校驗
) {
include $_REQUEST['file']; //包含$_REQUEST['file']文件
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
//打印滑稽表情
}
這段代碼告訴們需要滿足三個條件
1.值為非空 2.值為字符串 3.能夠通過checkFile()函數校驗 否則打印滑稽
查看checkfile()函數
highlight_file(__FILE__); //打印代碼
class emmm //定義emmm類
{
public static function checkFile(&$page)//將傳入的參數賦給$page
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];//聲明$whitelist(白名單)數組
if (! isset($page) || !is_string($page)) {//若$page變量不存在或非字符串
echo "you can't see it";//打印"you can't see it"
return false;//返回false
}
if (in_array($page, $whitelist)) {//若$page變量存在於$whitelist數組中
return true;//返回true
}
$_page = mb_substr(//該代碼表示截取$page中'?'前部分,若無則截取整個$page
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
$_page = urldecode($page);//url解碼$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語句
1.第一個if語句對變量進行檢驗,要求$page為字符串,否則返回false 2.第二個if語句判斷$page是否存在於$whitelist數組中,存在則返回true 3.第三個if語句判斷截取后的$page是否存在於$whitelist數組中,截取$page中'?'前部分,存在則返回true 4.第四個if語句判斷url解碼並截取后的$page是否存在於$whitelist中,存在則返回true 若以上四個if語句均未返回值,則返回false 有三個if語句可以返回true,第二個語句直接判斷$page,不可用 第三個語句截取'?'前部分,由於?被后部分被解析為get方式提交的參數,也不可利用 第四個if語句中,先進行url解碼再截取,因此我們可以將?經過兩次url編碼,在服務器端提取參數時解碼一次,checkFile函數中解碼一次,仍會解碼為'?',仍可通過第四個if語句校驗。('?'兩次編碼值為'%253f'),構造url: http://399fe153-1f62-43d5-a67f-e645a0e7ac66.node3.buuoj.cn/source.php?file=source.php%253f../ffffllllaaaagggg
經過測試發現無返回值,這可能是因為我們不知道ffffllllaaaagggg文件存放的具體位置
所以依次增加../,最終成功拿到flag
http://xxxx:xxxx/source.php?file=source.php%253f../../../../../ffffllllaaaagggg
