容器环境:Apache
解析器:PHP
Content-Disposition: form-data; name="myfile[]"; filename="phpinfo.php
.jpg"
Content-Type: image/png
获得shell后开始对代码进行解析
从上图可以看到这里将我们上传的图片文件绑定到了某个msgID之中。并且在上面还有引入一段
include("upload_file.php");
在代码下方并未找到存储文件的代码,所以存入文件的代码应该写在了upload_file.php
随即我们开始解析该文件代码
<?php
//指定儲存檔案的目錄
$upload_dir = "./download/";
for ($i = 0; $i < 2; $i++)
{
//若檔案名稱不是空字串,表示上傳成功,將暫存檔案移至指定之目錄
if ($_FILES["myfile"]["name"][$i] != "")
{
$file_ext = pathinfo($_FILES["myfile"]["name"][$i], PATHINFO_EXTENSION);
$file_ext = strtolower($file_ext);
//modified by ling 20210118,判斷合法副檔名
//if( $file_ext != 'php'){
if (in_array($file_ext,array('pdf','ppt','pptx','doc','docx','jpg')))
{
//搬移檔案
$temp_file = explode(".",$_FILES["myfile"]["name"][$i]);
$temp_name = date("YmdHis_"). $i ."." . $temp_file[1];
$upload_file = $upload_dir . $temp_name ;
if (move_uploaded_file($_FILES["myfile"]["tmp_name"][$i], $upload_file))
{
//顯示檔案資訊
// echo "檔案名稱:" . $temp_file[0] . "<br>";
//echo "在資料夾的檔案名稱:" . $temp_name . "<br>";
//echo "<hr>";
if( $i == "0" )
{
$temp_file1 = $temp_name;
$file1 = $temp_file[0];
}
if( $i == "1" )
{
$temp_file2 = $temp_name;
$file2 = $temp_file[0];
}
} //if (move_uploaded_file
else
{
echo "檔案上傳失敗 (" . $_FILES["myfile"]["error"] . ")<br><br>";
echo "<a href='javascript:history.back()'>重新上傳</a>";
} //else (move_uploaded_file
} //if (in_array($file_ext
} //if ($_FILES["myfile"]["name"]
} //for ($i = 0;
?>
利用for循环1 – 2,然后利用 $_FILES[“myfile”][“name”][$i] != “” 判断其中的文件名不为空。
利用 pathinfo 解析文件名,形成一个数组
$file_ext = pathinfo($_FILES["myfile"]["name"][$i], PATHINFO_EXTENSION);
通过这个 PATHINFO_EXTENSION 属性,判断是在取文件名的后缀。
$file_ext = strtolower($file_ext);
将后缀转换为统一小写
通过上图分析出当初这里采用的黑名单验证,后改为白名单验证,取后缀名称来与数组里面的白名单后缀匹配,当只有匹配到了后缀才会进入该代码区间。
我们通过层层打印
var_dump($file_ext);die;
发现打印出来的值的确是 jpg
那么他是如何绕过了in_array函数进行到下一步的呢?
随即我们打印下面这段代码的布尔值
var_dump(in_array($file_ext,array('pdf','ppt','pptx','doc','docx','jpg')));die;
得到结果 bool(true)
所以问题出现在何方?
原因
因为我们的后缀的确是 jpg结尾,并且也的确满足in_array函数的要求,但在下方保存文件名的时候出现了问题。
//搬移檔案
$temp_file = explode(".",$_FILES["myfile"]["name"][$i]);
$temp_name = date("YmdHis_"). $i ."." . $temp_file[1];
$upload_file = $upload_dir . $temp_name ;
其中我们最主要关注 explode(".",$_FILES["myfile"]["name"][$i]);
他的打印结果我们来看看。
其中最主要的是在第二段的取值: $temp_name = date("YmdHis_"). $i ."." . $temp_file[1];
他这里最大的缺陷在于取了数组中的固定值,这里如果他使用 end 函数,默认只取最后一个就能完美修复该漏洞。
例如:end 函数取值。
最终达到修复该漏洞
所以并不是我们的回车绕过了漏洞,而是他的内部取值出现了问题。
暂无评论内容