嵌入式 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)。
创建 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)。