嵌入式 Tomcat 的 Context.docBase 是否存在安全问题?

Are there security concerns with embedded Tomcat's Context.docBase?

创建 org.apache.catalina.Context 时,您需要指定一个“docBase”参数。 docBase 应该是一个现有目录。如果它不是现有的可访问目录,则上下文创建失败。

java 文档将此参数描述为“上下文的基本目录,用于静态文件。必须存在,相对于服务器主目录”。 Tomcat 对该目录做了什么?它可能会从该位置提供文件吗?如果我不想提供静态文件,该参数的最安全值是多少?

例如,在我能写的最简单的嵌入式 Tomcat 服务器中,File(".").getAbsolutePath() 参数是否有可能被恶意客户端用来从当前目录检索文件?

import java.io.File;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.LifecycleException;
import org.apache.catalina.startup.Tomcat;

/**
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>9.0.56</version>
        </dependency>
 */
public class OneServlet {
    public static void main(String[] args) {
        Tomcat tomcat = new Tomcat();
        tomcat.setPort(9000);
        tomcat.getConnector();

        var context = tomcat.addContext("", new File(".").getAbsolutePath());
        Tomcat.addServlet(context, "servlet", new HttpServlet() {
            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                resp.getWriter().write("Hello world");
            }
        });
        context.addServletMappingDecoded("/", "servlet");

        try {
            tomcat.start();
            tomcat.getServer().await();
        } catch (LifecycleException e) {
            e.printStackTrace();
        }
    }
}

在传统部署中,docBase 指向您的 WAR 文件的根目录或包含扩展的 WAR 文件的目录。它是 ServletContext#getResource calls are resolved and also the root for the DefaultServlet 的基础 URL。

在您的情况下,使用 new File(".").getAbsoluteFile() 确实允许攻击者检索所有文件,前提是他们可以猜出文件的名称并且请求未被您的一个 servlet 拦截。它不会发生,因为您调用 Tomcat#addContext 而不是 Tomcat#addWebapp,这会阻止 Tomcat 将默认值 web.xml 应用到您的应用程序(即没有 DefaultServlet)。

但是,更安全的做法是使用 null 作为 docBase。在现代 Tomcat 上,这将导致创建一个空的内存资源集(参见 source code)。