upload-labs靶场通关-01~10

文件上传漏洞通常发生在程序设计中,由于对用户上传文件的处理不当或存在缺陷,导致用户能够绕过校验限制,向服务器上传具有执行能力的动态脚本文件。这些文件可能包括木马程序、病毒、恶意脚本或WebShell等。尽管文件上传本身并非问题所在,但服务器对上传文件的处理和解释方式不当,可能会引发严重后果。

upload-labs靶场主要用于渗透测试和CTF比赛中的文件上传漏洞训练。它通过模拟真实的文件上传场景,帮助用户理解文件上传漏洞的原理、危害以及如何绕过各种检测机制。靶场包含20个关卡,每个关卡都有不同的挑战,从基本的文件类型检测到复杂的黑名单和白名单绕过,逐步提升难度,帮助用户逐步提升对文件上传漏洞的理解和实战能力‌。

Pass-01

  • 我们需要先确定上传上去的路径
  • 如何限制我们上传的问题

信息收集测试

1 使用info.php文件上传查看情况,结果有个弹窗提示无法上传,另外,这个时候我们没有拦截到任何发送到服务器端的请求,说明,此监测是客户端监测;

2.使用符合条件的文件上传,如下面,上传正确的图片后,页面上有反显,那么我们就能获取到访问图片的路径,因为我们不仅要上传文件上去,还要能访问。

3.通过chrome的开发者工具既能查看到图片访问的路径,这边上传上去的文件连名字都没有修改,那么我们要访问我们上传的文件路径就是http://ip:端口/Pass-01/upload/文件名

4.由于这个是客户端限制,我们可以直接通过bp向服务器端发送请求,在这之前我们要先拦截下正常的请求,这边image.png是上传的文件名字,而下面啊那些就是这个图片的信息,由于是图片,所以这边看上去像乱码。

分析

已知条件

  • 已经知道能访问的路径
  • 文件名没有修改

绕过方案:

把我们的info.php文件改成info.png,然后通过bp拦截,把文件名改成info.php,既能访问到这个文件,路径地址是:

http://ip:端口/upload/info.php

实施

1.修改文件名

2.开启bp的拦截

3.发起请求并拦截,第二部分是文件的内容

4.发送到repeat中,并修改文件名

5.访问地址

