安全注意事项

目录

简介

Tomcat默认配置对于大多数用例而言是相当安全的。某些环境可能需要更安全或更不安全的配置。本页面旨在为可能影响安全的配置选项提供单一参考点,并对更改这些选项的预期影响提供一些说明。目的是提供一份在评估Tomcat安装安全性时应考虑的配置选项列表。

注意:阅读本页面不能替代阅读和理解详细的配置文档。这些属性的更完整描述可在相关文档页面中找到。

非Tomcat设置

Tomcat配置不应是唯一的防御措施。系统中的其他组件(操作系统、网络、数据库等)也应得到保护。

Tomcat不应以root用户身份运行。为Tomcat进程创建一个专用用户,并为该用户提供操作系统所需的最小权限。例如,不应允许使用Tomcat用户进行远程登录。

文件权限也应适当限制。在.tar.gz分发包中,文件和目录不可被所有人读取,且组没有写入权限。在类Unix操作系统上,Tomcat以默认的0027 umask运行,以维护Tomcat运行时创建的文件(例如日志文件、解压的WAR包等)的这些权限。

以ASF的Tomcat实例为例(其中自动部署被禁用,Web应用以解压目录形式部署),标准配置是所有Tomcat文件由root拥有,组为Tomcat,且所有者具有读/写权限,组仅具有读权限,其他用户无任何权限。例外是日志、临时和工作目录,它们由Tomcat用户而不是root拥有。这意味着即使攻击者入侵了Tomcat进程,他们也无法更改Tomcat配置、部署新的Web应用或修改现有Web应用。Tomcat进程以007的umask运行以维护这些权限。

在网络层面,考虑使用防火墙将入站和出站连接限制为仅您期望存在的连接。

JMX

JMX连接的安全性取决于JRE提供的实现,因此超出了Tomcat的控制范围。

通常,访问控制非常有限(要么对所有内容只读,要么对所有内容读写)。Tomcat通过JMX公开了大量的内部信息和控制,以帮助调试、监控和管理。鉴于可用的访问控制有限,JMX访问应被视为等同于本地root/管理员访问,并相应地进行限制。

大多数(所有?)JRE供应商提供的JMX访问控制不会记录失败的认证尝试,也不会在重复认证失败后提供账户锁定功能。这使得暴力攻击易于实施且难以检测。

鉴于以上所有情况,应注意确保,如果使用JMX接口,其得到适当的保护。您可能希望考虑保护JMX接口的选项包括:

  • 为所有JMX用户配置强密码;
  • 将JMX监听器仅绑定到内部网络;
  • 将JMX端口的网络访问限制为受信任的客户端;以及
  • 提供一个应用程序特定的健康页面供外部监控系统使用。

默认Web应用

一般

Tomcat默认附带了一些Web应用程序。过去在这些应用程序中发现过漏洞。不需要的应用程序应被移除,这样即使发现其他漏洞,系统也不会面临风险。

ROOT

ROOT Web应用程序的安全风险非常低,但它确实包含了正在使用的Tomcat版本。ROOT Web应用程序通常应从公开可访问的Tomcat实例中移除,这不是出于安全原因,而是为了向用户显示一个更合适的默认页面。

文档

文档Web应用程序的安全风险非常低,但它确实标识了正在使用的Tomcat版本。它通常应从公开可访问的Tomcat实例中移除。

示例

示例Web应用程序应始终从任何安全敏感的安装中移除。虽然示例Web应用程序不包含任何已知漏洞,但已知它包含可能被攻击者与Tomcat实例上部署的另一个应用程序中的漏洞结合使用以获取原本无法获得的其他信息的功能(特别是显示所有接收到的cookie内容并允许设置新cookie的cookie示例)。

管理器

Manager应用程序允许远程部署Web应用程序,并且由于弱密码的广泛使用以及启用了Manager应用程序的公开可访问Tomcat实例,它经常成为攻击者的目标。默认情况下,Manager应用程序不可访问,因为没有用户配置有必要的访问权限。如果启用了Manager应用程序,则应遵循保护管理应用部分中的指导。

