upload-labs全通关
upload-labs pass-01


直接上传一句话木马貌似不行,尝试抓包看看

发现全是get请求抓不到post传参上传一句话木马的包,合理猜测是不是前段验证,F12禁用JavaScript验证试试看

可以看到成功上传并且返回了图片

使用phpinfo()命令发现一句话木马成功上传
同理,是不是我们上传一个图片(此时通过了前段白名单验证是可以抓到包的)再抓包,修改图片内容为一句话木马也可行?

返回了上传文件路径,确实可行(单纯上传一个图片不修改后缀为php可是不可以执行命令的哦)

upload-labs pass-02

这次直接上传一句话木马并且禁止JavaScript验证也不行了,上传一个图片试试

看来图片可以上传

像上一道题一样上传时抓包再修改文件内容后缀,成功了

那能不能上传一句话木马然后修改文件类型呢

将content-type修改为image/jpeg、image/png、image/gif中的任何一种


成功了
upload-labs pass-03

直接上传一句话木马告诉我提示:不允许上传.asp,.aspx,.php,.jsp后缀文件!
这次哪怕开启禁用JavaScript验证也不行,这次的验证不是简单的前段验证了,猜测是检测后缀,这时我们可以使用phtml文件
通常,在嵌入了php脚本的html中,使用 phtml作为后缀名;
完全是php写的,则使用php作为后缀名。
这两种文件,web服务器都会用php解释器进行解析。

修改后缀后为phtml后,可以看到返回上传后的文件路径

upload-labs pass-04

这次也不说什么被过滤了,就告诉你不能上传,看看源码
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //收尾去空
if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '此文件不允许上传!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
可以看到基本所有的大小写绕过上面的全给你ban了,不是哥们,才第四关就ban这么多绕过?
当然还有办法,可以看到这里并没有禁止上传.htaccess文件,那就可以试试看
二、原理
原理:.htaccess文件(或者"分布式配置文件"),全称是Hypertext Access(超文本入口)。
提供了针对目录改变配置的方法,
即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。
作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。
简而言之我们可以撰写.htaccess文件的内容来使我们上传的文件能够被作为php文件解析,题目又要求我们上传图片,那我们就可以先上传.htaccess文件再上传图片马
<IfModule mime_module>
SetHandler application/x-httpd-php #在当前目录下,所有文件都会被解析成php代码执行
</IfModule>



图片马上传成功,

upload-labs pass-05

跟前面没有对后缀进行过滤的源码比较发现少了个转化为小写,那就尝试一下Php(至于为什么不试试pHp啥的,因为都被过滤了)

成功上传


upload-labs pass-06

可以看到源码少了个首尾去空,猜测在后缀前面或者后面加上空格即可绕过,开始尝试(注意要在抓取的数据包里面进行修改,不然windows重命名是会自动给你去掉空格的)

成功上传了但是一直因为windows会自动删空格导致我无法使用phpinfo()命令,很破防,哪位高人要是成功了辛苦在评论区吱一声
upload-labs pass-07

源码显示少了个删除文件名末尾的点,猜测在php文件名后加上一个.即可绕过
直接在windows里面重新命名在后缀最后加个点会被直接删除,这下又得在数据包里面改了


成功绕过
upload-labs pass-08

查看源码,发现少了去除::$DATA,可以在文件名后加上以进行绕过
补充知识:php在window的时候如果文件名+"::$DATA"会把::$DATA之后的数据当成文件流处理,
不会检测后缀名,且保持"::$DATA"之前的文件名 他的目的就是不检查后缀名。

不是哥们,windows的文件名后缀不能包括诸如:这样的字符,又只能在数据包里面改了

欧克,也是成功上传了
upload-labs pass-09

其实仔细对比会发现和第四关的源码基本上一模一样,但是第四关没有过滤.htaccess文件,这里他是把.htaccess文件给过滤了的,那该怎么办呢
这里发现既删除了文件名末尾的点还首尾去空,这样我们可以再php后缀后面加上点 空格 点
:::info
补充知识:deldot()函数从后向前检测,当检测到末尾的第一个点时会继续它的检测,但是遇到空格会停下来,而php后面的点会被windows自动视为空
:::
同样,在抓取的数据包中修改后缀


upload-labs pass-10
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = str_ireplace($deny_ext,"", $file_name);
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
可以看到黑名单很长但是没有大小写的过滤,那就试一下大小写

上传成功了但是后缀没了,估计有函数会检测上传的文件名中是否包含php,有的话直接去除(大小写一样过滤),这样的话我们就利用嵌套,在php里面再套一个php

成功了,再看看phpinfo();

upload-labs pass-11
$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类型文件!";
}
}
以上就是该题的源码,最关键的代码如下
:::info
$ext_arr = array('jpg','png','gif');//说明本题只允许上传.jpg,.png,.gif后缀文件
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
//这里的strrpos结合参数应该是查找上传的文件名中最后一个点出现的位置,+1是为了跳过'.'
//substr表示在上传文件名中分割出.之后的东西,也就是拓展名
:::
如果是白名单检测的话,我们可以采用00截断绕过。00截断利用的是php的一个漏洞。在 php<5.3.4 版本中,存储文件时处理文件名的函数认为0x00是终止符。于是在存储文件的时候,当函数读到 0x00(%00) 时,会认为文件已经结束。
例如:我们上传 1.php%00.jpg 时,首先后缀名是合法的jpg格式,可以绕过前端的检测。上传到后端后,后端判断文件名后缀的函数会认为其是一个.jpg格式的文件,可以躲过白名单检测。但是在保存文件时,保存文件时处理文件名的函数在遇到%00字符认为这是终止符,于是丢弃后面的 .jpg,于是我们上传的 1.php%00.jpg 文件最终会被写入 1.php 文件中并存储在服务端。
综上所述,我们先上传一个一句话木马php文件,然后再改后缀

