[譯]讓Web應用更安全的13個小技巧

不管你是ReactAngularVue.js,仍是原生JavaScript開發者,你的代碼都有可能成爲黑客眼中的獵物。javascript

做爲一個前端開發者,咱們可能更加關注性能、SEOUI/UX,每每會忽視安全問題。前端

當你瞭解了大型框架是如何讓你對xss攻擊保持開放態度時,也許你會感受到很意外。例如,React中的dangerouslySetInnerHTML或者Angular中的bypassSecurityTrust都是一些高危操做。java

咱們須要記住,就安全而言,前端如今和後端、DevOps同樣承擔着相同的職責。前端也可能遭受到成千上萬的惡意攻擊。程序員

常見的攻擊手段

讓咱們來了解一下常見的攻擊類型有哪些。web

1. 任意文件上傳

這種攻擊方式是將惡意文件上傳到服務器中並執行,從而攻擊系統。攻擊包括:文件系統或者數據庫超載、徹底接管系統、將攻擊轉發到後端系統或者簡單的破壞。chrome

2. 點擊劫持

這是一種誘導用戶點擊非本站網頁或元素的攻擊方式。這種攻擊可能致使用戶在不經意之間提供證書或者敏感信息,下載惡意軟件,訪問惡意網頁,在線購買產品或者被偷偷轉移資產。數據庫

譯者注:簡單的說就是在用戶觀看到的網站上覆蓋一層透明的惡意網站,誘導用戶點擊惡意網站上的按鈕來觸發攻擊行爲npm

3. XSS攻擊

這是一種將惡意腳本JS腳本注入到網頁中的攻擊方式。網站上的缺陷使這些攻擊得以成功並普遍傳播。後端

4. SQL注入

這是一種經過用戶輸入將惡意的SQL注入到數據庫中,進而破壞數據庫的攻擊方式。api

5. Dos攻擊(拒絕服務)

這是一種經過流量轟炸服務器,致使正常的用戶沒法正常訪問服務器的攻擊方式。

6. 中間人攻擊或者會話劫持

這是一種攔截客戶端和服務端之間的通訊,從中竊取用戶的密碼、帳號或者任何我的詳細信息的攻擊方式。

防範手段

攻擊者將會竭盡全力的在前端尋找安全漏洞,在本文中,咱們將看到一些編寫前端代碼時安全相關的最佳實踐。

1. 嚴格的限制用戶的輸入(第一個攻擊點)

應該始終嚴格的對待用戶輸入,避免諸如SQL注入、點擊劫持等等。所以,在將用戶輸入發送到服務端以前,校驗並過濾用戶輸入是很重要的。

能夠經過刪除或替換危險的字符來過濾數據,例如,使用白名單並轉義輸入的數據。

可是,我意識到過濾和編碼用戶輸入並非一件容易的事,所以咱們可使用如下開源庫:

  • DOMPurify.僅僅使用一個函數就能夠過濾用戶的輸入。同時,也支持自定義的規則,而且支持在HTML5SVGMathML中使用。
  • secure-filters. 它提供方法去過濾HTMLJavaScript內聯CSS等等。當你想利用用戶的輸入生成JavaScript或者CSS時,這個庫特別好用。

若是是文件上傳,請務必檢查文件類型而且使用文件過濾功能僅容許某些文件類型上傳。

2. 注意隱藏保存瀏覽器內存中的數據或字段

若是咱們利用type="hidden"來隱藏頁面中敏感數據,或者把他們放到瀏覽器的localStoragesessionStoragecookies時,咱們須要謹慎的考慮這些數據是否安全。

攻擊者能夠輕鬆訪問添加到瀏覽器中的全部內容。攻擊者能夠打開開發工具並更改全部保存在內存中的變量。若是你根據localStoragesessionStoragecookies中的值隱藏了身份驗證界面,該怎麼辦?

ZapProxy這樣的工具,能夠在攻擊者找到注入腳本的方法後,將這些值暴露給攻擊者,而後攻擊者可使用它們進行進一步的攻擊。

所以,避免使用type="hidden",避免將密鑰、身份驗證令牌等儘量多的存到瀏覽器的內存中。

3. 使用CSP

永遠不要相信服務器返回的全部內容,在Http header中定義一個強大的CSP策略,僅僅容許受信任的內容在瀏覽器中執行。

最好有一個白名單列表,即便攻擊者注入了腳本,該腳本和白名單不匹配,它也不會執行。

舉個例子:

// header
content-security-policy: script-src ‘self’ https://apis.xyz.com
複製代碼

這裏定義咱們的Web應用僅僅信任https://apis.xyz.com和自己域名的腳本。對於其餘域名的資源都會在控制檯中報錯。

注意:強大CSP策略也沒辦法解決內聯腳本執行的問題,所以xss攻擊仍然存在。

你能夠在MDN網站上閱讀更詳細CSP說明。

譯者注:不只能夠在header中設置csp規則,你也能夠在meta標籤中設置。

4. 開啓XSS保護模式

若是攻擊者經過某種方式在用戶輸入中插入攻擊代碼,咱們能夠經過"X-XSS-Protection": "1; mode=block"來告訴瀏覽器阻止響應。

大多數現代瀏覽器默認狀況下都啓用了XSS保護模式,但仍建議添加X-XSS-Protection。 這有助於提升不支持CSP的舊版瀏覽器的安全性。

5. 避免典型的XSS錯誤

Dom API innerHTML常常被用做XSS攻擊的入口。例如:

document.querySelector('.tagline').innerHTML = nameFromQueryString
複製代碼

