Apache Tomcat 9 (9.0.53) - Security Considerations
一、Introduction
Tomcat的安全性适用于大多数用例。某些环境可能需要更多或更少的安全配置。本文旨在为可能影响安全性的配置选项提供单一参考点,并就更改这些配置的影响提供一些注释。初衷是给Tomcat部署的安全评估提供一个考量配置清单。
SPR- single point of reference - 单一参考点
Definition of point of reference:something that is used to judge or understand something else。
Point of reference is the intentional use of one thing to indicate something else, and may refer to:
二、Non-Tomcat settings
Tomcat配置不应该是唯一的防护。系统中的其他组件(操作系统、网络、数据库等)也应受到加固。
Tomcat不应在root用户下运行。为Tomcat进程创建一个专用用户,并为该用户提供操作系统所需的最低权限。例如,不能使用Tomcat用户远程登录。
文件权限应受限。在发行版中,文件和目录不是全局可读的,并且组没有写访问权限。在类Unix的操作系统上,Tomcat使用默认的umask运行,以维护在Tomcat运行时创建的文件(例如日志文件、扩展的WAR等)的这些权限…tar.gz0027
以ASF中的Tomcat实例为例(自动部署被禁用 auto-deployment is disabled
,web应用程序被部署为分解目录exploded directories
),标准配置是所有Tomcat文件的owner是root & group 是 tomcat,同时owner具有读/写权限,group只有读权限,而全局没有权限。
但是,logs, temp and work directory的owner是Tomcat用户而不是root。这意味着即使攻击者破坏Tomcat进程,他们也无法更改Tomcat配置、部署新的web应用程序或修改现有的web应用程序。Tomcat进程以007的umask运行,以维护这些权限。
在网络层,考虑使用防火墙来限制。
JMX
JMX连接的安全性取决于JRE,不是Tomcat控制。
通常,访问控制非常有限(要么对所有只读,要么对所有读写)。Tomcat通过JMX公开大量内部信息和控制,以帮助调试、监视和管理。考虑到可用的有限访问控制,JMX访问应被视为等同于本地root/admin访问,并受到相应的限制。
几乎所有的JRE供应商提供的JMX访问控制不会记录失败的身份验证尝试,也不会在多次身份验证失败后提供帐户锁定功能。这使得暴力攻击很容易发动,也很难检测。
考虑到以上所有因素,应注意确保JMX接口(如果使用)得到适当的保护。JMX接口加固选项:
- 为所有JMX用户配置强密码;
- 将JMX监听器绑定到内网;
- 限制受信任客户端访问JMX端口;
- 提供特定于应用程序的运行状况页面,供外部监控系统使用。
三、Default web applications
General、ROOT、Documentation、Examples、Manager、Host Manager、Securing Management Applications
全部删掉
四、Security manager
The Security Manager (The Java™ Tutorials > Essential Java Classes > The Platform Environment) (oracle.com)
要么在开始的时候就用,要么就算了吧。
五、server.xml
1. General
默认的 server.xml
包含大量注释,包括注释掉的一些范例。删除这些注释可以使阅读和理解server.xml变得更加容易。
如果某组件类型未列出,则该类型没有直接影响安全性的设置。
2. Server
设置 port 属性为 -1
,关闭shutdown port。
如果没有关闭shutdown port,那么就配置强密码。
3. Listeners
使用gcc在Solaris上编译的APR Lifecycle Listener不稳定。如果在Solaris上使用APR/native connector ,请使用Sun Studio compiler。
JNI Library Loading Listener可用于加载native code。它只能用于加载受信任的库。
应根据需要启用和配置Security Lifecycle Listener。
4. Connectors
默认,一个非TLS HTTP/1.1的connector配置在端口8080上。不使用的Connectors应从server.xml中删除。
AJP Connectors 应仅在受信的网络上使用,或使用secret
属性进行保护。
AJP Connectors 阻止具有未知请求属性的转发请求。配置适当的正则表达式或属性allowedRequestAttributesPattern
,可以允许已知的安全和/或预期属性。
address属性可用于控制connector 监听哪个IP。默认情况下,connector 监听所有配置的IP。
allowTrace属性用于启用对调试有用的TRACE请求。由于某些浏览器处理 TRACE request 响应的方式会使浏览器受到XSS攻击,因此默认情况下禁用TRACE requests。
discardFacades属性设置为true
将导致为每个请求创建新的facade对象。这减少了将数据从一个请求暴露给另一个请求,应用程序中出现BUG的机会。
encodedSolidusHandling属性允许对请求URI进行非标准解析。在反向代理后面将此属性设置为非默认值可能会使攻击者绕过代理的安全设置。
maxPostSize属性控制POST请求(被转为参数)的最大尺寸。参数在请求期间会被缓存,因此默认情况下限制为2MB,以减少DOS攻击的暴露。
maxSavePostSize属性控制表单和客户端证书身份验证期间POST请求的保存。这些参数在身份验证期间(可能是几分钟)被缓存,因此默认情况下这被限制为4KB,以减少DOS攻击的风险。
maxParameterCount属性控制request中解析和存储的参数和键值对的最大数量(GET+POST)。过多的参数会被忽略。如果要拒绝此类请求,请配置FailedRequestFilter。
xpoweredBy属性控制X-Powered-By HTTP header
是否随每个请求一起发送。如果发送,则header的值包含Servlet和JSP规范版本、完整的Tomcat版本(例如ApacheTomcat/9.0)、JVM供应商的名称和JVM的版本。默认,此header处于禁用状态。此header可为合法客户端和攻击者提供有用信息。
server属性控制服务器 HTTP header
的值。Tomcat4.1.x到8.0.x的这个header的默认值是ApacheCooote/1.1。从8.5.x开始,默认情况下不设置此header。此header可以向合法客户端和攻击者提供有限的信息。
SSLEnabled、scheme和secure属性都可以独立设置。通常用于配置tomact反向代理时。这允许Tomcat查看客户端和代理之间的连接的SSL属性,而不是代理和Tomcat之间的连接。比如,客户端通过HTTPS连接到代理,代理通过HTTP连接到Tomcat。如果Tomcat有必要区分代理接收到的是安全连接还是非安全连接,那么代理必须使用单独的connector将安全和非安全请求传递给Tomcat。如果代理使用AJP,则客户端连接的SSL属性通过AJP协议传递,不需要单独的连接器。
tomcatAuthentication和tomcatAuthorization属性与AJP connectors 一起使用,来判断Tomcat是否应处理所有身份验证和授权,或者身份验证是否应委托给反向代理(身份验证用户名作为AJP协议的一部分传递给Tomcat)。
AJP连接器中的requiredSecret属性配置在Tomcat和Tomcat前面的反向代理之间的shared secret。它用于防止通过AJP协议进行未经授权的连接。
5. Host
host元素控制部署。自动部署允许管理更简单,但也使攻击者更容易部署恶意程序。自动部署由autoDeploy
和deployOnStartup
属性控制。如果两者都是false
,则只部署server.xml中定义的Contexts ,并且任何更改都需要重启Tomcat。
在web应用不受信任的托管环境中,将deployXML
属性设置为false
,忽略于web应用程序打包的任何context.xml,这些context.xml可能会尝试为web应用程序分配更高的权限。请注意,如果启用了security manager,deployXML
属性将默认为false
。
6. Context
适用于Context 元素,这些元素被定义在: file, default file, per-host file, web application context file in per-host configuration directory or inside the web application. server.xml
,context.xml
, context.xml.default
。
crossContext属性控制是否允许一个上下文访问另一个上下文的资源。默认为false
,仅可为受信任的web应用更改。
privileged 属性控制上下文是否允许使用容器提供的servlet,如Manager servlet。默认为false
,仅可为受信任的web应用更改。
allowLinking 是nested Resources element的属性控制上下文是否允许使用链接文件。如果已启用且上下文未部署,则删除上下文资源时,这些链接也跟随操作。将此设置从不区分大小写的操作系统(包括Windows)上的默认设置更改为将禁用许多安全措施,并允许直接访问WEB-INF目录。从不区分大小写的操作系统(包括Windows),变更默认值false
,将禁用许多安全措施,并允许直接访问WEB-INF目录。
sessionCookiePathUsesTrailingSlash 可用于解决许多浏览器(Internet Explorer、Safari和Edge)中的错误,以防止多应用程序共享路径前缀时,跨应用程序暴露session cookie。但是,启用此选项可能会给拥有映射到/*
的servlet的应用程序带来问题。RFC6265 第8.5节 明确指出,不同的路径不能有效将cookie与其他应用程序隔离。
7. Valves
强烈推荐配置 AccessLogValve。Tomcat 默认配置已经包含了AccessLogValve。通常,每个主机配置一个,但是根据情况也根据不同engine或context配置不同的AccessLogValve。
任何管理应用程序都应受到RemoteAddrValve的保护(该Valve 也可用作 Filter)。allow 属性用于设置受信主机。
默认的ErrorReportValve在发送给客户端的响应中包含Tomcat版本号。为避免该情况,可以在每个web应用程序中配置自定义错误处理。或者,您可以显式配置 ErrorReportValve并将其showServerInfo属性设置为false
。或者,可以变更版本号,创建文件 CATALINA_BASE/lib/org/apache/catalina/util/ServerInfo.properties
,内容如下:
server.info=Apache Tomcat/9.0.x
修改为期望的值。请注意,该更改将使管理工具中报告的版本号变更,从而在管理工具上不能正确的判断实际部署版本。CATALINA_HOME/bin/version.bat|sh
脚本仍会报告正确的版本号。
当发生错误时,默认的ErrorReportValve会向客户端显示堆栈跟踪 and/or JSP源代码。为了避免这种情况,可以在每个web应用程序中配置自定义错误处理。或者,您可以显式配置ErrorReportValve并将其showReport属性设置为false
。
RewriteValve使用正则表达式,格式不良的正则表达式模式可能容易受到“catastrophic backtracking”或“ReDoS”的攻击。有关更多详细信息,请参阅 Rewrite docs。
8. Realms
MemoryRealm不是为生产环境设计的,因为对tomcat-users.xml
的任何更改都需要重启tomcat才能生效。
JDBCRealm不建议在生产环境中使用,因为它对于所有身份验证和授权选项都是单线程的。改用DataSourceRealm。
UserDatabaseRealm不是为large-sacle部署设计的。它适用于small-scale、相对静态的环境。
JAASRealm没有被广泛使用,因此代码没有其他realms成熟。建议在使用此realm之前进行额外测试。
默认,realms不实现任何形式的帐户锁定。这意味着暴力攻击可以成功。为了防止暴力攻击,所选realm应封装在LockOutRealm中。
9. Manager
manager组件用于生成session IDs。
randomClass属性可以更改用于生成随机session ID的类。
sessionIdLength属性可以更改session ID的长度。
persistAuthentication控制在session持久化时是否包括与session关联的已验证主体。
使用JDBCStore时,会话存储应该是安全的(专用凭据、适当的权限),以便只有JDBCStore能够访问持久化的会话数据。特别是,JDBCStore不应通过web应用程序的凭据进行访问。
10. Cluster
集群实现需要基于一个安全、可信的网络,用于所有跟集群相关的网络流量。在不安全、不受信的网络上运行群集是不安全的。
如果您在一个不受信任的网络上运行,或者更愿意谨慎行事,则可以使用EncryptInterceptor 对节点之间的通信进行加密。
六、System Properties
org.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH 和org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH 系统属性允许对请求URI进行非标准解析。在反向代理后面使用这些选项可使攻击者绕过代理上的安全配置。
org.apache.catalina.connector.Response.ENFORCE_ENCODING_IN_GET_WRITER 系统属性如果禁用会影响安全性。当规范默认使用ISO-8859-1时,很多用户(违反RFC2616)试图猜测文本媒体类型的字符编码。一些浏览器会将包含ISO-8859-1字符的响应解释为UTF-7,但如果解释为UTF-7,则会触发XSS漏洞。
七、web.xml
这适用于默认文件,web应用中的文件,如果它们涉及到这些组件。conf/web.xml
、 /WEB-INF/tomcat-web.xml
、 /WEB-INF/web.xml
。
DefaultServlet 配置readonly属性为true
。变更该属性,会允许客户端删除、修改服务器上的静态资源,以及上传新资源。在没有验证的情况下,这不应被变更。
DefaultServlet 配置 listings 属性为 false
。这倒不是因为允许目录浏览会导致严重安全问题,二十创建数千文件的目录清单会占用大量CPU资源,从而导致DOS攻击。
DefaultServlet 配置 showServerInfo 属性。 当开启目录浏览,Tomcat version信息会被包含在response内,发送给客户端。要避免,可以显示的配置DefaultServlet,设置showServerInfo属性为false
。替代方案,改变版本信息。创建文件CATALINA_BASE/lib/org/apache/catalina/util/ServerInfo.properties
,内容如下:
server.info=Apache Tomcat/9.0.x
修改为期望的值。请注意,该更改将使管理工具中报告的版本号变更,从而在管理工具上不能正确的判断实际部署版本。CATALINA_HOME/bin/version.bat|sh
脚本仍会报告正确的版本号。
默认CGI Servlet 是关闭的。如果开启,在生产环境,debug initialisation parameter 不应该设置为10
或更高,因为debug 页面是不安全的。
当在Windows上开启使用了 CGI Servlet,仔细检查设置,确保它适合您的环境。默认值为secure
。不安全的配置可能使服务器暴露远程代码执行。关于潜在风险和缓解措施的进一步信息,参见CGI How To. enableCmdLineArguments
cmdLineArgumentsDecoded
。
FailedRequestFilter 可以配置并用于拒绝请求参数解析出错的请求。如果没有过滤器,默认行为是忽略无效或过多的参数。
HttpHeaderSecurityFilter 可以向response添加header以提高安全性。如果客户端直接访问Tomcat,那么您可能希望启用此filter及其设置的所有headers,除非您的应用程序已经设置了它们。如果Tomcat是通过反向代理访问的,那么该filter的配置需要与反向代理设置的hearder进行协调。
八、General
基本身份验证(BASIC)和表单身份验证(FORM)以明文形式传递用户名和密码。使用这些身份验证机制的Web应用程序在通过不受信网络时,应使用SSL。
对于攻击者来说,通过身份验证的session cookie几乎与用户密码一样有用,应提供与密码本身相同级别的保护。这意味着,通过SSL进行身份验证,直到会话结束一直使用SSL。