pass17-源码分析
打开pass17,貌似和前面的几关差不多(pass14,15,16都是图片马)。
看源码和提示:
提示:
即利用上传的图片生成了一张新的图片。
源码:
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])){
// 获得上传文件的基本信息,文件名,类型,大小,临时文件路径
$filename = $_FILES['upload_file']['name'];
$filetype = $_FILES['upload_file']['type'];
$tmpname = $_FILES['upload_file']['tmp_name'];
$target_path=UPLOAD_PATH.'/'.basename($filename);
// 获得上传文件的扩展名
$fileext= substr(strrchr($filename,"."),1);
//判断文件后缀与类型,合法才进行上传操作
if(($fileext == "jpg") && ($filetype=="image/jpeg")){
if(move_uploaded_file($tmpname,$target_path)){
//使用上传的图片生成新的图片
$im = imagecreatefromjpeg($target_path);
if($im == false){
$msg = "该文件不是jpg格式的图片!";
@unlink($target_path);
}else{
//给新图片指定文件名
srand(time());
$newfilename = strval(rand()).".jpg";
//显示二次渲染后的图片(使用用户上传图片生成的新图片)
$img_path = UPLOAD_PATH.'/'.$newfilename;
imagejpeg($im,$img_path);
@unlink($target_path);
$is_upload = true;
}
} else {
$msg = "上传出错!";
}
}else if(($fileext == "png") && ($filetype=="image/png")){
if(move_uploaded_file($tmpname,$target_path)){
//使用上传的图片生成新的图片
$im = imagecreatefrompng($target_path);
if($im == false){
$msg = "该文件不是png格式的图片!";
@unlink($target_path);
}else{
//给新图片指定文件名
srand(time());
$newfilename = strval(rand()).".png";
//显示二次渲染后的图片(使用用户上传图片生成的新图片)
$img_path = UPLOAD_PATH.'/'.$newfilename;
imagepng($im,$img_path);
@unlink($target_path);
$is_upload = true;
}
} else {
$msg = "上传出错!";
}
}else if(($fileext == "gif") && ($filetype=="image/gif")){
if(move_uploaded_file($tmpname,$target_path)){
//使用上传的图片生成新的图片
$im = imagecreatefromgif($target_path);
if($im == false){
$msg = "该文件不是gif格式的图片!";
@unlink($target_path);
}else{
//给新图片指定文件名
srand(time());
$newfilename = strval(rand()).".gif";
//显示二次渲染后的图片(使用用户上传图片生成的新图片)
$img_path = UPLOAD_PATH.'/'.$newfilename;
imagegif($im,$img_path);
@unlink($target_path);
$is_upload = true;
}
} else {
$msg = "上传出错!";
}
}else{
$msg = "只允许上传后缀为.jpg|.png|.gif的图片文件!";
}
}
注意函数
basename()
给出一个包含有指向一个文件的全路径的字符串,本函数返回基本的文件名。
看一些例子:
<?php
echo "1) ".basename("/etc/sudoers.d", ".d").PHP_EOL;
echo "2) ".basename("/etc/sudoers.d").PHP_EOL;
echo "3) ".basename("/etc/passwd").PHP_EOL;
echo "4) ".basename("/etc/").PHP_EOL;
echo "5) ".basename(".").PHP_EOL;
echo "6) ".basename("/");
?>
输出:
看源码可以知道,如果图片 的类型是png,gif,png并且Content-type是允许上传的。(比如源码15行)
所以在看上面的源码的时候,只需要看一个if语句块就行了:
if(($fileext == "jpg") && ($filetype=="image/jpeg")){
if(move_uploaded_file($tmpname,$target_path)){
//使用上传的图片生成新的图片
$im = imagecreatefromjpeg($target_path);
if($im == false){
$msg = "该文件不是jpg格式的图片!";
@unlink($target_path);
}else{
//给新图片指定文件名
srand(time());
$newfilename = strval(rand()).".jpg";
//显示二次渲染后的图片(使用用户上传图片生成的新图片)
$img_path = UPLOAD_PATH.'/'.$newfilename;
imagejpeg($im,$img_path);
@unlink($target_path);
$is_upload = true;
}
}
在上面 的代码中,就是只针对于jpg类型的图片进行新的处理。PNG和GIF都是同理。
关注有一行:(使用上传的图片生成新的图片)
函数imagecreatefromjpeg()
php官网的介绍:
由文件或 URL 创建一个新图象。
imagecreatefromjpeg() 返回一图像标识符,代表了从给定的文件名取得的图像。
貌似也没有特别的东西。
pass17-图片上传
上传之前第14关-16关我一直用的图片马:shell.gif
上传之前,先把之前几关遗留的马删除。
不知道为什么我上传完是这个鬼样子。。。
可能是环境问题。
我将PHP版本改为7.3.4nts,清空上传文件之后再次上传文件。
又告诉我不是GIF格式的文件。。。
后来我又尝试了几次,有一次确实上传成功了,但是文件包含怎么都不行。奇了怪了。。。
其实是因为“二次渲染”导致上传 的图片中的一句话木马已经不见了。
那这一关该怎么做呢?
文件对比工具进行对比:
将二次渲染的图片和我原先上传的图片shell.gif进行对比(可以用010editor进行对比)
发现:
1.文件头的部分有一些区别。
2.一句话木马 的内容被删去了。
解决思路:把木马加载哪一个地方,木马才不会被删掉。
当然我自己有一个图片(不会因为“二次渲染”而导致木马被删掉),
上传文件:
再次连接webshell就成功。