为什么上传一张“图片”最后却能控制服务器——文件上传漏洞入门学习最近学 Web 安全的时候学到了一个很经典的漏洞文件上传漏洞Upload Vulnerability刚开始看到这个名字的时候我其实有点懵。上传文件不是很正常吗头像、图片、附件、简历……几乎所有网站都有上传功能。那它为什么会变成漏洞后来真正理解之后我发现文件上传漏洞本质其实是“服务器错误地执行了用户上传的文件”。今天这篇文章就用我的逻辑和语言聊聊我最近对文件上传漏洞的理解。一、正常的网站为什么需要文件上传其实这个功能太常见了。比如上传头像上传图片上传 PDF上传 Word 文档上传简历上传视频这些都属于用户把文件传给服务器比如你换微信头像。本质上其实就是POST /upload浏览器把文件名文件内容文件类型一起发送给服务器。服务器收到之后正常来说到这里都没有问题。问题出现在“服务器怎么检查这个文件”。二、文件上传漏洞到底是什么网站把“用户上传的文件”当成了“程序”执行。这就危险了。比如正常用户上传1.jpg 没问题。但攻击者上传?php phpinfo(); ?如果服务器把它当PHP 执行了。那访问/upload/test.php页面就会执行代码。这时候已经不是“上传文件”了。而是用户开始在服务器上运行代码。这个危险程度其实非常高。严重情况下可以控制网站获取数据库读取服务器文件拿到 WebShell甚至继续入侵内网很多真实攻击最开始就是一个文件上传漏洞。三、服务器为什么会执行上传的文件这里是我最近真正想明白的地方。以前我一直以为“上传成功 漏洞成功”。后来发现根本不是。真正关键的是服务器“怎么解析这个文件”。比如test.php 为什么它危险因为服务器看到 .php 后缀后。会认为这是 PHP 程序于是交给 PHP 解析器执行。而1.jpg服务器会认为这是图片所以只会展示不会执行。因此文件上传漏洞的本质其实是“解析问题”。这句话非常重要。四、网站一般怎么防御正常网站肯定不会允许你直接上传 .php。所以通常会做检查。比如1. 检查后缀名允许.jpg.png.gif禁止.php.jsp.asp这是最基础的。2. 检查 Content-Type比如Content-Type: image/jpeg看起来像图片。但这里其实可以伪造。所以单独依赖这个并不安全。3. 检查文件头比如JPG 文件开头FF D8 FFPNG 文件开头89 50 4E 47服务器会看看“你到底是不是真图片”。4. 重新生成图片这个是更安全的方式。有些网站会重新压缩重新绘制图片这样即使你藏了恶意代码,也可能被“洗掉”。5.环境加固禁用危险函数及时更新服务器补丁阻断恶意文件执行条件给大家看看真实环境下的包里面包含的这些内容五、为什么还会出现漏洞因为很多网站检查做得不完整。比如只检查文件名。攻击者就可能1.php.jpg或者1.PHp甚至1.php%00.jpg不同服务器、不同环境、不同解析规则可能都会导致绕过。这里也是文件上传真正复杂的地方。因为漏洞很多时候不是代码本身而是服务器环境导致的。比如ApacheNginxIIS解析方式都可能不同。5.1任意文件的绕过方式请在合法授权的靶机环境使用A.黑名单1.双写绕过通过重复写入被过滤的后缀如 “php” 被拦截时用 “pphphp”过滤后剩余 “php”绕过简单的字符串替换校验。2.大小写绕过利用服务器对大小写不敏感的特性如 “PhP”“pHp”避开对 “php” 等小写后缀的检测。3.空格绕过在文件名后添加空格如 “shell.php”部分校验机制会忽略空格而服务器保存时可能自动截断空格导致恶意文件被解析。4.点绕过在文件名中加入多个点如 “shell.php.”“shell.php...”绕过对后缀长度或格式的简单校验服务器可能仅识别最后一个点前的内容。5.变形绕过使用脚本引擎支持的其他后缀如 php3、pht、phar 等或修改文件 MIME 类型如将 php 文件伪装成 text/plain绕过对白名单后缀的检测。6.特殊符号绕过利用 “::$DATA”Windows 系统使服务器忽略后缀后的内容如 “shell.php::$DATA” 被当作 “shell.php” 解析。7..htaccess 文件攻击上传恶意.htaccess 文件修改服务器配置如将.jpg 文件解析为 php使原本合法的文件类型被当作脚本执行。8.分步上传绕过先上传 “php:.jpg” 等混合后缀文件再上传 “.” 等文件触发服务器解析漏洞使恶意脚本被执行。B.白名单1.MIME 类型篡改白名单若仅校验 HTTP 请求中的 Content-Type 字段如限制为 image/jpeg攻击者可通过抓包工具将恶意文件如.php的 Content-Type 改为白名单内类型直接绕过校验。2.特殊符号截断利用 %00URL 空字符、0x00二进制空字符等截断符构造 “shell.php%00.jpg” 这类文件名服务器在处理时可能忽略截断符后的内容将文件识别为.php 并解析执行。六、我现在终于理解 WebShell 是什么了以前经常听别人说“传个一句话木马”但我一直没真正理解现在终于懂了。本质其实就是上传一个能被服务器执行的脚本文件。比如?php eval($_POST[cmd]); ?如果服务器执行它。攻击者就能远程控制网站。当然这里只是学习原理。真正环境中一定不能乱测试七、文件上传漏洞最重要的不是“技巧”我现在感觉很多人刚学文件上传。特别喜欢记双写绕过大小写绕过MIME 绕过图片马但其实最重要的是理解“服务器为什么会执行文件”这个才是核心。因为你真正理解解析逻辑之后。后面的文件包含命令执行RCE中间件漏洞会突然通很多。八、总结今天学文件上传漏洞之后。我最大的感受是Web 安全很多时候不是“黑客魔法”而是“程序错误地信任了用户输入”。而文件上传漏洞。本质其实就是这个阶段开始能感觉到 Web 安全开始越来越有意思了后面会发一些各种漏洞的打靶场教程想学的小伙伴可以关注一下后续内容哦