任何攻擊者均可以使用上面的代碼行注入惡意代碼。

你們能夠考慮使用textContent來代替innerHTML,避免直接生成HTML。若是你不生成HTML,那就不會有JavaScript插入到頁面中,即便你能夠在頁面中看到攻擊代碼,可是,什麼也不會發生。

密切關注Trusted Types(MDN地址),這是由google程序員開發出來的,旨在防範全部基於DOM的XSS攻擊的方案。

在React.js中,dangerouslySetInnerHTML可能產生和innerHTML相似的影響。

注意:不要直接將用戶輸入作了innerHTML的值,儘可能使用textContent

另外,咱們應該正常的設置http響應頭Content-TypeX-Content-Type-Options。例如,請勿將JSON數據編碼成text/HTML,以避免意外執行。

6. 禁用IFrame嵌入

禁用iframe能夠幫助咱們免受點擊劫持攻擊。咱們應該在header中添加"X-Frame-Options": "DENY",來禁止瀏覽器在頁面中渲染iframe

咱們也可使用CSP指令frame-ancestors,它能夠更好的控制咱們的頁面能夠被哪些父頁面經過iframe的形式來嵌套展現。

7. 通用的錯誤提示

相似"您的密碼有誤"這樣的提示對用戶很友好,同時,他對攻擊者也很友好。他們能夠經過服務端返回的錯誤信息來判斷他下一步須要進行什麼樣的攻擊。

當處理用戶的帳號、郵件、我的信息時,咱們應該嘗試使用一些模棱兩可的錯誤提示,相似「錯誤的登錄信息」。

8. 使用驗證碼

在對外的公共服務(登錄、註冊)上使用驗證碼。驗證碼的目的在於幫助咱們區分真人和機器人,而且也能夠阻止DoS攻擊。

9. 設置Referrer-Policy

當咱們使用<a>標籤或者超連接引導用戶離開咱們的網站時,確保你在請求header裏面添加了"Referrer-Policy": "no-referrer",或者在<a>標籤中添加了rel="noopener"rel="noreferrer"屬性。

當咱們不設置header或者rel屬性時,目標網站就能夠獲取到一些用戶相關的數據。

譯者注:rel=noopener保證跳轉過去的網站沒法經過window.opener竊取原來網頁的信息。rel=noreferrer做用是防止將引用者信息傳遞到目標網站。上面提到的策略你們能夠去mdn上了解一下MDN Referrer-PolicyMDN Link Type

10. 限制瀏覽器的功能或者API

就像CSP能夠限制可信的資源域名同樣,咱們也能夠限制瀏覽器提供哪些能力給咱們用。咱們能夠利用http header中的Feature-Policy字段來限制使用瀏覽器提供的功能。

提示:禁用一切你不使用的功能

譯者注:Feature-Policy是一個實驗中的header屬性,目前在chrome瀏覽器中的兼容性尚可,IESafari都不支持。具體能夠在MDN Feature-Policy中瞭解。

11. 按期審查npm依賴

常常跑一下npm audit來獲取存在漏洞的npm包列表,升級他們避免一些安全問題。

GitHub如今會標記出哪些存在漏洞的依賴。咱們也可使用Snyk來自動檢查你的源碼,而且自動升級版本號。

12. 分離你的應用

與後端同樣,咱們也擁有微服務架構,其中,將單一的Web應用轉變爲多個小型前端應用的聚合,每一個小型前端應用能夠單獨運行。

相同的原理能夠應用於前端。 例如,一個Web應用能夠分爲公共部分,身份驗證部分和後臺管理部分,每一個應用都託管在單獨的子域中,例如https://public.example.comhttps://users.example.comhttps://admin.example.com。這將減小web應用中的漏洞。

注意:適當的分隔還能夠防止應用程序公共部分出現XSS漏洞,從而防止它自動破壞用戶信息。

13. 儘可能避免使用第三方服務

一行代碼就可使用相似Google Analytics的第三方服務,同時,也可能會給你的應用帶來漏洞。想想這些第三方服務腳本被篡改的狀況。

擁有一套健全的CSP策略很重要。大多數第三方服務都有定義的CSP指令,所以請務必添加它們。

一樣,若是可能的話,請確保給你的script標籤都加上integrity屬性。子資源完整性功能(SRI)能夠驗證腳本的hash值,並確保其未被篡改。

<script src= "https://example.com/example-framework.js" integrity= "sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/ux..." crossorigin= "anonymous" ></script>
複製代碼

譯者注:將使用base64編碼事後的文件哈希值寫入你所引用的 <script><link> 標籤的 integrity 屬性值中便可啓用子資源完整性校驗功能。

仔細考慮自動填充字段

存儲在瀏覽器的自動填充裏面的用戶我的數據對用戶和攻擊者都很方便。

攻擊者添加了第三方的腳本,利用瀏覽器的自動填充來提取用戶的郵箱地址去構建追蹤標識。他們可使用這些信息創建用戶瀏覽歷史記錄配置文件,而後將其出售給壞人。

咱們許多人甚至都不知道他們的瀏覽器自動填充功能存儲了哪些信息。

提示:禁止將敏感信息自動填入表單

譯者注:MDN中也有一個web安全相關的專題,你們有興趣能夠關注一下MDN web security

關於譯者本人

我是一個莫得感情的代碼搬運工,最近搞了一個公衆號,每週會按期更新一、2篇前端文章,你們有興趣的話關注一下,咱們一塊兒交流前端知識~

好啦,翻譯完畢啦, 原文連接在此

相關文章
相關標籤/搜索