【问题标题】:Securely allow user-generated files to be downloaded from server安全地允许从服务器下载用户生成的文件
【发布时间】:2016-08-17 14:43:59
【问题描述】:

我用的是Tomcat8/Java

我目前允许从服务器下载敏感的用户生成的 Excel 文件(用 Java/POI 创建),方法是创建一个带有 GUID 的文件名,然后将其保存在公开可用的目录中,并提供此文件的链接.

第一阶段

用户选择各种参数,JSP 将这些参数发送到 Java 文件中

String fileName = "excelFiles/"
                + myReports
                        .createExcel(listCompanyDetails);

public static String createExcel(List listCompanyDetails) {
        String fileName = "MyFile"+UUID.randomUUID() + ".xls";
        String fileFullPath="\..."+fileName;
        FileInputStream inputStream = new FileInputStream(new File(APPCodeTable.templateExcelFile));
        Workbook wb=new HSSFWorkbook(inputStream);
        FileOutputStream out = new FileOutputStream(fileFullPath);
        wb.write(out);
        out.close();
}

第 2 阶段

JSP 然后在 iFrame 中显示文件

<iframe id="target_upload" name="target_upload" width="100%"
src="<%=fileName%>" height="100%"></iframe>

在我们的系统上完成的渗透测试结果表明,我们应该改为从 jsp 文件以流的形式生成文件,这样会更安全,因为它可以避免使用 GUID,并且可以避免使用直接链接到将绕过登录授权的文件。

然而,使用 servlet 似乎是更好的编码实践。例如Implementing a simple file download servlet

我正在考虑将文档保存在服务器上,由 GUID 标识,然后将此 GUID 传递给 servlet。然而,这似乎违背了我提高安全性的初衷。

如果我实现了一个简单的下载 servlet(如附加链接中所示),我如何才能在该 servlet 中获取我创建的文件?

【问题讨论】:

  • 简单地通过 servlet 流式传输似乎并不能解决任何安全问题——尤其是因为通过 Tomcat 提供的静态资源已经由 servlet(catalina DefaultServlet)提供。因此,回答这个问题需要更好地了解安全发现的实际内容(与发现提出的解决方案相比)
  • 我稍微更新了关于安全问题的问题
  • “但是我仍然需要将文档保存在服务器上”....这个陈述不一定是真的(或者它为什么是真的背后的原因还不清楚)。如果您实际上是“即时”生成 XLSX(即由 HttpServletRequest 触发),那么您无需将 Workbook 写入 FileOutputStream,而是将其写入 HttpServletResponse 的 outputStream。例如new Workbook().write(httpServletResponse.getOutputStream()) 还有比这更多的东西,但是如果这种方法看起来可行,我会以答案的形式写出详细信息
  • 谢谢@jamey graham。我重写了我的问题,以便让您了解您建议的方法在我的特定情况下是否可行......

标签: java security tomcat8


【解决方案1】:

您可以通过将 Workbook 写入 HttpServletResponse.getOutputStream() 来有效地将这两个步骤合并为 1,而不是在第 1 阶段写入文件并在第 2 阶段读取该文件。

1。 收集用户参数(假设这是在&lt;form&gt; 中完成的)并针对 IFRAME 发布它们。例如

 <form action="reportservlet/MyReport.xls" method="POST" target="target_upload">

2。 设置一个新的 servlet + 映射(* 映射允许 MyReport.xls 部分是任何东西......包括您在提交表单时即时构建的东西)。

<servlet>
    <servlet-name>ReportServlet</servlet-name>
    <servlet-class>foo.ReportServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ReportServlet</servlet-name>
    <url-pattern>/reportservlet/*</url-pattern>
</servlet-mapping>

3。 在您的 servlet 中,类似于(忽略 servlet 中业务逻辑的“糟糕设计”..这只是说明性的)

public void doPost(HttpServletRequest req, HttpServletResponse rsp) throws ServletException {
    // all the security stuff and stuff to produce List listCompanyDetails
    FileInputStream inputStream = new FileInputStream(new File(APPCodeTable.templateExcelFile));
    Workbook wb=new HSSFWorkbook(inputStream);
    rsp.setContentType("application/vnd.ms-excel");
    wb.write(rsp.getOutputStream()); // this is the key...write directly to the request output vs. a temp file
}

一些评论..

  1. 我假设您正在为一组控制良好的用户进行开发,他们将 a) 使用 IE 并且 b) 安装了 Excel - 在 IFRAME 中定位 excel 内容是一个非常糟糕的主意
  2. 绝对不要使用 JSP 代替我建议的 Servlet - 使用 JSP 生成二进制数据只是一个“坏主意”。它在技术上是可行的,但除非您正确构建 JSP,否则您可能会引入字符数据(很可能是难以看到的换行符和/或尾随空格),这会破坏 XLS

【讨论】:

  • 谢谢。刚从假期回来 - 抱歉延迟回复...我如何将我的“List listCompanyDetails”传递给“doPost”servlet?
【解决方案2】:

我从Implementing a simple file download servlet实现了@wen的回答

此外,我使用@Ramesh PVK 在How to deny web access to a Tomcat directory 中的建议删除了对保存文件的目录的直接 Web 访问权限

<security-constraint>
  <web-resource-collection>
    <web-resource-name >precluded methods</web-resource-name>
    <url-pattern >/excelFiles/*</url-pattern>
    </web-resource-collection>
    <auth-constraint/>
</security-constraint>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-15
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 2017-06-08
    • 2016-10-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多