1. 程式人生 > >對於WEB應用安全,我too young了

對於WEB應用安全,我too young了

文章概要

開發 WEB 應用的同學應該不少,不知道大家平時開發中,有沒有關注過應用開發的「安全問題」。

所謂安全問題,就是開發中不要留下漏洞,給入侵者破壞者機會。

比如,我們常掛在嘴邊的安全問題有 「SQL 注入」,為了防止出現問題,一般都會使用預編譯的 SQL,而不是拼接SQL,以此來保證安全。再比如,我們一個允許使用者輸入的文字框中,會禁用程式碼的渲染,比如像

這種會被做為純文字對待。

類似需要注意的問題有很多,如果我們不留意,就會容易造成安全問題。

不過有些「洞」,是你我開發中不曾留意的。或者說你只有先意識到有這一類問題需要注意,開發的時候才會把它堵上。

比如最近開發的一個WEB 應用,公司做安全的同事幫忙看了看,就給報了幾個問題。

這裡簡單總結和各位一起分享下,歡迎留言討論。

同事給指出的問題主要有兩個:

不安全的 TRACE、OPTIONS 等方法未禁用

使用者提交的資訊裡,可以包含第三方連結,容易出現釣魚問題。

問題一:

通過TRACE、OPTIONS 方法,可以暴露不少關鍵資訊。

我們知道,HTTP 請求裡可以使用不同的 Method 來實現不同的請求功能, 比如常見的 GET/POST/PUT/DELETE 。除此之外還有一些,比如 TRACE/OPTIONS 等,每種請求簡單描述如下。詳細描述,可以檢視RFC2616(https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

)

GET 請求指定的頁面資訊,並返回實體主體。

HEAD 類似於get請求,只不過返回的響應中沒有具體的內容,用於獲取報頭

POST 向指定資源提交資料進行處理請求(例如提交表單或者上傳檔案)。資料被包含在請求體中。POST請求可能會導致新的資源的建立和/或已有資源的修改。

PUT 從客戶端向伺服器傳送的資料取代指定的文件的內容。

DELETE 請求伺服器刪除指定的頁面。

CONNECT HTTP/1.1協議中預留給能夠將連線改為管道方式的代理伺服器。

OPTIONS 允許客戶端檢視伺服器的可用內容。

TRACE 回顯伺服器收到的請求,主要用於測試或診斷

從上面內容可以看出,TRACE 方法,OPTIONS方法,一般都會返回大量和實際業務處理無關的內容,如果開放會暴露許多伺服器的關鍵資訊,可能引出安全問題。

處理方式:

對於傳統的web專案, 直接在web.xml 裡增加安全限制「security-constraint」即可。

對於 Spring Boot應用,如果是使用 Tomcat做為容器,可以通過宣告獨立的配置,實現類似web.xml的效果:

web.xml的配置

<security-constraint>
    <web-resource-collection>
        <web-resource-name>restricted methods</web-resource-name>
        <url-pattern>/*</url-pattern>
        <http-method>PUT</http-method>
        <http-method>DELETE</http-method>
        <http-method>HEAD</http-method>
        <http-method>OPTIONS</http-method>
        <http-method>TRACE</http-method>
    </web-resource-collection>
    <auth-constraint/>
</security-constraint>

Spring Boot 應用中的配置

@Configuration
public class TomcatCustomizer implements EmbeddedServletContainerCustomizer {

    @Override
    public void customize(ConfigurableEmbeddedServletContainer container) {
        TomcatEmbeddedServletContainerFactory tomcat = (TomcatEmbeddedServletContainerFactory) container;
        tomcat.setSessionTimeout(8, TimeUnit.HOURS);
        tomcat.addContextCustomizers(new ContextSecurityCustomizer());

    }
    private static class ContextSecurityCustomizer implements TomcatContextCustomizer {
        @Override
        public void customize(Context context) {
            SecurityConstraint constraint = new SecurityConstraint();
            SecurityCollection securityCollection = new SecurityCollection();
            securityCollection.setName("restricted_methods");
            securityCollection.addPattern("/*");
            securityCollection.addOmittedMethod(HttpMethod.POST.toString());
            securityCollection.addOmittedMethod(HttpMethod.GET.toString());
            constraint.addCollection(securityCollection);
            constraint.setAuthConstraint(true);
            context.addConstraint(constraint);
        }
    }

}

如果使用 Jetty,配置方式也類似。

當然,如果想要做到不與容器依賴緊耦合,還可以自己定義Filter,然後在請求中判斷請求頭裡的 Method 如果是不允許的方法,可以直接返回錯誤。

問題二:

具體是這樣,我們的應用裡允許使用者上傳圖片。上傳的圖片會儲存到物件儲存中,然後返回一個URL,最後使用者完整的資訊裡,是直接儲存了一個URL。但是,我們看到,整個上傳到提交的過程,並不是一步完成的,所以,使用者可以自行構造這個提交的請求,並將圖片的URL,替換成任意連結。

這個時候,在頁面再次渲染時,是會請求圖片URL來展示圖片的。如果是一個惡意的第三方釣魚連結,容易造成盜取使用者資訊等安全問題。

處理方式:

這個問題,一般在後端對提交的內容進行檢驗,如果有「不符合規定」的域名,就報錯。一般是維護一個白名單,判斷URL資訊在不在白名單中。

判斷一個URL的字尾,你一般用什麼方式呢?正則表示式?字串擷取?

這裡有個方式供參考,可以直接取出我們預期的域名字尾:

String host = "";
URL fullUrl = null;
        try {
            fullUrl = new URL("http://blog.tomcat8080.com/abc=def");
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        host = fullUrl.getHost();

        InternetDomainName domainName = InternetDomainName.from(host);
        String top = domainName.topPrivateDomain().toString();

這些安全技術,彷彿是和WEB開發平行的一個領域,屬於另一個工種。這些不屬於架構,與設計模式無關,也不在資料庫設計、虛擬機器優化的範圍內,但是,也是我們不得不去認真瞭解和重視的。可能不需要安全工程師那麼深入,但一些常見的安全問題要了解,類似於一個 「CheatSheet」避免自己開發的時候暴露,保證我們開發的應用安全,不被攻擊和洩露資料。對於WEB安全,我還是 too young了,歡迎各位留言述說自己的經驗。

原文連結

https://mp.weixin.qq.com/s?__biz=MzI3MTEwODc5Ng%3D%3D&mid=2650860070&idx=1&sn=be68c46b247d369dc96b079879224cef&chksm=f13295f5c6451ce3018ad0d9ba796bab68f99740985e52e53f92a78773631b73c3dec4fdd2b3&mpshare=1&scene=23&srcid=%23rd

服務推薦