bash 复制代码
[http://ip](http://ip/):端口/upload/info.php

总结

文件要能上传,传完要能访问,还要能解析执行!

Pass-02

信息收集测试

1.使用info.php文件,异常提示文件类型不正确,并且有发送请求到服务端,说明是服务器端校验;

复制代码

2.如果是服务器端校验,那么我们就需要获取到服务器端的代码了,我们这边就假设我们已经能获取到服务器端的代码

ini 复制代码
```
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name']            
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '文件类型不正确,请重新上传!';
        }
    } else {
        $msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';
    }
}
```

3.上传一个正常的页面,查看反显的路径,路径与Pass-01一样:http://ip:端口/Pass-01/upload/文件名

分析

这边的判断主要是根据请求过来的Content-Type的值进行判断是否图片,如果我们直接这个值改成其中一个"image/jpeg",其他的偶不变,既能绕过,注意这边的没有修改上传的文件名字。

已知条件:

  • 已经知道能访问的路径
  • 文件名没有修改
  • 文件校验的策略

绕过方案:

通过bp修改Content-Type的值为"image/jpeg"

实施

1.拦截请求或者让请求正常通过后,发送到repeat中;

2.在repeat中修改Content-Type,并发送请求;

3.验证,能正常访问:http://ip:端口/upload/info.php

总结

服务器端的校验主要根据具体的校验方案来进行突破,这边主要是对Content-Type校验的绕过方式。

Pass-03

信息收集测试

1.使用info.php文件,异常提示"提示:不允许上传.asp,.aspx,.php,.jsp后缀文件!",并且有发送请求到服务端,说明是服务器端校验;

2.正常图片,反显图片的名称与源文件不一致,说明文件名有做了修改;

3.查看源码:

ini 复制代码
```
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        $deny_ext = array('.asp','.aspx','.php','.jsp');
        $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.'/'.date("YmdHis").rand(1000,9999).$file_ext;            
            if (move_uploaded_file($temp_file,$img_path)) {
                 $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';
        }
    } else {
        $msg = UPLOAD_PATH . 
        '文件夹不存在,请手工创建!';
    }
}
```

#### 分析与实施

分析代码,黑名单只有'.php',而apache识别为php脚本文件的扩展名有:.php、 .php3、.php4、 .php5,另外index.php.aaa也是能识别的,但是代码中会把.php删掉,所以使用php3|.php4| .php5。,所以,我把后缀改成php3上传既,并验证如下图,能正常访问

Apache HTTP服务器默认情况下支持解析以下常见的文件扩展名: ![image-20250424180334462]()

apache后缀识别原理:

复制代码
Apache对文件后缀名的识别是从后向前进行匹配的,以单个.作为分隔符。当遇到未知的文件后缀名时,会继续向前匹配,直到遇到可以识别的后缀名为止。

总结

这题主要让价了解apache解析成php脚本的扩展名有哪些,apache解析原理。

Pass-04

信息收集与分析

根据之前的经验,我们直接看源码

ini 复制代码
$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.'/'.date("YmdHis").rand(1000,9999).$file_ext;
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '此文件不允许上传!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}
​

这回增加了更多的黑名单,03中的方法应该是不行了。我们可以利用apache中.htaccess文件的特性,把图片解析成php。其中.htaccess(Hypertext Access)是 Apache 服务器的一个分布式配置文件,可以覆盖主配置文件的设置,无需重启服务器即可生效(需要管理员级别权限修改的httpd.conf文件修改后需要重启Apach服务器)它主要用于目录级的配置,是 Web 安全、URL 重写和服务器优化的重要工具。

实施

  1. 新增一个文件.htaccess,添加下面代码,

    bash 复制代码
    <FilesMatch "loudong.jpg">
    SetHandler application/x-httpd-php
    </FilesMatch>  

2.然后在把info.php改成loudong.jpg文件

3.注意这边上传后的文件名没有改,我们就按照下面回显的路径去访问,访问地址是:http://ip:端口/upload/loudong.jpg,既能看到php的info信息

总结

此题主要的知识点是.htaccess文件。

Pass-05

信息收集与分析

查看了代码后,与04差不多,我们就试试使用04的代码测试下,得到下面的结果:

只能在分析下代码,与04差不多,黑名单中添加了".htaccess",但是没有转换成小写,那么我们PHP就能绕过。

ini 复制代码
$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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",".htaccess");
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);//删除文件名末尾的点
        $file_ext = strrchr($file_name, '.');
        $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.'/'.date("YmdHis").rand(1000,9999).$file_ext;
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '此文件类型不允许上传!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}
​

实施

1.修改后缀php改成PHP并上传

2.访问对应的地址

总结

根据具体的代码制定绕过计划

Pass-06

信息收集与分析

与05比较,少了去掉收尾空格的代码片段。

ini 复制代码
$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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",".htaccess");
        $file_name = $_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
        
        if (!in_array($file_ext, $deny_ext)) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
            if (move_uploaded_file($temp_file,$img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '此文件不允许上传';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}
​

通过上传的时候通过bp添加空格,在校验文件名是否合格的时候,能绕过验证,并且系统保存末尾有空格的文件名称时,会自动把末尾的空格去掉。

实施

总结

保存的特性系统的特性,把末尾的空格去掉。

Pass-07

信息收集与分析

与06比较缺少了删除末尾的"."的代码段,如果我们再末尾添加一个.那么 <math xmlns="http://www.w3.org/1998/Math/MathML"> f i l e e x t = s t r r c h r ( file_ext = strrchr( </math>fileext=strrchr(file_name, '.'); 中返回的就是".",所以

ini 复制代码
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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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",".htaccess");
        $file_name = trim($_FILES['upload_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 . '文件夹不存在,请手工创建!';
    }
}

实施

总结

针对操作系统在后面加.与空格,保存成文件后,都会自动把.与空格去掉

Pass-08

信息收集与分析

代码中缺少对":: <math xmlns="http://www.w3.org/1998/Math/MathML"> D A T A "的处理,在 W i n d o w s 中会把 : : DATA"的处理,在Windows中会把:: </math>DATA"的处理,在Windows中会把::DATA 之后的数据当成文件流处理,不会检测后 缀名,且保持:: <math xmlns="http://www.w3.org/1998/Math/MathML"> D A T A 之前的文件名,类似之前" . "与空格的功效,所以在 b p 中使用 r e p e a t 发送到服务器前把文件名中添加 : : DATA 之前的文件名,类似之前"."与空格的功效,所以在bp中使用repeat发送到服务器前把文件名中添加:: </math>DATA之前的文件名,类似之前"."与空格的功效,所以在bp中使用repeat发送到服务器前把文件名中添加::DATA即可。

ini 复制代码
$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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",".htaccess");
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);//删除文件名末尾的点
        $file_ext = strrchr($file_name, '.');
        $file_ext = strtolower($file_ext); //转换为小写
        $file_ext = trim($file_ext); //首尾去空
        
        if (!in_array($file_ext, $deny_ext)) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '此文件类型不允许上传!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}
​

实施

把请求发送到repeat中后,修改filename,添加::$DATA

访问地址http://IP:端口/upload/info.php

总结

在windows操作系统中添加::#DATA作为文件名末尾,操作系统会忽略。

Pass-09

信息收集与分析

代码:

ini 复制代码
$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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",".htaccess");
        $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 . '文件夹不存在,请手工创建!';
    }
}
​

