Upload-labs less1-20通关笔记
Upload-labs 通关笔记涵盖 Upload-labs 全部 20 关文件上传漏洞每关包含漏洞原理、源码分析、绕过步骤与修复方案。点击每关标题展开详细内容。 关卡目录Pass-01前端JS验证绕过漏洞原理仅在前端浏览器使用 JavaScript 校验文件后缀名服务器端未进行任何验证。前端代码对攻击者完全可见且可控。关键源码functioncheckFile(){varfiledocument.getElementById(upload_file).value;varextfile.substring(file.lastIndexOf(.)1).toLowerCase();if(ext!jpgext!pngext!gif){alert(只允许上传图片文件);returnfalse;}returntrue;}###**绕过步骤**1.准备PHP一句话木马 info.php?phpphpinfo();?2.方法一浏览器按F12→ 设置 → 勾选 Disable JavaScript直接上传.php 文件。3.方法二将 info.php 改名为 info.jpg上传时用 BurpSuite 抓包将 filenameinfo.jpg改回 filenameinfo.php放行。/detailsdetailssummarybPass-02只校验content-type/b/summary###**漏洞原理**后端仅检查HTTP请求头中的 Content-Type 字段未验证文件真实内容。Content-Type 由客户端发送可任意伪造。 ###**漏洞源码**phpif($_FILES[upload_file][type]!image/jpeg$_FILES[upload_file][type]!image/png$_FILES[upload_file][type]!image/gif){$msg只允许上传图片文件;}绕过步骤上传 PHP 文件BurpSuite 拦截请求。将请求头中的 Content-Type: application/octet-stream 修改为 Content-Type: image/jpeg。放行数据包上传成功。Pass-03黑名单-特殊后缀绕过漏洞原理黑名单禁止了 .php、.jsp、.asp 等常见动态脚本后缀但未禁止 .php3、.phtml、.php5 等同样能被 Apache 解析的后缀。关键源码$deny_extarray(.asp,.aspx,.php,.jsp);绕过步骤将木马文件命名为 info.php3 或 info.phtml。直接上传访问上传后的文件即可被解析执行。Pass-04黑名单-.htaccess绕过漏洞原理黑名单中未禁止 .htaccess 文件上传。.htaccess 是 Apache 的分布式配置文件攻击者可通过上传该文件将特定后缀如图片作为 PHP 脚本执行。关键源码$deny_extarray(.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绕过步骤创建一个 .htaccess 文件内容为AddType application/x-httpd-php .jpg上传该 .htaccess 文件。再上传一个包含 PHP 代码的 shell.jpg。访问 shell.jpg图片将以 PHP 方式执行。Pass-05黑名单-大小写绕过漏洞原理黑名单过滤时未对文件后缀进行统一大小写转换导致大小写混写可绕过。关键源码$deny_extarray(.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_extstrrchr($file_name,.);if(in_array($file_ext,$deny_ext)){...}// 未转换小写直接比较绕过步骤将木马文件后缀改为大小写混写如 info.Php、info.pHp。上传文件由于黑名单中是 .php 而上传的是 .Php匹配失败上传成功。Pass-06黑名单-空格绕过漏洞原理Windows 系统在保存文件时会自动去除文件名末尾的空格。黑名单过滤时未考虑此特性导致 info.php 末尾空格上传后实际变为 info.php。关键源码$deny_ext...// 同上if(in_array($file_ext,$deny_ext)){...}// 未对文件名进行 trim 处理绕过步骤上传文件用 BurpSuite 拦截。修改 filename“info.php” 为 filenameinfo.php 注意末尾加空格。放行文件上传后保存为 info.php。Pass-07黑名单-点号绕过漏洞原理Windows 系统在保存文件时会自动去除文件名末尾的点号 .。黑名单未过滤此情况。关键源码// 未使用 deldot() 或类似函数去除末尾点号if(in_array($file_ext,$deny_ext)){...}绕过步骤上传文件BurpSuite 拦截。修改 filename“info.php” 为 filename“info.php.”末尾加点。放行上传后文件名变为 info.php。Pass-08黑名单-::$DATA绕过漏洞原理Windows NTFS 文件系统支持文件流Alternate Data Streams在文件名后添加 ::$DATA 不会影响文件内容但可以绕过黑名单匹配。关键源码$deny_ext...// 同上if(in_array($file_ext,$deny_ext)){...}// 未过滤 ::$DATA绕过步骤上传文件BurpSuite 拦截。修改 filename“info.php” 为 filename“info.php::$DATA”。放行文件以 info.php 保存在服务器上。Pass-09黑名单-点空格点绕过漏洞原理综合利用了点号、空格的过滤逻辑缺陷。某些过滤函数只去除一次首尾特殊字符通过构造 info.php. . 可在处理后变为 info.php。关键源码$deny_ext...;$file_namedeldot($file_name);// 只去点不去空格$file_extstrrchr($file_name,.);// 未递归处理绕过步骤上传文件BurpSuite 拦截。修改 filename“info.php” 为 filename“info.php. .”。放行服务器处理后文件名变为 info.php。Pass-10黑名单-双写绕过漏洞原理黑名单过滤逻辑为将敏感后缀如 .php替换为空字符串且只执行一次。攻击者通过双写如 .pphphp使替换后仍保留一个完整后缀。关键源码$deny_extarray(.php,.php5,...);$file_extstr_ireplace($deny_ext,,$file_ext);// 替换一次绕过步骤将文件命名为 info.pphphp。上传后服务器将中间的 .php 替换为空结果为 info.php。Pass-11白名单-00截断(GET方式)漏洞原理PHP 底层基于 C 语言C 语言将 \0URL 编码为 %00视为字符串结束符。当上传路径通过 GET 参数传递时可在文件名后加入 %00 截断使后续的合法后缀被忽略。利用条件PHP 5.3.4且 magic_quotes_gpc Off。关键源码$img_path$_GET[save_path]./.$_FILES[upload_file][name];// 未对 save_path 进行安全处理绕过步骤上传 PHP 文件BurpSuite 拦截。找到 GET 参数 ?save_path…/upload/将其修改为 ?save_path…/upload/info.php%00。放行最终保存路径为 …/upload/info.php.jpg 等后续内容被截断忽略。Pass-12白名单-00截断(POST方式)漏洞原理与 Pass-11 相同利用 PHP 底层 C 语言将%00视为字符串结束符的特性。区别在于本关的保存路径通过 POST 请求体传递需在 BurpSuite 中对截断字符进行十六进制编辑。利用条件PHP 5.3.4且magic_quotes_gpc Off。关键源码$img_path$_POST[save_path]./.$_FILES[upload_file][name];// 未对 save_path 进行过滤绕过步骤上传 PHP 文件BurpSuite 拦截。在请求体中找到 save_path…/upload/在其末尾手动添加 info.php 和一个空格。· 示例save_path…/upload/info.php .jpg切换到 BurpSuite 的 Hex十六进制视图。找到刚刚添加的空格对应的十六进制值 20将其修改为 00。返回 Raw 视图可见 info.php 后出现一个方框字符代表 \0放行数据包。文件最终保存为 info.php后续 .jpg 被截断忽略。Pass-13图片马制作 文件包含漏洞利用漏洞原理本关对文件内容进行了读取要求文件头必须为图片格式但未对文件包含进行限制。攻击者将 PHP 代码嵌入真实图片中制作“图片马”上传后配合文件包含漏洞如 include执行代码。关键源码$infogetimagesize($_FILES[upload_file][tmp_name]);if($infofalse){$msg不是有效的图片文件;}// 仅验证文件头未阻止包含绕过步骤制作图片马Windows 命令行copy /b 1.jpg info.php shell.jpg· 1.jpg任意正常图片· info.php?php phpinfo(); ?· shell.jpg生成的图片马上传 shell.jpg通过校验。靶场通常提供一个文件包含漏洞页面如 include.php?file./upload/shell.jpg访问该 URL 即可执行 PHP 代码。Pass-14文件头校验 - getimagesize() 绕过漏洞原理后端使用 getimagesize() 函数读取文件头部信息来判断图片类型。该函数仅检查文件头几个字节攻击者可在 PHP 代码前添加合法图片文件头进行伪造。关键源码$infogetimagesize($_FILES[upload_file][tmp_name]);if(!$info){$msg文件不是图片;}绕过步骤创建一个文件 shell.php内容如下GIF89a ?php phpinfo(); ?· GIF89a 是 GIF 图片的标准文件头标识。直接上传 shell.php。getimagesize() 读取到 GIF89a 头认为文件合法放行上传。访问上传后的文件代码执行。Pass-15文件头校验 - exif_imagetype() 绕过漏洞原理本关使用 exif_imagetype() 函数校验文件头原理与 getimagesize() 完全相同同样可通过伪造文件头绕过。关键源码if(exif_imagetype($_FILES[upload_file][tmp_name])false){$msg文件不是图片;}绕过步骤同 Pass-14在 PHP 代码前添加 GIF89a 或 PNG 文件头 \x89PNG。上传文件通过校验。访问文件执行 PHP 代码。Pass-16二次渲染绕过漏洞原理服务器对用户上传的图片进行二次渲染重新生成图片原图中的恶意 PHP 代码极有可能被清除。绕过此机制需要找到渲染后文件内容不发生改变的区域如图片的注释区、尾部冗余数据区将 PHP 代码写入该区域。关键源码// 以 GIF 为例$imimagecreatefromgif($_FILES[upload_file][tmp_name]);imagegif($im,$upload_path);imagedestroy($im);// 代码被重新渲染非图片数据被丢弃绕过步骤准备对比工具找一个正常 GIF 图片上传后下载渲染后的版本用 010 Editor 等工具对比渲染前后未发生改变的字节区域。写入代码在 GIF 的头部 GIF89a 之后、第一个图像描述块之前的区域直接插入 ?php phpinfo(); ?。保存修改后的 GIF 文件并上传。渲染后该区域未被破坏访问上传文件PHP 代码执行。Pass-17条件竞争 - 先保存后校验漏洞原理服务器处理逻辑为先将上传的文件临时保存到目标目录然后进行后缀名/文件头校验。若不合法则删除文件。从保存到删除之间存在极短的时间窗口攻击者通过高并发请求在该窗口内访问文件即可执行恶意代码。关键源码move_uploaded_file($temp_file,$upload_path);if(!check_file($upload_path)){unlink($upload_path);// 不合法则删除}绕过步骤bp一直发包上传PHP抢时间差Pass-18条件竞争 - 重命名时间窗口漏洞原理与 Pass-17 类似区别在于文件上传后先按白名单规则重命名再进行校验。若文件名被修改为合法图片后缀攻击者可利用重命名完成到校验删除之间的时间窗口访问原始恶意文件。关键源码$new_namemd5($file_name)..jpg;move_uploaded_file($temp_file,$upload_path.$new_name);if(!check_file($upload_path.$new_name)){unlink($upload_path.$new_name);}绕过步骤竞争思路同上但需注意文件被重命名为 .jpg直接访问不会解析 PHP。Pass-19条件竞争 Apache 解析漏洞漏洞原理综合利用条件竞争与 Apache 解析漏洞如文件名 shell.php.jpg 在特定配置下被当作 PHP 执行。服务器先重命名文件为 .jpg但校验不通过时会删除。攻击者在删除前访问文件若 Apache 存在解析缺陷即可执行代码。关键源码逻辑类似 Pass-18文件名被强制添加 .jpg 后缀。绕过步骤上传文件 shell.php服务器重命名为 shell.php.jpg。发起高并发请求访问 shell.php.jpg。若 Apache 配置了 AddHandler application/x-httpd-php .php 且对后缀解析不严格如存在 .php.xxx 解析漏洞shell.php.jpg 可能被当作 PHP 执行。Pass-20数组绕过漏洞漏洞原理本关是一个综合关卡其最核心的漏洞在于对 $file 变量是数组还是字符串的不同处理逻辑。代码在处理 save_name 时会判断其是否为数组。如果不是才按点号拆分成数组如果是则直接使用。攻击者可以直接提交一个精心构造的数组作为 save_name利用 end()、reset() 和 count() 等函数处理数组时的特性构造出合法的后缀名和恶意文件路径。关键源码分析// 关键代码逻辑$fileempty($_POST[save_name])?$_FILES[upload_file][name]:$_POST[save_name];if(!is_array($file)){$fileexplode(.,strtolower($file));// 不是数组才拆分}$extend($file);// 取数组最后一个元素作为后缀$allow_suffixarray(jpg,png,gif);if(!in_array($ext,$allow_suffix)){$msg禁止上传该后缀文件!;}else{// $file[count($file) - 1] 获取的是后缀$file_namereset($file)...$file[count($file)-1];// ... 保存文件}绕过步骤准备一个 PHP 一句话木马 test.php。上传时用 BurpSuite 拦截请求修改 Content-Type 为 image/jpeg 等合法类型。最关键的一步将 POST 参数 save_name 的值修改为一个数组例如· save_name[0]test.phpsave_name[2]jpg这样构造后file就是一个数组。end(file 就是一个数组。end(file就是一个数组。end(file) 取到的是 jpg通过了白名单。但 reset($file) 取到的是 test.php而file[count(file[count(file[count(file) - 1] 取到的是 jpg。由于 $file[1] 未定义最终拼接出的文件名 $file_name 可能是 test.php.jpg。由于解析漏洞该文件在某些环境下仍可被当作PHP执行。