安全性考量
目錄
簡介
預設情況下,Tomcat 被組態為對大多數使用案例合理安全。有些環境可能需要更多或更少的安全組態。此頁面提供影響安全性的組態選項的單一參考點,並提供對變更這些選項預期影響的一些評論。目的是提供在評估 Tomcat 安裝的安全性時應考慮的組態選項清單。
注意:閱讀此頁面並非閱讀和了解詳細組態文件檔的替代方案。這些屬性的更完整描述可以在相關的文件檔頁面中找到。
非 Tomcat 設定
Tomcat 組態不應是唯一的防禦措施。系統中的其他組件(作業系統、網路、資料庫等)也應受到保護。
不應以 root 使用者身分執行 Tomcat。為 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/管理員存取,並應適當限制。
大多數(全部?)JRE 廠商提供的 JMX 存取控制不會記錄失敗的驗證嘗試,也不會在重複驗證失敗後提供帳戶鎖定功能。這使得暴力攻擊容易發動且難以偵測。
考量以上所有事項,如果使用 JMX 介面,應特別注意確保其安全性。下列選項可供您考量,以確保 JMX 介面的安全性:
- 為所有 JMX 使用者設定強密碼;
- 僅將 JMX 監聽器繫結至內部網路;
- 限制可信任的用戶端存取 JMX 連接埠的網路;以及
- 提供特定於應用程式的健康狀況頁面,供外部監控系統使用。
預設 Web 應用程式
一般
Tomcat 內建許多預設啟用的網頁應用程式。過去曾在這些應用程式中發現漏洞。應移除不需要的應用程式,如此一來,如果發現其他漏洞,系統才不會面臨風險。
ROOT
ROOT 網頁應用程式會造成極低的安全性風險,但它會顯示正在使用的 Tomcat 版本。ROOT 網頁應用程式通常應從可公開存取的 Tomcat 執行個體中移除,但不是基於安全性考量,而是為了向使用者顯示更適當的預設頁面。
文件
文件網頁應用程式會造成極低的安全性風險,但它會識別正在使用的 Tomcat 版本。它通常應從可公開存取的 Tomcat 執行個體中移除。
範例
範例網頁應用程式應始終從任何安全性敏感的安裝中移除。雖然範例網頁應用程式不包含任何已知的漏洞,但已知它包含一些功能(特別是顯示所有已接收 cookie 內容並允許設定新 cookie 的 cookie 範例),攻擊者可能結合 Tomcat 執行個體上部署的其他應用程式中的漏洞,使用這些功能取得原本無法取得的其他資訊。
管理員
管理員應用程式允許遠端部署網頁應用程式,而且由於廣泛使用弱密碼和啟用管理員應用程式的可公開存取 Tomcat 執行個體,因此常成為攻擊者的目標。管理員應用程式預設無法存取,因為未設定任何具有必要存取權限的使用者。如果啟用管理員應用程式,則應遵循保護管理應用程式區段中的指南。
主機管理員
主機管理員應用程式允許建立和管理虛擬主機,包括為虛擬主機啟用管理員應用程式。主機管理員應用程式預設無法存取,因為未設定任何具有必要存取權限的使用者。如果啟用主機管理員應用程式,則應遵循保護管理應用程式區段中的指南。
保護管理應用程式
部署提供 Tomcat 執行個體管理功能的網頁應用程式時,應遵循下列準則:
- 確保任何獲准存取管理程式的使用者都有強大的密碼。
- 不要移除 LockOutRealm 的使用,它可以防止對使用者密碼的暴力攻擊。
- 在管理程式的 context.xml 檔案中設定 RemoteAddrValve,它預設限制存取至本機。如果需要遠端存取,請使用此閥門將其限制在特定 IP 位址。
安全性管理員
啟用安全性管理員會導致網路應用程式在沙盒中執行,大幅限制網路應用程式執行惡意動作的能力,例如呼叫 System.exit()、建立網路連線或存取網路應用程式根目錄和暫存目錄以外的檔案系統。但是,應該注意的是,安全性管理員無法防止某些惡意動作,例如透過無限迴圈觸發高 CPU 使用率。
啟用安全性管理員通常是為了限制潛在影響,如果攻擊者找到方法危害受信任的網路應用程式。安全性管理員也可以用來降低執行不受信任的網路應用程式的風險(例如在主機環境中),但應該注意的是,安全性管理員只會降低執行不受信任的網路應用程式的風險,並不會消除它們。如果執行多個不受信任的網路應用程式,建議將每個網路應用程式部署到個別的 Tomcat 執行個體(理想情況下是個別主機),以降低惡意網路應用程式影響其他應用程式可用性的能力。
Tomcat 已在啟用安全性管理員的情況下進行測試;但大多數 Tomcat 使用者並未使用安全性管理員執行,因此 Tomcat 在此組態中的使用者測試並未那麼完善。已經有,並且持續有觸發在安全性管理員下執行的錯誤報告。
如果啟用安全性管理員,安全性管理員施加的限制可能會中斷大多數應用程式。不應在未廣泛測試的情況下使用安全性管理員。理想情況下,應在開發週期開始時引入安全性管理員的使用,因為追蹤和修復因對成熟應用程式啟用安全性管理員而導致的問題可能會很耗時。
啟用安全性管理員會變更下列設定的預設值
- Host 元素的 deployXML 屬性的預設值變更為
false
。
server.xml
一般
預設的 server.xml 含有大量的註解,包括一些範例元件定義,這些定義已註解掉。移除這些註解,讓閱讀和理解 server.xml 變得容易許多。
如果元件類型未列出,表示沒有任何設定會直接影響該類型的安全性。
伺服器
將 port 屬性設定為 -1
會停用關閉埠。
如果關閉埠未停用,則應為 shutdown 設定強密碼。
監聽器
如果在 Solaris 上使用 gcc 編譯,APR Lifecycle Listener 會不穩定。如果在 Solaris 上使用 APR/native 連接器,請使用 Sun Studio 編譯器編譯。
JNI Library Loading Listener 可用於載入原生程式碼。它只應使用於載入受信任的函式庫。
應啟用 Security Lifecycle Listener 並適當地設定。
連接器
預設情況下,會在埠 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 攻擊的影響。若要進一步減少受到 DoS 攻擊的影響,方法是限制 FORM 驗證允許的期間,如果會話是由 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 協定進行未經授權的連線。
主機
主機元素控制部署。自動部署允許更簡單的管理,但也讓攻擊者更容易部署惡意應用程式。自動部署由 autoDeploy 和 deployOnStartup 屬性控制。如果兩者都是 false
,則只會部署在 server.xml 中定義的 Context,且任何變更都需要重新啟動 Tomcat。
在可能不信任網路應用程式的託管環境中,將 deployXML 屬性設定為 false
以忽略與網路應用程式一起封裝的任何 context.xml,這些 context.xml 可能會嘗試將更高的權限指派給網路應用程式。請注意,如果啟用安全性管理員,則 deployXML 屬性會預設為 false
。
內容
這適用於所有可以定義 Context 元素的地方:server.xml
檔案、預設的 context.xml
檔案、每個主機的 context.xml.default
檔案、每個主機設定目錄中的網路應用程式內容檔案或網路應用程式內部。
crossContext 屬性控制內容是否允許存取其他內容的資源。預設為 false
,且僅應針對受信任的網路應用程式變更。
privileged 屬性控制內容是否允許使用容器提供的 servlet,例如 Manager servlet。預設為 false
,且僅應針對受信任的網路應用程式變更。
嵌套 Resources 元素的 allowLinking 屬性控制內容是否允許使用連結的檔案。如果啟用且內容已解除部署,則刪除內容資源時會追蹤連結。在不區分大小寫作業系統(包括 Windows)上將此設定從預設的 false
變更,將會停用多項安全措施,並允許直接存取 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 也可用於 Filter)。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」的影響。請參閱 重寫文件 以取得更多詳細資料。
領域
MemoryRealm 不適用於生產用途,因為對 tomcat-users.xml 的任何變更都需要重新啟動 Tomcat 才能生效。
UserDatabaseRealm 不適用於大型安裝。它適用於小型、相對靜態的環境。
JAASRealm 使用並不廣泛,因此程式碼不如其他領域成熟。建議在使用此領域之前進行額外測試。
預設情況下,領域不會實作任何形式的帳戶鎖定。這表示暴力攻擊可能會成功。為防止暴力攻擊,應將所選領域封裝在 LockOutRealm 中。
管理員
manager 元件用於產生階段 ID。
用於產生隨機階段 ID 的類別可以用 randomClass 屬性變更。
階段 ID 的長度可以用 sessionIdLength 屬性變更。
persistAuthentication 控制與階段關聯的經過驗證主體(如果有)是否在重新啟動期間或儲存到 Store 時包含在內。
使用 JDBCStore 時,應保護階段儲存(專用憑證、適當權限),以便只有 JDBCStore 能夠存取已儲存的階段資料。特別是,不應透過任何可供網路應用程式使用的憑證存取 JDBCStore。
群集
叢集實作是基於所有叢集相關網路流量都使用安全、受信任的網路所撰寫。在不安全、不受信任的網路中執行叢集並不安全。
如果您需要機密性或完整性保護,則可以使用 EncryptInterceptor 來加密節點之間的流量。此攔截器無法防範在不受信任的網路中執行的所有風險,特別是 DoS 攻擊。
web.xml
這適用於預設的 conf/web.xml
檔案、網路應用程式中的 /WEB-INF/tomcat-web.xml
和 /WEB-INF/web.xml
檔案(如果它們定義了在此處提到的元件)。
readonly 設定為 true
時,會設定 DefaultServlet。將其變更為 false
可讓客戶端刪除或修改伺服器上的靜態資源,並上傳新資源。通常不應在未要求驗證的情況下變更此設定。
DefaultServlet 已設定為將 清單 設定為 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 在預設情況下已停用。如果已啟用,則不應在生產系統上將 debug 初始化參數設定為 10
或更高,因為 debug 頁面並不安全。
在 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
)。此目錄用於各種可能對安全性敏感的暫時檔案,包括檔案上傳和啟用反資源鎖定時的網路應用程式副本。請考慮將java.io.tmpdir
系統屬性設定為適當的安全目錄。
一般
BASIC 和 FORM 驗證會以明文傳遞使用者名稱和密碼。使用這些驗證機制的網路應用程式與透過不可信賴網路連線的用戶端應使用 SSL。
對於經過驗證的使用者,其會話 cookie 對攻擊者而言幾乎與使用者的密碼一樣有用,且應提供與密碼本身同等級的保護。這通常表示透過 SSL 進行驗證,並持續使用 SSL 直到會話結束。
Tomcat 實作的 Servlet API 檔案上傳支援可能會使用由 java.io.tmpdir
系統屬性定義的目錄(預設為 $CATALINA_BASE/temp
)來儲存暫時檔案。此位置應使用適當的檔案權限進行保護 - 通常為 Tomcat 使用者可讀寫,而其他使用者無法存取。