根据代码的验证过程,只要 <math xmlns="http://www.w3.org/1998/Math/MathML"> f i l e e x t 中不是黑名单的字符串就行,由于" . "、 " 空格 " 、" : : file_ext中不是黑名单的字符串就行,由于"."、"空格"、":: </math>fileext中不是黑名单的字符串就行,由于"."、"空格"、"::DATA"三个保存时,对最终落地到操作系统的文件名没有影响,那么我们通过这个三个组合添加到我们的文件名后,由于"::$DATA"是整个替换,所以用不了,那么就剩"."与"空格"了

ini 复制代码
 $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA

逐句分析:

ini 复制代码
$file_name = trim($_FILES['upload_file']['name']);

头尾去空格,那么我们文件名最后一个必须是"."

ini 复制代码
$file_name = deldot($file_name);//删除文件名末尾的点

deldot此函数删除末尾的点,一直删除到没有为止,如果有两个".",那么会删除两个,那么我们末尾的字符串是空格+.了:" ."

ini 复制代码
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空

前面两个对我们没有影响,最后一个取首位空格的函数,我们的倒数第二个空格又没有了,那么我们可以倒数三个在加上一个".",完成的文件名为:

info.php. .

实施

总结

需要对代码进行逐条分析,找到逻辑的漏洞。

Pass-10

信息收集与分析

代码:

ini 复制代码
$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 . '文件夹不存在,请手工创建!';
    }
}

这段代码的核心是 <math xmlns="http://www.w3.org/1998/Math/MathML"> f i l e n a m e = s t r i r e p l a c e ( file_name = str_ireplace( </math>filename=strireplace(deny_ext,"", $file_name);,它吧所有的黑名单中的关键字全部换成空格,文件都能上传,但是上传后,php的文件名被去掉了,那么也就无法运行了。

注意上面的代码知会执行一次,如果我们再php中插入一个php字符窜,那么一个php被替换成"",剩下的还是php,如pphphp、phphpp(这个不行,替换完会变成hpp),综上,只能是pphphp了。

实施

总结

根据具体的代码具体分析,分析出其中的逻辑漏洞。

相关推荐
用户35218024547541 分钟前
Burp Suite-使用本地文件作为响应内容
安全·逆向
G扇子1 小时前
深入解析XSS攻击:从原理到防御的全方位指南
前端·安全
w23617346011 小时前
HTTP vs HTTPS:传输协议的安全演进与核心差异
安全·http·https
kaamelai2 小时前
Kaamel视角下的MCP安全最佳实践
大数据·人工智能·安全
浩浩测试一下2 小时前
网络安全实战指南:从安全巡检到权限维持的应急响应与木马查杀全(命令查收表)
linux·安全·web安全·ubuntu·网络安全·负载均衡·安全架构
小白64023 小时前
需要掌握的前端安全概念以及实操
前端·安全
YJQ99674 小时前
Nginx防盗链及HTTPS:保护网站内容安全与加密传输
nginx·安全·https
AORO_BEIDOU5 小时前
遨游三防|30200mAh、双露营灯三防平板,见证堆料天花板
大数据·科技·安全·智能手机·电脑·信息与通信
Suckerbin5 小时前
第十三章-PHP MySQL扩展
mysql·安全·php