作爲前端開發人員,我們最關心的是性能、SEO 和 UI/UX——安全性卻經常被忽略。
我們應該記住,就安全性而言,前端現在與後端或 DevOps 承擔着同樣的責任。前端可能會發生幾千種惡意攻擊。
常見攻擊
1. 不受限制的文件上傳
這是一種將惡意文件上傳到服務器然後對系統執行的攻擊方式。攻擊可能包括:使文件系統或數據庫超載,接管完整的系統,客戶端攻擊,將攻擊轉發到後端系統或進行簡單的破壞。
2. 點擊劫持
這是一種惡意用戶誘騙正常用戶點擊網頁或不屬於該站點的元素的攻擊方式。這種攻擊可能會導致用戶在不經意間提供憑據或敏感信息、下載惡意軟件、訪問惡意網頁、在線購買產品或轉移資金。
3. XSS 攻擊
這是一種將惡意腳本以瀏覽器端腳本的形式注入網頁的攻擊方式。網站上的缺陷使這些攻擊廣泛傳播並得以成功。
4. SQL注入
這是一種通過輸入字段把惡意代碼注入到 SQL 語句中去破壞數據庫的攻擊方式。
5. 拒絕服務攻擊( DoS 攻擊)
這種攻擊方式通過用流量轟炸服務器,使目標用戶無法使用服務器或其資源。
6. 中間人攻擊或會話劫持
這種攻擊方式依靠攔截客戶端與服務器之間的通信,以竊取密碼、帳號或其他個人詳細信息。
前端編碼時要牢記的一些常見的準則
1.嚴格的用戶輸入(第一個攻擊點)
用戶輸入在本質上應始終保持嚴格,以避免諸如 SQL 注入,點擊劫持等漏洞。所以在將用戶輸入發送到後端之前,應該先對其進行驗證或清理是非常重要的。
可以通過刪除或替換上下文相關的危險字符來對數據進行清理,例如使用白名單並對輸入數據進行轉義。
但是,對於目前所有的可能性,清理和編碼並不是一件容易的事,所以可以使用以下開源庫:
DOMPurify
使用起來最簡單,只需要有一個方法就可以清除用戶的輸入。它有自定義規則的選項,並且支持HTML5、SVG 和 MathML。secure-filters
是 Salesforce 開發的一個庫,其中提供了清理 HTML、JavaScript、內聯 CSS 樣式和其他上下文的方法。如果你想在某些地方使用用戶輸入的信息,例如生成 CSS 或 JavaScript 時,特別有用。
如果是文件上傳,請務必檢查文件類型並啓用文件過濾器,並且只允許某些類型的文件上傳。
2. 當心隱藏字段或存儲在瀏覽器內存中的數據
如果你打算通過 input 的 type="hidden"
把敏感數據隱藏在頁面中或把它添加到瀏覽器的 localStorage
,sessionStorage
,cookies
中,並且認爲這是安全的,則需要重新考慮你的解決方案。
攻擊者可以輕鬆的訪問添加到瀏覽器中的所有內容。攻擊者可以打開 dev tools 並更改所有內存變量。如果你根據 localStorage
、 sessionStorage
和 cookies
值隱藏了身份驗證頁面,會怎麼樣?
瀏覽器中有 ZapProxy 之類的工具,甚至是一些檢查工具,它們可以在攻擊者找到注入腳本的方法後把這些值暴露出來,然後攻擊者就可以利用它們進一步的攻擊。
因此要避免使用 type="hidden"
,以及避免把密鑰、auth token 等過多地存儲在瀏覽器的內存中。
3. 使用強大的內容安全策略(CSP)
永遠不要信任服務器發送的“任何東西”,始終都要定義一個強大的 Content-Security-Policy HTTP 頭,該標頭僅允許某些受信任的內容在瀏覽器上執行或提供更多資源。
最好有一個白名單——允許的來源清單。即使攻擊者注入了腳本,該腳本也不會與白名單匹配,更不會執行。
例如:
content-security-policy: script-src ‘self’ https://apis.xyz.com
在這裏,應用程序僅信任來自 apis.xyz.com
和我們自己(self
)的腳本。對於其餘的來源,在控制檯中將會引發錯誤。
注意:強大的內容安全策略不能解決內聯腳本執行的問題,因此 XSS 攻擊仍然有效。
4. 啓用 XSS 保護模式
如果攻擊者以某種方式從用戶輸入中注入了惡意代碼,我們可以通過 "X-XSS-Protection": "1; mode=block"
標頭來指示瀏覽器阻止響應。
大多數現代瀏覽器默認情況下都啓用了 XSS 保護模式,但仍建議你添加 X-XSS-Protection
標頭。這有助於確保不支持 CSP 標頭的舊版瀏覽器的安全性。
5. 避免典型的 XSS 錯誤
XSS 攻擊通常可追溯到 DOM API 的 innerHTML
。例如:
document.querySelector('.tagline').innerHTML = nameFromQueryString
任何攻擊者都可以用上面的代碼行注入惡意代碼。
考慮使用 textContent
而不是 innerHTML
,以防止完全生成 HTML 輸出。如果你不生成 HTML,則無法插入 JavaScript,也許你會看到其中的內容,但什麼事也不會發生。
請密切注意最新的受信任的類型規範,以防止藉助 google 進行基於 DOM 的跨站點腳本攻擊。
就 react.js 而言,應該對 dangerouslySetInnerHTML
保持謹慎的,並且可以產生與 innerHTML
類似的影響。
注意:切勿基於用戶輸入去設置 innerHTML
的值,而應該儘可能用 textContent
代替 innerHTML
。
同樣,應正確設置 HTTP 響應頭 Content-Type
和 X-Content-Type-Options
及其預期行爲。例如不要把 JSON 數據編碼爲 text/HTML,以防止被意外執行。
6. 禁用 iframe 嵌入
禁用 iframe 可以使我們免受 clickjacking 攻擊的影響。我們應始終在請求中使用 "X-Frame-Options":"DENY"
標頭,以禁止在框架中渲染網站。
另外,我們可以用 frame-ancestors
CSP 指令,該指令可以更好地控制哪些家長可以將頁面嵌入到 iframe 中。
7. 使用模棱兩可的錯誤提示
諸如“你的密碼不正確”之類的錯誤可能不僅對用戶有用,對攻擊者同樣有幫助。他們可能會從這些錯誤中找出信息,從而幫助他們計劃下一步的行動。
在處理帳戶、電子郵件和 PII 時,我們應該嘗試使用諸如“錯誤的登錄信息”之類的模棱兩可的錯誤提示。
8. 使用驗證碼
在面向公衆的端點(登錄、註冊、聯繫)上使用驗證碼。 驗證碼是一種旨在區分人與機器人的系統,可以幫助阻止DoS(拒絕服務)攻擊。
9. 始終設置 Referrer-Policy
每當我們用定位標記或導航到離開網站的鏈接時,請確保你使用標頭策略 "Referrer-Policy": "no-referrer"
,或者在使用定位標記的情況下,設置 rel = noopener 或 noreferrer
。
如果不設置這些標頭和相關性,則目標網站可以獲得會話 token 和數據庫 ID 之類的數據。
10. 對瀏覽器功能和 API 進行限制
與 CSP 中一樣,受限域可以連接到網站,同樣的原理也可以應用於瀏覽器功能和 API。我們可以添加一個 Feature-Policy
標頭來拒絕對某些功能和 API 的訪問。
提示:把所有你不用的功能設置爲 none
。
11. 定期審覈依賴性
定期運行 npm audit
以獲取易受攻擊軟件包的列表,並對其進行升級避免安全問題。
現在 GitHub 對易受攻擊的依賴項進行標記。還可以用 Snyk 來自動檢查你的源代碼並拉取 bump 版本。
12. 分隔你的應用程序
與後端一樣,前端也可以使用微服務架構,其中單個應用被拆分爲較小的自包含組件,每個組件都單獨運行。
例如一個應用可以分爲公共部分,身份驗證部分和管理部分,每個部分都託管在單獨的子域中,例如 https://public.example.com
, https://users.example.com
和 https://admin.example.com
。
這樣可以確保減少客戶端漏洞。
注意:適當的分隔還可以防止應用的公共部分出現 XSS 漏洞,從而防止它自動破壞用戶信息。
13. 避免使用第三方服務
Google Analytics、Google Tag Manager、Intercom、Mixpanel 等第三方服務可能會使你的 Web 應用容易受到攻擊。想一想假如這些第三方服務受到損害時會怎樣。
制定強有力的 CSP 政策非常重要。 大多數第三方服務都有定義的 CSP 指令,所以請務必添加它們。
另外在添加腳本標籤時,要確保在可能的情況下包含 integrity
屬性。Subresource Integrity 功能可以驗證腳本的加密哈希,並確保沒有對其進行過篡改。
<script src= "https://example.com/example-framework.js" integrity= "sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/ux..." crossorigin= "anonymous" ></script>
慎重使用自動填充字段
存儲在瀏覽器自動填充中的個人標識信息對於用戶和攻擊者都很方便。
攻擊者可以通過添加第三方腳本,利用瀏覽器的內置自動填充功能提取電子郵件地址來構建跟蹤標識符。他們可以用這些信息建立用戶瀏覽歷史記錄配置文件,然後將其出售給壞人。
許多人甚至都不知道他們的瀏覽器自動填充功能到底存儲了哪些信息。
提示:對敏感數據禁用自動填寫表格功能。