主机管理器

Host Manager应用程序允许创建和管理虚拟主机——包括为虚拟主机启用Manager应用程序。默认情况下,Host Manager应用程序不可访问,因为没有用户配置有必要的访问权限。如果启用了Host Manager应用程序,则应遵循保护管理应用部分中的指导。

保护管理应用

部署为Tomcat实例提供管理功能的Web应用程序时,应遵循以下准则:

  • 确保允许访问管理应用程序的任何用户都拥有强密码。
  • 不要移除LockOutRealm的使用,它可防止针对用户密码的暴力攻击。
  • 在管理应用程序的context.xml文件中配置RemoteAddrValve,该阀门默认将访问限制为localhost。如果需要远程访问,请使用此阀门将其限制为特定的IP地址。

安全管理器

从Tomcat 11开始,移除了在安全管理器下运行的支持。通过在专用环境(如容器或虚拟机)中的专用Tomcat实例上运行单个Web应用程序,可能会获得类似(甚至可以说更好)的功能。

server.xml

一般

默认的server.xml包含大量的注释,包括一些被注释掉的示例组件定义。移除这些注释会大大提高server.xml的可读性和理解性。

如果未列出组件类型,则该类型没有直接影响安全的设置。

服务器

port属性设置为-1会禁用关闭端口。

如果未禁用关闭端口,则应为shutdown配置强密码。

监听器

如果在Solaris上使用gcc编译,APR生命周期监听器不稳定。如果在Solaris上使用APR/native连接器,请使用Sun Studio编译器进行编译。

JNI库加载监听器可用于加载本机代码。它应仅用于加载受信任的库。

安全生命周期监听器应根据需要启用和配置。

连接器

默认情况下,端口8080上配置了一个非TLS的HTTP/1.1连接器。不使用的连接器应从server.xml中移除。

AJP是一个明文协议。AJP连接器通常只能在受信任的网络上使用。如果在不受信任的网络上使用,使用secret属性将限制对授权客户端的访问,但secret属性对任何能够观察网络流量的人都可见。

AJP连接器会阻止带有未知请求属性的转发请求。可以通过为allowedRequestAttributesPattern属性配置适当的正则表达式来允许已知的安全和/或预期的属性。

address属性可用于控制连接器监听连接的IP地址。默认情况下,连接器会监听所有配置的IP地址。

allowBackslash属性允许对请求URI进行非标准解析。当位于反向代理后面时,将此属性设置为非默认值可能会使攻击者绕过代理强制执行的任何安全约束。

allowTrace属性可用于启用TRACE请求,这对于调试可能很有用。由于某些浏览器处理TRACE请求响应的方式(这会使浏览器面临XSS攻击),默认情况下禁用了对TRACE请求的支持。

discardFacades属性设置为true将导致为每个请求创建一个新的门面对象。这是默认值,这样做可以减少应用程序中错误将一个请求的数据暴露给另一个请求的几率。

encodedSolidusHandling属性允许对请求URI进行非标准解析。当位于反向代理后面时,将此属性设置为非默认值可能会使攻击者绕过代理强制执行的任何安全约束。

如果将enforceEncodingInGetWriter属性设置为false,则会产生安全隐患。许多用户代理违反RFC 7230,在应使用规范规定的默认ISO-8859-1时,会尝试猜测文本媒体类型的字符编码。某些浏览器会将包含对ISO-8859-1安全但如果解释为UTF-7会触发XSS漏洞的字符的响应解释为UTF-7。

maxPostSize属性控制将解析参数的POST请求的最大大小。参数在请求期间被缓存,因此默认限制为2 MiB,以减少DDoS攻击的风险。

