探索

java文件上传过滤

时间:2010-12-5 17:23:32  作者:焦点   来源:百科  查看:  评论:0
内容摘要:去年有个朋友做后台管理系统,文件上传接口没做任何过滤,上线第三天服务器就被塞满了jsp脚本。攻击者上传了一个改名成.jpg的webshell,路径还直接返回给了前端。这事其实很典型——很多人以为前端限

去年有个朋友做后台管理系统,文件文件上传接口没做任何过滤,上传上线第三天服务器就被塞满了jsp脚本。过滤攻击者上传了一个改名成.jpg的文件webshell,路径还直接返回给了前端。上传这事其实很典型——很多人以为前端限制了accept="image/*"就万事大吉,过滤但抓包改个后缀就能绕过去。文件

文件上传过滤的上传核心逻辑不在前端,在服务端。过滤前端那点校验只是文件给正常用户看的,对攻击者来说形同虚设。上传服务端要做的过滤第一件事,是文件判断文件真实类型,而不是上传信后缀名。Java里可以用Files.probeContentType(),过滤或者更靠谱的Apache Tika。比如一个文件叫avatar.png,但Tika检测出来是text/x-php,那就直接拒绝。

String mimeType = tika.detect(file.getBytes()); if (!Arrays.asList("image/jpeg", "image/png", "image/gif").contains(mimeType)) {  throw new IllegalArgumentException("不支持的文件类型"); }

光看MIME还不够。有些攻击者会构造图片马,文件头是正常的JPEG,后面拼接PHP代码。这时候需要检查文件魔数。JPEG以FF D8 FF开头,PNG是89 50 4E 47。读前几个字节比对,比后缀可靠得多。我一般会写个简单的魔数校验工具类,把常见图片格式的签名都列进去。

后缀名白名单是必须的,但别用黑名单。有人写if (fileName.endsWith(".jsp"))就完事,攻击者用.jspx、.jspf甚至.jsp;.jpg(某些容器会截断分号)照样能绕。白名单只允许.jpg、.png、.gif,其他一律拒绝。注意大小写,.JPG和.jpg要统一转小写再比较。

存储路径也得处理。别用用户上传的原始文件名拼路径,什么../../../../etc/passwd这种目录穿越,或者shell.jsp直接落到web目录下。我的做法是:用UUID重命名文件,存储目录放在web根目录之外,通过一个专门的Servlet或Controller来读取文件流。这样即使上传了恶意脚本,也无法通过URL直接访问执行。

String newFileName = UUID.randomUUID() + "." + ext; Path targetPath = Paths.get("/data/upload/", newFileName); Files.copy(file.getInputStream(), targetPath, StandardCopyOption.REPLACE_EXISTING);

文件大小和数量限制别忽略。有人上传一个10GB的zip,解压后直接把磁盘打满。Spring Boot里配置spring.servlet.multipart.max-file-size=5MB和max-request-size=10MB,同时在业务层再校验一次。别只靠容器配置,Tomcat的maxSwallowSize这些参数有时候会坑你。

图片文件还可以做二次处理。用Thumbnailator或者Java自带的ImageIO读一遍,能正常解码成BufferedImage的,基本就是真图片。解码失败的直接丢弃。这一步能干掉大部分图片马,因为PHP代码拼接在图片数据后面,ImageIO读取时可能报错或者只读前面部分。不过要注意,有些特殊格式的图片可能解码失败但其实是合法的,得权衡误杀率。

还有个容易漏的点:上传目录的权限。Linux下设置成chmod 755,属主是运行Java进程的用户,别给写和执行权限。Windows下更简单,去掉IIS或Tomcat对该目录的脚本执行权限。如果非要把文件放在web目录下,至少配个web.xml把*.jsp的访问映射到404。

最后说个真实案例。某次代码审计看到一个上传接口,做了后缀白名单、MIME校验、大小限制,看起来挺全。但存储时用了new File(uploadDir + fileName),fileName是用户可控的原始文件名。攻击者上传test.jpg,然后构造fileName=../../../tomcat/webapps/ROOT/shell.jsp,虽然后缀是jpg,但路径穿越后实际写入了jsp文件。这种组合漏洞单看每个校验都没问题,拼在一起就出事。

过滤这事没有一劳永逸的方案。多层校验叠加,每层都假设前一层可能被绕过。文件类型、后缀、路径、权限、二次渲染,能上的都上。别嫌麻烦,等服务器被挂马的时候更麻烦。

最近更新
热门排行
copyright © 2026 powered by 力不从心网   sitemap