通过 String fileType = fileItem.getName().substring(i+1);获取到后缀,并使用equals进行限制。
@WebServlet("/uploads")public class UploadFile extends HttpServlet{@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf-8");if(ServletFileUpload.isMultipartContent(req)){FileItemFactory factory = new DiskFileItemFactory();ServletFileUpload upload = new ServletFileUpload(factory);try {List<FileItem> list = upload.parseRequest(req);for(FileItem fileItem:list){if(!fileItem.isFormField()){int i = fileItem.getName().lastIndexOf('.');if(i>0){String fileType = fileItem.getName().substring(i+1);System.out.println("上传的类型为:"+fileType);if(fileType.equals("png")){System.out.println("上传成功!");System.out.println("上传的文件名:"+fileItem.getName());fileItem.write(new File("web根路径"+fileItem.getName()));}else{System.out.println("非法上传,文件后缀为"+fileType);}}}}} catch (Exception e) {e.printStackTrace();}}}}
现在测试一下,成功拦截掉非png后缀的:
到这里,是不是以为白名单就非常安全了?nonono。。
假设管理员粗心大意,修改了xml配置。
这样就会造成了白名单的绕过,而png就会当做jsp脚本来执行
web.xml文件配置如下
<servlet><servlet-name>tomcatpooljsp</servlet-name><jsp-file>/test.jsp</jsp-file></servlet><servlet-mapping><servlet-name>tomcatpooljsp</servlet-name><url-pattern>/test.png</url-pattern></servlet-mapping>
直接上传一个png格式的jsp一句话,成功绕过。
这里是看到网上之前分享的防御姿势,但是吧....感觉安全性还是不如白名单高。
代码如下,通过判断文件头来进行下一步操作。(ps:自己看看就好)
// 获得文件头部字符串public static String bytesToHexString(byte[] src) {StringBuilder stringBuilder = new StringBuilder();if (src == null || src.length <= 0) {return null;}for (int i = 0; i < src.length; i++) {int v = src[i] & 0xFF;String hv = Integer.toHexString(v);if (hv.length() < 2) {stringBuilder.append(0);}stringBuilder.append(hv);}return stringBuilder.toString();}FILE_TYPE_MAP.put("jpg", "FFD8FF"); //JPEGFILE_TYPE_MAP.put("png", "89504E47"); //PNGFILE_TYPE_MAP.put("gif", "47494638"); //GIF
俺的原创:https://www.freebuf.com/vuls/304252.html