maxSavePostSize属性控制在FORM和CLIENT-CERT认证以及HTTP/1.1升级期间请求体的保存。对于FORM认证,请求体在HTTP会话中缓存,持续认证期间,因此缓存的请求体默认限制为4 KiB,以减少DDoS攻击的风险。为了通过限制FORM认证的允许持续时间来进一步减少DDoS攻击的风险,如果会话是由FORM认证创建的,则使用缩短的会话超时。此缩短的超时由FORM认证器authenticationSessionTimeout属性控制。

maxParameterCount属性控制从查询字符串获取的请求参数(包括上传文件)的最大总数,对于POST请求,如果内容类型是application/x-www-form-urlencodedmultipart/form-data,则还包括请求体中的参数。参数过多的请求将被拒绝。

xpoweredBy属性控制是否在每个请求中发送X-Powered-By HTTP头。如果发送,该头的值将包含Servlet和JSP规范版本、完整的Tomcat版本(例如Apache Tomcat/11.0)、JVM供应商名称和JVM版本。默认情况下,此头是禁用的。此头可以向合法客户端和攻击者提供有用信息。

server属性控制Server HTTP头的值。Tomcat 4.1.x到8.0.x的此头默认值为Apache-Coyote/1.1。从8.5.x版本开始,此头默认不设置。此头可以向合法客户端和攻击者提供有限信息。

SSLEnabledschemesecure属性都可以独立设置。它们通常在Tomcat位于反向代理后面,且代理通过HTTP或HTTPS连接到Tomcat时使用。它们允许Tomcat查看客户端与代理之间连接的SSL属性,而不是代理与Tomcat之间的。例如,客户端可能通过HTTPS连接到代理,但代理使用HTTP连接到Tomcat。如果Tomcat需要能够区分代理接收到的安全和非安全连接,代理必须使用单独的连接器将安全和非安全请求传递给Tomcat。如果代理使用AJP,则客户端连接的SSL属性通过AJP协议传递,无需单独的连接器。

tomcatAuthenticationtomcatAuthorization属性与AJP连接器一起使用,以确定Tomcat是否应处理所有认证和授权,或者是否应将认证委托给反向代理(通过AJP协议将已认证的用户名传递给Tomcat),同时Tomcat仍可执行授权。

AJP连接器中的requiredSecret属性配置了Tomcat和Tomcat前面的反向代理之间的共享密钥。它用于防止通过AJP协议进行未经授权的连接。

主机

host元素控制部署。自动部署使管理更简单,但也使攻击者更容易部署恶意应用程序。自动部署由autoDeploydeployOnStartup属性控制。如果两者都为false,则只部署server.xml中定义的Context,并且任何更改都将需要重启Tomcat。

在Web应用程序可能不受信任的托管环境中,将deployXML属性设置为false,以忽略Web应用程序中可能尝试为Web应用程序分配更高权限的任何context.xml。请注意,如果启用了安全管理器,则deployXML属性将默认为false

上下文

这适用于Context元素在所有可以定义它们的地方:server.xml文件、默认的context.xml文件、每个主机的context.xml.default文件、每个主机配置目录中的Web应用程序上下文文件或Web应用程序内部。

crossContext属性控制一个上下文是否允许访问另一个上下文的资源。它默认是false,并且只应为受信任的Web应用程序更改。

privileged属性控制一个上下文是否允许使用容器提供的servlet,例如Manager servlet。它默认是false,并且只应为受信任的Web应用程序更改。

嵌套的Resources元素的allowLinking属性控制上下文是否允许使用链接文件。如果启用并且上下文被卸载,则在删除上下文资源时将跟随链接。在不区分大小写的操作系统(包括Windows)上将此设置从默认的false更改将禁用许多安全措施,并允许(除其他外)直接访问WEB-INF目录。

