# 問題

在滲透測試的 report 裡面發現了一個 Application-Platform Disclosure 的一個 issue,就是在 error page 上面顯示了 tomcat 的 version:

這個來自 apache 的默認的 error page 會顯示出 Tomcat 和版本號,這要是比黑客知道用哪個 web server / 版本,會有潛在的安全問題。

平常的 spring boot application,只要把 error whitelabel 設成 false,加上沒有設置跳轉到指定的 error page 時,就會出現由 Apache 提供的默認 Error page

  • 可以在 application.properties 裡設置: server.error.whitelabel.enabled=false

# 明確修改方向

我們需要改的地方是 Tomcat 裡面的 Error Report Valve 的配置(詳細可以看官網:https://tomcat.apache.org/tomcat-9.0-doc/config/valve.html)

從上圖可以看到,我們只要把 showReportshowServerInfo 設置為 false 就可以把在錯誤頁面中顯示的 tomcat 版本號給隱藏起來。
我們可以在 project 中透過搜索找到 ErrorReportValue.class 的源碼中也看到了它們的 setter:

public void setShowReport(boolean showReport) {
        this.showReport = showReport;
    }
    public boolean isShowReport() {
        return this.showReport;
    }
    public void setShowServerInfo(boolean showServerInfo) {
        this.showServerInfo = showServerInfo;
    }
    public boolean isShowServerInfo() {
        return this.showServerInfo;
    }

# 解決方法

我們明確了知道要改的地方之後,在網上有很多的教程,比如這個:https://www.thegeekstuff.com/2013/08/hide-tomcat-version-number/
都是需要到自己的 tomcat 安裝的目錄下的 server.xml 裡更改文件這兩個 setShowreportsetShowReport 的配置。

可問題是當你用的是一個 spring boot application,裡面是 embedded tomcat 的時候,並不是在自己的 local 裡找 server.xml 或者是 tomcat-server.xml 之類的文件去改。

於是我們可以自己寫一個類去改這個配置:

  • 在 project 中建立 TomcatErrorReportValveConfiguration.class
  • 主要把 setShowreportsetShowReport 設成 false
import org.apache.catalina.valves.ErrorReportValve;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class TomcatErrorReportValveConfiguration {
    @Bean
    public WebServerFactoryCustomizer<TomcatServletWebServerFactory> errorReportValveCustomizer() {
        return factory -> factory.addContextCustomizers(context -> {
            ErrorReportValve valve = new ErrorReportValve();
            valve.setShowServerInfo(false);
            valve.setShowReport(false);
            context.getParent().getPipeline().addValve(valve);
        });
    }
}

當你重啟 app 之後,你看到的 error page 就應該不會顯示 tomcat version number 了

當然除了這個方法外,更建議自定義 Error 的頁面,這樣會更安全喔!

Reference: https://github.com/spring-projects/spring-boot/issues/21257