上传功能本身没问题,文件问题出在服务器太信任用户了。上传
你打开一个招聘网站,漏洞理上传简历。文件浏览器把文件塞进HTTP请求的上传body里,服务器收到后存到某个目录,漏洞理然后返回一个链接。文件整个过程看起来天经地义。上传但如果服务器没有检查你传的漏洞理到底是什么文件,你传的文件就不是简历了——你传的是一段PHP代码,改了个后缀叫
resume.php。上传服务器照单全收,漏洞理存进了Web目录。文件接下来你只需要访问https://example.com/uploads/resume.php,上传这段代码就在服务器上跑起来了。漏洞理这就是文件上传漏洞最朴素的样子。关键点在于:服务器判断文件类型的方式,往往比你想的粗糙得多。
很多开发者只看
Content-Type。浏览器上传文件时会带一个MIME类型,比如图片是image/jpeg,PDF是application/pdf。但这个字段是客户端发的,Burp Suite一抓一改,image/jpeg秒变application/x-php,或者反过来。服务器如果只信这个,等于把门禁卡交给访客自己填。稍微好一点的做法是检查后缀名。黑名单禁掉
.php、.jsp、.asp。但黑名单这东西天生有漏网之鱼。PHP不止.php能跑,.php3、.php5、.phtml在某些配置下照样解析。Apache的mod_mime模块甚至允许.php.jpg这种双后缀按PHP执行,取决于AddHandler怎么写。Windows环境下还有shell.php::$DATA这种NTFS数据流绕过,后缀检查直接失效。白名单看起来靠谱些——只允许
.jpg、.png、.gif。但白名单也有自己的坑。比如你允许.htaccess被上传(有些场景下确实需要),攻击者传一个.htaccess进去,内容写AddType application/x-httpd-php .jpg,然后传一个shell.jpg。服务器一看后缀是jpg,放行。但Apache读了.htaccess之后,把jpg当PHP解析了。白名单没拦住,因为.htaccess本身不在拦截范围内。还有一个经常被忽略的维度:文件内容检测。有些系统会读文件头几个字节,看是不是
FF D8 FF(JPEG的magic bytes)。这招能挡住大部分直接传webshell的情况,但挡不住图片马。攻击者把PHP代码嵌在正常图片的EXIF字段或者注释段里,文件头合法,内容检测通过。然后配合文件包含漏洞或者解析漏洞,让这段代码被执行。单独一个图片马上传上去没事,但一旦和LFI(本地文件包含)组合,杀伤力就出来了。我见过一个真实案例。某CMS的头像上传功能,前端用JS限制了只能选图片,后端检查了
Content-Type和文件大小,后缀也做了白名单。看起来挺严密。但它的上传目录和网站根目录是同一个,而且服务器是IIS 6.0。攻击者传了一个avatar.asp;.jpg,IIS 6.0的解析漏洞把分号后面的内容当参数处理,实际执行的是avatar.asp。白名单里的.jpg还在,但服务器根本不按那个逻辑走。防御的核心思路其实就一条:不要相信用户传的任何东西,包括文件名、类型、内容。存储的时候重命名成随机字符串加安全后缀,存到Web根目录之外,通过后端脚本读取后再输出。如果业务必须直接访问,那就把上传目录的脚本执行权限彻底关掉。Nginx里加一句
location ~* /uploads/.*\.(php|jsp|asp)$ { deny all; },比什么后缀检查都管用。文件上传漏洞的可怕之处不在技术复杂度,而在它太容易被低估。一个上传点,开发者觉得“不就是存个文件嘛”,攻击者看到的却是一个直接往服务器上写代码的入口。差距就在这儿。
顶: 474踩: 84






评论专区