sessionCookiePathUsesTrailingSlash可用于解决一些浏览器(Internet Explorer、Safari和Edge)中的一个bug,以防止当应用程序共享公共路径前缀时,会话cookie在应用程序之间暴露。然而,启用此选项可能会为映射到/*的Servlet应用程序带来问题。还应注意的是,RFC6265第8.5节明确指出,不同的路径不应被视为足以将cookie与其他应用程序隔离。

当启用antiResourceLocking时,Tomcat会将解压后的Web应用程序复制到由java.io.tmpdir系统属性定义的目录(默认为$CATALINA_BASE/temp)。此位置应通过适当的文件权限进行保护——通常是Tomcat用户可读写,其他用户无访问权限。

当启用mapperContextRootRedirectEnabled和/或mapperDirectoryRedirectEnabled时,请求处理将更高效,但会产生安全副作用。首先,即使用户无权访问该目录,Web应用程序或目录的存在也可能被确认。其次,任何阀门(Valves)和/或过滤器(Filters)——包括提供安全功能的那些——将没有机会处理请求。

阀门

强烈建议配置一个AccessLogValve。默认的Tomcat配置包含一个AccessLogValve。这些通常是按主机配置的,但也可以根据需要按引擎或按上下文配置。

任何管理应用程序都应通过RemoteAddrValve(此阀门也可用作过滤器)进行保护。allow属性应用于限制对一组已知可信主机的访问。

默认的ErrorReportValve会在发送给客户端的响应中包含Tomcat版本号。为避免这种情况,可以在每个Web应用程序中配置自定义错误处理。或者,您可以明确配置一个ErrorReportValve并将其showServerInfo属性设置为false。或者,可以通过创建文件CATALINA_BASE/lib/org/apache/catalina/util/ServerInfo.properties并包含以下内容来更改版本号:

server.info=Apache Tomcat/11.0.x

根据需要修改值。请注意,这也会改变某些管理工具中报告的版本号,并可能使其更难确定实际安装的版本。CATALINA_HOME/bin/version.bat|sh脚本仍将报告正确的版本号。

默认的ErrorReportValve在发生错误时可以向客户端显示堆栈跟踪和/或JSP源代码。为避免这种情况,可以在每个Web应用程序中配置自定义错误处理。或者,您可以明确配置一个ErrorReportValve并将其showReport属性设置为false

RewriteValve使用正则表达式,而格式不佳的正则表达式模式可能容易受到“灾难性回溯”或“ReDoS”攻击。有关更多详细信息,请参阅重写文档

MemoryRealm不适用于生产环境,因为对tomcat-users.xml的任何更改都需要重启Tomcat才能生效。

UserDatabaseRealm不适用于大规模安装。它适用于小型、相对静态的环境。

JAASRealm使用不广泛,因此其代码不如其他域成熟。在使用此域之前建议进行额外测试。

默认情况下,这些域不实现任何形式的账户锁定。这意味着暴力攻击可能会成功。为防止暴力攻击,所选域应包装在LockOutRealm中。

管理器

manager组件用于生成会话ID。

用于生成随机会话ID的类可以通过randomClass属性进行更改。

会话ID的长度可以通过sessionIdLength属性进行更改。

persistAuthentication控制会话关联的认证Principal(如果有)在会话重启或持久化到存储时是否被包含。

使用JDBCStore时,会话存储应得到保护(专用凭据,适当的权限),以便只有JDBCStore能够访问持久化的会话数据。特别是,JDBCStore不应通过任何可供Web应用程序使用的凭据进行访问。

将session持久化到存储或在集群中复制session的Manager实现通常使用Java序列化。虽然session数据被认为是受信任的(因为应用程序是受信任的),但系统管理员可能希望考虑对Java序列化施加限制。这可以通过使用sessionAttributeValueClassNameFilter属性来完成。此属性的一个安全的起始值为java\\.lang\\.(?:Boolean|Integer|Long|Number|String)|org\\.apache\\.catalina\\.realm\\.GenericPrincipal\\$SerializablePrincipal|\\[Ljava.lang.String;,然后可以根据应用程序的需求进行调整。如果为sessionAttributeValueClassNameFilter设置值,建议将warnOnSessionAttributeFilterFailure设置为true

集群

集群实现是基于所有集群相关的网络流量都使用安全、可信的网络这一前提编写的。在不安全、不可信的网络上运行集群是不安全的。

如果您需要保密性或完整性保护,则可以使用EncryptInterceptor来加密节点间的流量。此拦截器不能完全防御在不可信网络上运行的所有风险,特别是DDoS攻击。

web.xml

这适用于默认的conf/web.xml文件、Web应用程序中的/WEB-INF/tomcat-web.xml/WEB-INF/web.xml文件(如果它们定义了此处提到的组件)。

配置为readonly设置为true。将其更改为false允许客户端删除或修改服务器上的静态资源并上传新资源。通常不应在不要求认证的情况下更改此设置。

DefaultServlet配置为listings设置为false。这并非因为允许目录列表被认为不安全,而是因为生成包含数千个文件的目录列表会消耗大量CPU,从而导致DDoS攻击。

DefaultServlet配置为showServerInfo设置为true。当启用目录列表时,Tomcat版本号会包含在发送给客户端的响应中。为避免这种情况,您可以显式配置一个DefaultServlet并将其showServerInfo属性设置为false。或者,可以通过创建文件CATALINA_BASE/lib/org/apache/catalina/util/ServerInfo.properties并包含以下内容来更改版本号:

server.info=Apache Tomcat/11.0.x

根据需要修改值。请注意,这也会改变某些管理工具中报告的版本号,并可能使其更难确定实际安装的版本。CATALINA_HOME/bin/version.bat|sh脚本仍将报告正确的版本号。

CGI Servlet默认是禁用的。如果启用,在生产系统上,调试初始化参数不应设置为10或更高,因为调试页面不安全。

在Windows上使用CGI Servlet并启用enableCmdLineArguments时,请仔细检查cmdLineArgumentsDecoded的设置,并确保其适合您的环境。默认值是安全的。不安全的配置可能会使服务器面临远程代码执行的风险。有关潜在风险和缓解措施的更多信息,请查阅CGI操作指南中的链接。

HttpHeaderSecurityFilter可用于向响应添加头部以提高安全性。如果客户端直接访问Tomcat,那么您可能希望启用此过滤器及其设置的所有头部,除非您的应用程序已自行设置。如果通过反向代理访问Tomcat,则此过滤器的配置需要与反向代理设置的任何头部协调。

WebDAV servlet为Web应用程序内容启用编辑功能。如果启用了WebDAV servlet,则应适当保护WebDAV功能。

配置安全约束时,如果一个或多个约束的URL模式覆盖了URL的任何部分,该部分成为servlet的pathInfo,并且servlet使用pathInfo来标识其他资源(例如默认servlet),则应小心。在这种情况下,安全约束的正确应用取决于Servlet的实现。Tomcat附带的所有servlet在这种情况下都会正确运行。

嵌入式Tomcat

使用嵌入式Tomcat时,脚本、server.xml和其他配置提供的典型默认值未设置。嵌入式Tomcat的用户可能需要考虑以下事项:

  • 通常在server.xml中配置的监听器,包括org.apache.catalina.security.SecurityListener,默认情况下不会被配置。如果需要,必须显式启用它们。
  • java.io.tmpdir将不会被设置(通常它被设置为$CATALINA_BASE/temp)。此目录用于各种可能涉及安全敏感的临时文件,包括文件上传以及在启用反资源锁定时的Web应用程序副本。请考虑将java.io.tmpdir系统属性设置为适当安全的目录。

一般

BASIC和FORM认证以明文形式传递用户名和密码。使用这些认证机制并通过不可信网络连接的Web应用程序应使用SSL。

对于经过认证的用户会话的会话cookie,对攻击者来说几乎与用户密码同样有用,因此应给予与密码本身相同级别的保护。这通常意味着通过SSL进行认证,并继续使用SSL直到会话结束。

Tomcat对Servlet API文件上传的支持可能使用由java.io.tmpdir系统属性(默认为$CATALINA_BASE/temp)定义的目录来存储临时文件。此位置应通过适当的文件权限进行保护——通常是Tomcat用户可读写,其他用户无访问权限。