本文主要是介绍我的创作纪念日【特别篇】--【文件上传漏洞(三)】-lab 11-lab19,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文件上传漏洞——upload-labs 1-19
文章目录
- 文件上传漏洞——upload-labs 1-19
- lab 11、%00截断绕过(GET)
- 源码分析
- 检测方法
- 绕过方法
- 抓包上传
- lab 12、%00截断绕过(二)(POST)
- 源码审计
- lab 13、图片马绕过
- 源码分析
- 相关函数
- 图片马
- 什么是图片马
- 如何制作图片马
- 绕过非法
- lab 14、getimagesize图片类型绕过
- 查看源码
- 相关函数
- 制作看似正常的图片马
- upload-labs-15 exif_imagetype()-图片马
- 源码分析
- 绕过方式
- lab 16 二次渲染绕过
- 源码分析
- 关键函数
- 二次渲染
- 相关函数
- 检测方式
- 绕过方式
- lab 17、
- 源码分析
- 检测方式
- 绕过方式
- 上传木马文件用bp抓包
- labs-18 条件竞争
- 源码分析
- 检测方式
- 绕过方式
- 具体步骤
lab 11、%00截断绕过(GET)
源码分析
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){$ext_arr = array('jpg','png','gif');$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);if(in_array($file_ext,$ext_arr)){$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;if(move_uploaded_file($temp_file,$img_path)){$is_upload = true;}else{$msg = '上传失败!';}}else{$msg = "只允许上传.jpg|.png|.gif类型文件!";}
}
查看源代码,意识到他是一个白名单,我们前面学习的方法是用不了的,
在本关的核心突破口是:
$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
相比于前几关
$_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $file_name
我们发现本关的 save_path 是我们可控的,换句话说在本关上传地址是可以被我们所掌控的,
我们可以尝试在本关 使用 %00截断 将后面的语句给截断
检测方法
白名单 + 文件重命名
绕过方法
通过==%00截断==完成
- 在这里我们可以将 %00 看作sql中的 注释符 将后面的php函数注释掉
- %00本意为:0x00会截断,0x表示16进制,URL中%00解码成16进制就是0x00。
抓包上传
上传php文件
抓包改文件后缀为.php%00
即可成功上传
lab 12、%00截断绕过(二)(POST)
源码审计
POST和GET传参的不同是,GET会自动解码,但POST不会对里面的数据自动解码,需要在Hex中修改。
抓包,将文件后缀php后面的a改为0x00
lab 13、图片马绕过
源码分析
相关函数
unpack()
: 从二进制字符串对数据进行解包,加了@是为了让报错不回显的。
图片马
什么是图片马
图片马:就是在图片中隐藏一句话木马。利用.htaccess等解析图片为PHP或者asp文件。达到执行图片内代码目的
如何制作图片马
copy 二次元.jpg/b + shell.php/a photo_shell.php
- b是指以二进制的方式合并复制文件,用于图像影音类文件
- a是指以ascii方式合并复制文件,用于文本类文件
上传成功即可
绕过非法
上传图片马就行
lab 14、getimagesize图片类型绕过
查看源码
相关函数
getimagesize() — 用于获取图像大小及相关信息,成功返回一个数组(返回图片宽度、图片高度、图片的类型、图片的尺寸),失败则返回 FALSE 并产生一条 E_WARNING 级的错误信息。
image_type_to_extension() — 根据指定的图像类型返回对应的后缀名。
stripos() — 查找字符串在另一字符串中第一次出现的位置(不区分大小写)。
制作看似正常的图片马
在cmd输入:
copy 1.png/b+1.txt 88.jpg
成功生成
同样也可以写个png文件
upload-labs-15 exif_imagetype()-图片马
源码分析
先了解一下exif_imagetype()作用:
exif_imagetype — 判断一个图像的类型
php_exif模块 — 通过使用 exif 扩展,可以操作图像元数据
exif_imagetype() — 获取图片类型
绕过方式
白名单 + exif_imagetype()函数
具体步骤和第13关相似
lab 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_ADDR.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格式的图片!";}else{//给新图片指定文件名srand(time());$newfilename = strval(rand()).".jpg";$newimagepath = $UPLOAD_ADDR.$newfilename;imagejpeg($im,$newimagepath);//显示二次渲染后的图片(使用用户上传图片生成的新图片)$img_path = $UPLOAD_ADDR.$newfilename;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格式的图片!";}else{//给新图片指定文件名srand(time());$newfilename = strval(rand()).".png";$newimagepath = $UPLOAD_ADDR.$newfilename;imagepng($im,$newimagepath);//显示二次渲染后的图片(使用用户上传图片生成的新图片)$img_path = $UPLOAD_ADDR.$newfilename;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格式的图片!";}else{//给新图片指定文件名srand(time());$newfilename = strval(rand()).".gif";$newimagepath = $UPLOAD_ADDR.$newfilename;imagegif($im,$newimagepath);//显示二次渲染后的图片(使用用户上传图片生成的新图片)$img_path = $UPLOAD_ADDR.$newfilename;unlink($target_path);$is_upload = true;}}else{$msg = "上传失败!";}}else{$msg = "只允许上传后缀为.jpg|.png|.gif的图片文件!";}
关键函数
- basename() — 返回路径中的文件名部分
- strrchr() — 查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符
- imagecreatefromjpeg() — 由文件或 URL 创建一个新图片
- srand() — 播下随机数发生器种子
- strval() — 获取变量的字符串值
- imagejpeg() — 输出图象到浏览器或文件
- unlink() — 删除文件
二次渲染
二次渲染:就是根据用户上传的图片,新生成一个图片,将原始图片删除,将新图片添加到数据库中。比如一些网站根据用户上传的头像生成大中小不同尺寸的图像。
查看源码:
$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_ADDR.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格式的图片!";}else{//给新图片指定文件名srand(time());$newfilename = strval(rand()).".jpg";$newimagepath = $UPLOAD_ADDR.$newfilename;imagejpeg($im,$newimagepath);//显示二次渲染后的图片(使用用户上传图片生成的新图片)$img_path = $UPLOAD_ADDR.$newfilename;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格式的图片!";}else{//给新图片指定文件名srand(time());$newfilename = strval(rand()).".png";$newimagepath = $UPLOAD_ADDR.$newfilename;imagepng($im,$newimagepath);//显示二次渲染后的图片(使用用户上传图片生成的新图片)$img_path = $UPLOAD_ADDR.$newfilename;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格式的图片!";}else{//给新图片指定文件名srand(time());$newfilename = strval(rand()).".gif";$newimagepath = $UPLOAD_ADDR.$newfilename;imagegif($im,$newimagepath);//显示二次渲染后的图片(使用用户上传图片生成的新图片)$img_path = $UPLOAD_ADDR.$newfilename;unlink($target_path);$is_upload = true;}}else{$msg = "上传失败!";}}else{$msg = "只允许上传后缀为.jpg|.png|.gif的图片文件!";}
}
相关函数
- basename() — 返回路径中的文件名部分
- strrchr() — 查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符
- imagecreatefromjpeg() — 由文件或 URL 创建一个新图片
- srand() — 播下随机数发生器种子
- strval() — 获取变量的字符串值
- imagejpeg() — 输出图象到浏览器或文件
- unlink() — 删除文件
- 这一部分的代码有个bug,就是只要我们上传的是图片木马就行,二次渲染并不会起作用,因为只要符合这两个条件if((KaTeX parse error: Expected 'EOF', got '&' at position 19: …eext == "png") &̲& (filetype==“image/png”)文件就会被上传。为了达到练习的效果我们还是当他二次渲染是起作用的。
检测方式
白名单 + 文件类型检测 + 上传成功之后对文件内容进行二次渲染
绕过方式
分析经过渲染的图片和原来的图片有什么不同,找到没有被渲染的部分将代码插入到其中即可
lab 17、
源码分析
$is_upload = false;
$msg = null;if(isset($_POST['submit'])){$ext_arr = array('jpg','png','gif');$file_name = $_FILES['upload_file']['name'];$temp_file = $_FILES['upload_file']['tmp_name'];$file_ext = substr($file_name,strrpos($file_name,".")+1);$upload_file = $UPLOAD_ADDR . '/' . $file_name;if(move_uploaded_file($temp_file, $upload_file)){if(in_array($file_ext,$ext_arr)){$img_path = $UPLOAD_ADDR . '/'. rand(10, 99).date("YmdHis").".".$file_ext;rename($upload_file, $img_path);$is_upload = true;}else{$msg = "只允许上传.jpg|.png|.gif类型文件!";unlink($upload_file);}}else{$msg = '上传失败!';}
}
上传的文件会被重命名,apache的解析漏洞无法利用。但是这里的bug是文件会先上传到服务器上,然后才会判断它的后缀名是否合法,不合法的话在从服务器上删除文件。
检测方式
白名单 + 文件重命名
绕过方式
竞争上传
上传木马文件用bp抓包
进入http://192.168.15.146/upload/trojan1.php目录下不断地刷新之后我们会发现上传成功了
labs-18 条件竞争
源码分析
//index.php
$is_upload = false;
$msg = null;
if (isset($_POST['submit']))
{require_once("./myupload.php");$imgFileName =time();$u = new MyUpload($_FILES['upload_file']['name'], $_FILES['upload_file']['tmp_name'], $_FILES['upload_file']['size'],$imgFileName);$status_code = $u->upload($UPLOAD_ADDR);switch ($status_code) {case 1:$is_upload = true;$img_path = $u->cls_upload_dir . $u->cls_file_rename_to;break;case 2:$msg = '文件已经被上传,但没有重命名。';break; case -1:$msg = '这个文件不能上传到服务器的临时文件存储目录。';break; case -2:$msg = '上传失败,上传目录不可写。';break; case -3:$msg = '上传失败,无法上传该类型文件。';break; case -4:$msg = '上传失败,上传的文件过大。';break; case -5:$msg = '上传失败,服务器已经存在相同名称文件。';break; case -6:$msg = '文件无法上传,文件不能复制到目标目录。';break; default:$msg = '未知错误!';break;}
}//myupload.php
class MyUpload{
......
......
...... var $cls_arr_ext_accepted = array(".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",".ppt",".html", ".xml", ".tiff", ".jpeg", ".png" );......
......
...... /** upload()**** Method to upload the file.** This is the only method to call outside the class.** @para String name of directory we upload to** @returns void**/function upload( $dir ){$ret = $this->isUploadedFile();if( $ret != 1 ){return $this->resultUpload( $ret );}$ret = $this->setDir( $dir );if( $ret != 1 ){return $this->resultUpload( $ret );}$ret = $this->checkExtension();if( $ret != 1 ){return $this->resultUpload( $ret );}$ret = $this->checkSize();if( $ret != 1 ){return $this->resultUpload( $ret ); }// if flag to check if the file exists is set to 1if( $this->cls_file_exists == 1 ){$ret = $this->checkFileExists();if( $ret != 1 ){return $this->resultUpload( $ret ); }}// if we are here, we are ready to move the file to destination$ret = $this->move();if( $ret != 1 ){return $this->resultUpload( $ret ); }// check if we need to rename the fileif( $this->cls_rename_file == 1 ){$ret = $this->renameFile();if( $ret != 1 ){return $this->resultUpload( $ret ); }}// if we are here, everything worked as planned :)return $this->resultUpload( "SUCCESS" );}
......
......
......
};
这题对文件后缀名做了白名单判断,然后会一步一步检查文件大小、文件是否存在等等,因此可以通过不断上传图片马,由于条件竞争可能来不及重命名,从而上传成功。
$img_path变量用户是可以通过POST提交的$_POST[‘save_name’]参数来控制的
检测方式
黑名单
绕过方式
大小写即可绕过
具体步骤
我们上传木马文件,将其将要保存的文件名改为upload-19.PHP,即可绕过黑名单检测
上传成功
解析成功
这篇关于我的创作纪念日【特别篇】--【文件上传漏洞(三)】-lab 11-lab19的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!