从AI错误提示说起:JAVA文件上传常见安全陷阱
文件上传漏洞的常见错误写法分析 本文总结了文件上传功能中三种典型的安全漏洞写法: 后缀判断逻辑错误:使用.jsp而非jsp进行黑名单判断,导致过滤失效; 字符串包含检测漏洞:使用indexOf(".jsp")>0判断时,.jsp文件名会被漏过; 白名单实现错误:与第一种情况类似,但出现在白名单场景中。 这些错误在开发和审计过程中容易被忽视,黑盒测试时可通过上传.jsp等特
<%
try {
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
String uploadPath = application.getRealPath(“/upload”);
File uploadDir = new File(uploadPath);
if (!uploadDir.exists()) {
uploadDir.mkdirs();
}
List<FileItem> items = upload.parseRequest(request);
for (FileItem item : items) {
if (!item.isFormField() && item.getSize() > 0) {
String originalName = item.getName();
String extension = originalName.substring(originalName.lastIndexOf("."));
if (extension.equals("jsp") || extension.equals("jspx")) {
out.print("ERROR: 文件格式非法");
return;
}
File targetFile = new File(uploadDir, originalName);
item.write(targetFile);
out.print("SUCCESS: " + originalName);
}
}
} catch (Exception e) {
out.print("ERROR: " + e.getMessage());
}
%>
这么写如果开发者不经过测试会直接导致任意文件上传,因为当`originalName="1.jsp"`时`originalName.substring(originalName.lastIndexOf("."))`获取到的是带`.`的后缀`.jsp`而下面的判断是不带`.`会导致判断形同虚设。

如果按照AI的代码写白名单那什么类型的文件都会上传失败。这类错误在实际审计过程中遇到过多次,最近一次遇到是在一个`.NET`项目里代码如下

写法差不多`AI`可能真的是学多了垃圾代码导致自己也瞎写。
# 案例二
另外一种错误的黑名单写法
<%@ page language=“java” contentType=“text/plain; charset=UTF-8” pageEncoding=“UTF-8”%>
<%@ page import=“java.io." %>
<%@ page import="java.util.” %>
<%@ page import=“org.apache.commons.fileupload." %>
<%@ page import="org.apache.commons.fileupload.disk.” %>
<%@ page import=“org.apache.commons.fileupload.servlet.*” %>
<%@ page import=“java.util.UUID” %>
<%
try {
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
String uploadPath = application.getRealPath(“/upload”);
File uploadDir = new File(uploadPath);
if (!uploadDir.exists()) {
uploadDir.mkdirs();
}
List<FileItem> items = upload.parseRequest(request);
for (FileItem item : items) {
if (!item.isFormField() && item.getSize() > 0) {
String originalName = item.getName();
if (originalName.indexOf(".jsp") > 0){
out.print("ERROR: 文件格式非法");
return;
}
String extension = originalName.substring(originalName.lastIndexOf("."));
String randomName = UUID.randomUUID().toString() + extension;
File targetFile = new File(uploadDir, randomName);
item.write(targetFile);
out.println("SUCCESS: " + originalName + " -> " + randomName);
}
}
} catch (Exception e) {
out.print("ERROR: " + e.getMessage());
}
%>
这里直接使用`originalName.indexOf(".jsp") > 0`判断文件名中是否包含`.jsp`我估计有一部分审计人员可能认为是安全的,实际上是不安全的当`originalName=".jsp"`时`originalName.indexOf(".jsp")==0`依然可以上传`jsp`文件。


有朋友这几天正好遇到一个黑盒案例估计代码写的差不多


所以以后不光审计需要注意,黑盒测试的时候遇到黑名单也可以使用`.jsp`试试
# 案例三
一种错误的白名单写法
<%@ page language=“java” contentType=“text/plain; charset=UTF-8” pageEncoding=“UTF-8” trimDirectiveWhitespaces=“true”%>
<%@ page import=“java.io." %>
<%@ page import="java.util.” %>
<%@ page import=“org.apache.commons.fileupload." %>
<%@ page import="org.apache.commons.fileupload.disk.” %>
<%@ page import=“org.apache.commons.fileupload.servlet.*” %>
<%@ page import=“java.util.UUID” %>
<%
try {
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
String uploadPath = application.getRealPath(“/upload”);
File uploadDir = new File(uploadPath);
if (!uploadDir.exists()) {
uploadDir.mkdirs();
}
List<FileItem> items = upload.parseRequest(request);
for (FileItem item : items) {
if (!item.isFormField() && item.getSize() > 0) {
String originalName = item.getName();
if (originalName.indexOf(".zip") > 0){
String extension = originalName.substring(originalName.lastIndexOf("."));
String randomName = UUID.randomUUID().toString() + extension;
File targetFile = new File(uploadDir, randomName);
item.write(targetFile);
out.print("SUCCESS: " + originalName + " -> " + randomName);
}
else {
out.print("ERROR: 文件格式非法");
}
}
}
} catch (Exception e) {
out.print("ERROR: " + e.getMessage());
}
%>
这种写法在审计过程中也不少见,基本做审计的都可以看出来是任意文件上传。`originalName="1.zip.jsp"`即可


这种在黑盒里挺常见的遇到过很多次,因为我黑盒测试任意文件上传的流程是先上传白名单后缀文件,比如`1.zip`如果可以上传我会直接测试`1.zipa`而不是`1.jsp`,测试`1.zipa`不行的话基本上就不行了,如果行的话大多数情况的可以shell。比如这个案例里`1.zipa`是行的然后我可能会直接测试`1.zip.jsp`即可成功`shell`
# 总结
白盒审计的时候需要注意黑名单/白名单逻辑是否严密,黑盒测试的话可以尝试`1.jpg.jsp\.jsp`这种文件名可能可以绕过某些错误的黑白名单判断。
`AI`写的代码也可能会出现漏洞,如果一种错误写法在网上很多的话`AI`可能被污染导致某类漏洞大规模出现。有的时候会想`AI`会不会让代码审计人员失业,从这个例子来说好像不会😄?
更多推荐



所有评论(0)