然后再访问返回的文件路径,即可获取敏感信息
upload-labs pass-12
$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 = $_POST['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类型文件!";
}
}

和上一道题一样的源码和提示

不同的是这一次路径是post传参上去的,这里不得不提POST传参的话不会像GET传参那样自动对%00进行url解码,所以我们可以
:::info
对%00进行解码或在16进制中修改,POST不会像GET那样对%00进行自动解码。
:::
原因
为什么 POST 传参不会自动对 %00 进行 URL 编码?
GET 参数在 URL 中,需要符合 URL 规范,浏览器通常会自动进行 URL 编码,以防止 URL 被截断或解析错误。
POST 的数据在请求体中,并不会影响 URL 解析,因此浏览器或客户端不会主动进行编码,而是按照开发者提供的数据原样发送。
POST 传参的编码依赖于 Content-Type,不同的 Content-Type 处理方式不同:
application/x-www-form-urlencoded 需要手动编码,服务器会解析 key=value 形式的数据。
application/json 不需要 URL 编码,而是以 JSON 格式发送,例如:
json
复制
编辑
{"name": "John", "message": "Hello"}
multipart/form-data 直接发送二进制数据,不进行 URL 编码
upload-labs pass-13

这一关就开始涉及图片马了,这里我想直接修改一句话木马文件为jpg看能不能成功,但是源码里面写了会检查图片的前两个字节
补充:
Png图片文件包括8字节:89 50 4E 47 0D 0A 1A 0A。即为 .PNG
Jpg图片文件包括2字节:FF D8。
Gif图片文件包括6字节:47 49 46 38 39|37 61 。即为 GIF89(7)a。
Bmp图片文件包括2字节:42 4D。即为 BM
图片马制作:
在cmd里执行 **copy logo.jpg/b+test.php/a test.jpg**
#logo.jpg为任意图片;test.php 插入的木马文件;test.jpg 生成的图片木马
转载自csdn
直接修改php文件是不能的,所以还是老老实实的用cmd制作图片马吧

制作完以后上传图片马

点击黄色的文件包含漏洞

利用get传参访问上传的图片马即可,位置的话就在抓包软件里面看


upload-labs pass-14
function isImage($filename){
$types = '.jpeg|.png|.gif';
if(file_exists($filename)){
$info = getimagesize($filename);
$ext = image_type_to_extension($info[2]);
if(stripos($types,$ext)>=0){
return $ext;
}else{
return false;
}
}else{
return false;
}
}
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$temp_file = $_FILES['upload_file']['tmp_name'];
$res = isImage($temp_file);
if(!$res){
$msg = "文件未知,上传失败!";
}else{
$img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").$res;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = "上传出错!";
}
}
}
源码里面可以看到不仅检查了图片文件前两位,还使用了getimagesize函数
getimagesize() 函数用于获取图像大小及相关信息,成功返回一个数组,失败则返回 FALSE 并产生一条 E_WARNING 级的错误信息。
主要是针对*.php直接更改文件后缀为图片后缀,上一题创建的图片马仍然可以使用。
这边仍然使用正常图片马也可以完成之前操作
upload-labs pass-15

function isImage($filename){
//需要开启php_exif模块
$image_type = exif_imagetype($filename);
switch ($image_type) {
case IMAGETYPE_GIF:
return "gif";
break;
case IMAGETYPE_JPEG:
return "jpg";
break;
case IMAGETYPE_PNG:
return "png";
break;
default:
return false;
break;
}
}
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$temp_file = $_FILES['upload_file']['tmp_name'];
$res = isImage($temp_file);
if(!$res){
$msg = "文件未知,上传失败!";
}else{
$img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$res;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = "上传出错!";
}
}
}
这一关使用了一个exif_imagetype函数,第一次见上网查了一下
exif_imagetype() 读取一个图像的第一个字节并检查其签名。如果发现了恰当的签名则返回一个对应的常量,否则返回 FALSE。返回值跟getimagesize() 返回的数组中的索引 2 的值是一样的,但exif_imagetype函数快得多。
用之前的图片马依然可以绕过
upload-labs pass-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的图片文件!";
}
}
这一关考的就是二次渲染,会把你上传后的图片重新渲染一遍然后返回再上传,这样的话辛辛苦苦写在图片里的一句话木马就会消失不见,目的就是要防止渲染以后去马
但是本题貌似有点问题,上传jpg以后服务器报错,有问题
本题可以参考以下大佬的wp

gif图片可以正常上传,我们试试gif的二次渲染

将上传后的gif下载后和原来写了马的gif一起放入010editor中对比


发现写入的马真的被删了
关于绕过gif的二次渲染,我们只需要找到渲染前后没有变化的位置,然后将php代码写进去,就可以成功上传带有php代码的图片了
使用010 editor的工具,再点击比较

可以看到,黄色得到部分里面就是两个gif中相同的部分,在黄色部分写入马即可


成功执行


文件上传靶场
浙公网安备 33010602011771号