安全注意事项
目录
简介
默认情况下,Tomcat 被配置为在大多数用例中具有合理的安全性。某些环境可能需要更安全或更不安全的配置。此页面旨在为可能影响安全性的配置选项提供一个参考点,并提供有关更改这些选项的预期影响的一些评论。目的是提供一个配置选项列表,在评估 Tomcat 安装的安全性时应考虑这些选项。
注意:阅读本页内容并不能替代阅读和理解详细的配置文档。这些属性的更完整描述可以在相关的文档页面中找到。
非 Tomcat 设置
Tomcat 配置不应该成为唯一的防御措施。系统中的其他组件(操作系统、网络、数据库等)也应该得到安全保护。
Tomcat 不应该以 root 用户身份运行。为 Tomcat 进程创建一个专用用户,并为该用户提供操作系统所需的最低权限。例如,不应该允许使用 Tomcat 用户远程登录。
文件权限也应该适当地限制。在 .tar.gz
分发版中,文件和目录对所有人不可读,并且组没有写入权限。在类 Unix 操作系统上,Tomcat 以默认 umask 0027
运行,以在 Tomcat 运行时创建的文件(例如日志文件、展开的 WAR 文件等)保持这些权限。
以 ASF 的 Tomcat 实例为例(其中自动部署被禁用,Web 应用程序以解压缩目录的形式部署),标准配置是所有 Tomcat 文件都归 root 所有,组为 Tomcat,并且所有者具有读写权限,组只有读权限,而所有人没有权限。例外情况是日志、临时和工作目录,它们归 Tomcat 用户而不是 root 所有。这意味着即使攻击者入侵了 Tomcat 进程,他们也无法更改 Tomcat 配置、部署新的 Web 应用程序或修改现有的 Web 应用程序。Tomcat 进程以 umask 007 运行,以保持这些权限。
在网络级别,考虑使用防火墙来限制传入和传出的连接,只允许您预期存在的连接。
JMX
JMX 连接的安全性取决于 JRE 提供的实现,因此不受 Tomcat 控制。
通常,访问控制非常有限(要么对所有内容只读,要么对所有内容读写)。Tomcat 通过 JMX 公开大量内部信息和控制,以帮助调试、监控和管理。鉴于可用的访问控制有限,JMX 访问应被视为等同于本地 root/admin 访问,并应相应地限制。
大多数(所有?)JRE 供应商提供的 JMX 访问控制不会记录身份验证失败尝试,也不会在多次身份验证失败后提供帐户锁定功能。这使得暴力攻击很容易实施,也很难检测。
鉴于以上所有内容,应注意确保在使用 JMX 接口时,对其进行适当的保护。您可以考虑以下选项来保护 JMX 接口:
- 为所有 JMX 用户配置强密码;
- 仅将 JMX 监听器绑定到内部网络;
- 将网络访问 JMX 端口限制为可信客户端;以及
- 为外部监控系统提供特定于应用程序的健康页面。
默认 Web 应用程序
一般
Tomcat 附带一些默认启用的 Web 应用程序。过去,这些应用程序中曾发现漏洞。应删除不需要的应用程序,这样如果发现其他漏洞,系统就不会处于风险之中。
ROOT
ROOT Web 应用程序的安全性风险很低,但它确实包含了正在使用的 Tomcat 版本。ROOT Web 应用程序通常应从公开可访问的 Tomcat 实例中删除,不是出于安全原因,而是为了向用户显示更合适的默认页面。
文档
文档 Web 应用程序的安全性风险很低,但它确实标识了正在使用的 Tomcat 版本。它通常应从公开可访问的 Tomcat 实例中删除。
示例
示例 Web 应用程序应始终从任何安全敏感的安装中删除。虽然示例 Web 应用程序不包含任何已知的漏洞,但已知它包含可能被攻击者利用的功能(特别是显示所有接收到的 cookie 内容并允许设置新 cookie 的 cookie 示例),这些功能可能与部署在 Tomcat 实例上的另一个应用程序中的漏洞结合使用,以获取原本无法获得的额外信息。
管理器
Manager 应用程序允许远程部署 Web 应用程序,由于广泛使用弱密码和公开可访问的启用了 Manager 应用程序的 Tomcat 实例,因此经常成为攻击者的目标。默认情况下,Manager 应用程序不可访问,因为没有用户配置了必要的访问权限。如果启用了 Manager 应用程序,则应遵循“**保护管理应用程序**”部分中的指南。
主机管理器
Host Manager 应用程序允许创建和管理虚拟主机,包括为虚拟主机启用 Manager 应用程序。默认情况下,Host Manager 应用程序不可访问,因为没有用户配置了必要的访问权限。如果启用了 Host Manager 应用程序,则应遵循“**保护管理应用程序**”部分中的指南。
保护管理应用程序
部署提供 Tomcat 实例管理功能的 Web 应用程序时,应遵循以下指南
- 确保任何被允许访问管理应用程序的用户都拥有强密码。
- 不要删除使用 LockOutRealm,它可以防止对用户密码的暴力攻击。
- 在管理应用程序的 context.xml 文件中配置 RemoteAddrValve,默认情况下它限制对 localhost 的访问。如果需要远程访问,请使用此阀门将其限制为特定 IP 地址。
安全管理器
启用安全管理器会导致 Web 应用程序在沙箱中运行,这极大地限制了 Web 应用程序执行恶意操作的能力,例如调用 System.exit()、建立网络连接或访问 Web 应用程序根目录和临时目录之外的文件系统。但是,需要注意的是,安全管理器无法阻止某些恶意操作,例如通过无限循环触发高 CPU 占用率。
通常启用安全管理器是为了限制潜在的影响,以防攻击者找到一种方法来破坏受信任的 Web 应用程序。安全管理器也可以用来降低运行不受信任的 Web 应用程序的风险(例如在托管环境中),但需要注意的是,安全管理器只能降低运行不受信任的 Web 应用程序的风险,并不能消除这些风险。如果运行多个不受信任的 Web 应用程序,建议将每个 Web 应用程序部署到单独的 Tomcat 实例(理想情况下是单独的主机)中,以减少恶意 Web 应用程序影响其他应用程序可用性的可能性。
Tomcat 在启用安全管理器的情况下进行了测试;但大多数 Tomcat 用户不使用安全管理器运行,因此 Tomcat 在这种配置下的用户测试并不多。已经并且仍然存在报告的安全漏洞是由在安全管理器下运行触发的。
如果启用安全管理器,安全管理器施加的限制可能会破坏大多数应用程序。在没有进行广泛测试的情况下,不应使用安全管理器。理想情况下,在开发周期的开始就应该引入安全管理器的使用,因为对于成熟的应用程序来说,跟踪和修复启用安全管理器导致的问题可能非常耗时。
启用安全管理器会更改以下设置的默认值
- Host 元素的 deployXML 属性的默认值更改为
false
。
server.xml
一般
默认的 server.xml 包含大量注释,包括一些被注释掉的示例组件定义。删除这些注释使 server.xml 更易于阅读和理解。
如果未列出组件类型,则该类型没有直接影响安全性的设置。
服务器
将 port 属性设置为 -1
将禁用关闭端口。
如果未禁用关闭端口,则应为 shutdown 配置一个强密码。
监听器
如果使用 gcc 在 Solaris 上编译,APR 生命周期监听器不稳定。如果在 Solaris 上使用 APR/native 连接器,请使用 Sun Studio 编译器编译它。
JNI 库加载监听器可用于加载本机代码。它只应用于加载受信任的库。
应启用安全生命周期监听器并根据需要进行配置。
连接器
默认情况下,在端口 8080 上配置了一个非 TLS、HTTP/1.1 连接器。应从 server.xml 中删除不会使用的连接器。
AJP 连接器应仅在受信任的网络上使用,或者使用合适的 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,以减少对 DoS 攻击的暴露。
**maxSavePostSize** 属性控制在 FORM 和 CLIENT-CERT 身份验证以及 HTTP/1.1 升级期间保存请求主体。对于 FORM 身份验证,请求主体在 HTTP 会话期间被缓存,因此默认情况下缓存的请求主体限制为 4 KiB,以减少对 DoS 攻击的暴露。为了通过限制 FORM 身份验证的允许持续时间来进一步减少对 DoS 攻击的暴露,如果会话是由 FORM 身份验证创建的,则使用缩短的会话超时时间。此缩短的超时时间由 FORM 身份验证器 的 `authenticationSessionTimeout` 属性控制。
**maxParameterCount** 属性控制从查询字符串获取的请求参数(包括上传的文件)的最大总数,以及对于 POST 请求,如果内容类型为 `application/x-www-form-urlencoded` 或 `multipart/form-data`,则控制从请求主体获取的请求参数的最大总数。过多的参数将被忽略。如果您想拒绝此类请求,请配置一个 FailedRequestFilter。
**xpoweredBy** 属性控制是否为每个请求发送 X-Powered-By HTTP 标头。如果发送,标头的值将包含 Servlet 和 JSP 规范版本、完整的 Tomcat 版本(例如 Apache Tomcat/10.1)、JVM 供应商的名称以及 JVM 的版本。此标头默认情况下被禁用。此标头可以为合法客户端和攻击者提供有用的信息。
**server** 属性控制 Server HTTP 标头的值。Tomcat 4.1.x 到 8.0.x 的默认值为 Apache-Coyote/1.1。从 8.5.x 开始,此标头默认情况下不会设置。此标头可以为合法客户端和攻击者提供有限的信息。
**SSLEnabled**、**scheme** 和 **secure** 属性可以独立设置。这些通常在 Tomcat 位于反向代理后面并且代理通过 HTTP 或 HTTPS 连接到 Tomcat 时使用。它们允许 Tomcat 查看客户端和代理之间连接的 SSL 属性,而不是代理和 Tomcat 之间的连接。例如,客户端可能通过 HTTPS 连接到代理,但代理使用 HTTP 连接到 Tomcat。如果 Tomcat 需要能够区分代理接收到的安全连接和非安全连接,则代理必须使用单独的连接器将安全请求和非安全请求传递给 Tomcat。如果代理使用 AJP,则客户端连接的 SSL 属性将通过 AJP 协议传递,并且不需要单独的连接器。
tomcatAuthentication 和 tomcatAuthorization 属性与 AJP 连接器一起使用,用于确定 Tomcat 是否应该处理所有身份验证和授权,或者是否应该将身份验证委托给反向代理(经过身份验证的用户名作为 AJP 协议的一部分传递给 Tomcat),并可以选择让 Tomcat 继续执行授权。
AJP 连接器中的 requiredSecret 属性配置 Tomcat 和 Tomcat 前面的反向代理之间的共享密钥。它用于防止通过 AJP 协议进行未经授权的连接。
主机
host 元素控制部署。自动部署允许更简单的管理,但也使攻击者更容易部署恶意应用程序。自动部署由 autoDeploy 和 deployOnStartup 属性控制。如果两者都为 false
,则只会部署在 server.xml 中定义的上下文,任何更改都需要重新启动 Tomcat。
在托管环境中,如果 Web 应用程序可能不可信,请将 deployXML 属性设置为 false
以忽略与 Web 应用程序打包在一起的任何 context.xml,这些 context.xml 可能尝试为 Web 应用程序分配更高的权限。请注意,如果启用了安全管理器,则 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
更改为 true
将禁用许多安全措施,并允许直接访问 WEB-INF 目录等。
sessionCookiePathUsesTrailingSlash 可用于解决许多浏览器(Internet Explorer、Safari 和 Edge)中的一个错误,以防止在应用程序共享公共路径前缀时跨应用程序公开会话 cookie。但是,启用此选项可能会为映射到 /*
的 Servlet 的应用程序造成问题。还应注意,RFC6265 第 8.5 节明确指出,不同的路径不应被视为足以将 cookie 与其他应用程序隔离。
当启用 **antiResourceLocking** 时,Tomcat 会将解压缩的 Web 应用程序复制到由 java.io.tmpdir
系统属性定义的目录(默认情况下为 $CATALINA_BASE/temp
)。此位置应使用适当的文件权限进行保护 - 通常对 Tomcat 用户具有读写权限,而其他用户则无权访问。
阀门
强烈建议配置 AccessLogValve。默认的 Tomcat 配置包含 AccessLogValve。这些通常按主机配置,但也可以根据需要按引擎或按上下文配置。
任何管理应用程序都应受到 RemoteAddrValve 的保护(此 Valve 也可用作过滤器)。**allow** 属性应用于将访问限制为一组已知的受信任主机。
默认的 ErrorReportValve 在发送给客户端的响应中包含 Tomcat 版本号。为了避免这种情况,可以在每个 Web 应用程序中配置自定义错误处理。或者,您可以显式配置一个 ErrorReportValve 并将其 **showServerInfo** 属性设置为 false
。或者,可以通过创建文件 CATALINA_BASE/lib/org/apache/catalina/util/ServerInfo.properties 并将其内容设置为以下内容来更改版本号
server.info=Apache Tomcat/10.1.x
根据需要修改值。请注意,这也会更改某些管理工具中报告的版本号,并且可能难以确定安装的实际版本。CATALINA_HOME/bin/version.bat|sh 脚本仍将报告正确的版本号。
默认的 ErrorReportValve 可以在发生错误时向客户端显示堆栈跟踪和/或 JSP 源代码。为了避免这种情况,可以在每个 Web 应用程序中配置自定义错误处理。或者,您可以显式配置一个 ErrorReportValve 并将其 **showReport** 属性设置为 false
。
RewriteValve 使用正则表达式,格式不正确的正则表达式模式可能容易受到“灾难性回溯”或“ReDoS”的攻击。有关更多详细信息,请参阅 Rewrite 文档。
领域
MemoryRealm 不适合生产使用,因为对 tomcat-users.xml 的任何更改都需要重新启动 Tomcat 才能生效。
UserDatabaseRealm 不适合大规模安装。它适用于小型、相对静态的环境。
JAASRealm 并不被广泛使用,因此代码不如其他领域成熟。建议在使用此领域之前进行额外的测试。
默认情况下,领域不实现任何形式的帐户锁定。这意味着暴力攻击可能会成功。为了防止暴力攻击,应将所选领域包装在 LockOutRealm 中。
管理器
manager 组件用于生成会话 ID。
用于生成随机会话 ID 的类可以使用 **randomClass** 属性更改。
会话 ID 的长度可以使用 **sessionIdLength** 属性更改。
**persistAuthentication** 控制在重新启动或存储期间会话持久化时是否包含与会话关联的已认证主体(如果有)。
当使用 **JDBCStore** 时,会话存储应受到保护(专用凭据、适当的权限),以使只有 **JDBCStore** 能够访问持久化的会话数据。特别是,**JDBCStore** 不应通过任何可供 Web 应用程序使用的凭据访问。
集群
集群实现基于安全、可信网络进行所有集群相关网络流量的传输。在不安全、不可信网络上运行集群是不安全的。
如果您需要机密性和/或完整性保护,可以使用 EncryptInterceptor 对节点之间的流量进行加密。此拦截器无法防御在不可信网络上运行的所有风险,特别是 DoS 攻击。
web.xml
此配置适用于默认的 conf/web.xml
文件、/WEB-INF/tomcat-web.xml
文件以及 Web 应用程序中的 /WEB-INF/web.xml
文件,前提是它们定义了此处提到的组件。
DefaultServlet 配置为 readonly 设置为 true
。将其更改为 false
允许客户端删除或修改服务器上的静态资源,并上传新的资源。除非需要身份验证,否则不应更改此设置。
DefaultServlet 配置为 listings 设置为 false
。这并非因为允许目录列表被认为不安全,而是因为生成包含数千个文件的目录列表会消耗大量 CPU,从而导致 DoS 攻击。
DefaultServlet 配置为 showServerInfo 设置为 true
。当启用目录列表时,Tomcat 版本号将包含在发送给客户端的响应中。为了避免这种情况,您可以显式配置 DefaultServlet 并将其 showServerInfo 属性设置为 false。或者,可以通过创建文件 CATALINA_BASE/lib/org/apache/catalina/util/ServerInfo.properties 并添加以下内容来更改版本号
server.info=Apache Tomcat/10.1.x
根据需要修改值。请注意,这也会更改某些管理工具中报告的版本号,并且可能难以确定安装的实际版本。CATALINA_HOME/bin/version.bat|sh 脚本仍将报告正确的版本号。
CGI Servlet 默认情况下处于禁用状态。如果启用,则不应在生产系统上将调试初始化参数设置为 10
或更高,因为调试页面不安全。
在 Windows 上使用 CGI Servlet 并启用 enableCmdLineArguments
时,请仔细查看 cmdLineArgumentsDecoded
的设置,并确保它适合您的环境。默认值是安全的。不安全的配置可能会使服务器暴露于远程代码执行攻击。有关潜在风险和缓解措施的更多信息,请参阅 CGI 使用指南 中的链接。
FailedRequestFilter 可以配置并用于拒绝在请求参数解析期间发生错误的请求。如果没有此过滤器,默认行为是忽略无效或过多的参数。
HttpHeaderSecurityFilter 可用于向响应添加标头以提高安全性。如果客户端直接访问 Tomcat,则可能需要启用此过滤器及其设置的所有标头,除非您的应用程序已经设置了它们。如果通过反向代理访问 Tomcat,则此过滤器的配置需要与反向代理设置的任何标头协调。
嵌入式 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 用户进行读写,而其他用户则无权访问。