譯者:Serene
原文:Six Security Vulnerabilities from a Year of HackerOne
一年前,我們推出了在 HackerOne 上的賞金計劃,以提高 Flexport 的安全性。 HackerOne 讓我們為業余愛好者和專業滲透測試人員提供賞金來鼓勵他們發現漏洞。 于是,我們收到了近 200 份報告,包括將服務器 token 從 nginx header 中刪除 到 XSS 漏洞。 以下是 200 個報告中最有趣的 6 個漏洞。
1. 刪除按鈕中的XSS漏洞
當發起賞金計劃時,我們沒想到會收到有關 XSS 的有效報告,畢竟 React 中內置了防范這種漏洞的保護措施,不幸的是,我們收到的第一份不同尋常的報告就是關于存儲型 XSS 漏洞的。

原因
當時我們在使用 Bootbox 來顯示錯誤消息并創建確認對話框。 Bootbox 獨立于 React 管理 DOM 元素,因此不受 React 的 XSS 保護措施的影響。 所以,當將用戶輸入直接展示在確認對話框中時,就觸發了攻擊。
修復
短期的修復方案是在用戶輸入傳遞給 Bootbox 展示之前,將所有可能和 XSS 相關的標簽刪除(JSXSS 提供了一個節點模塊讓這部分變得很簡單)。正在籌備長期的解決方案是,從 Bootbox 轉移到一個基于 React 的確認模塊。
教訓
React 阻止了 XSS 不代表所有代碼都是安全的。對所有在 React 之外工作的庫都不能信任,并且要盡可能地避免使用它們。
2. Markdown 渲染中的 XSS 漏洞
在修復了 Bootbox 并檢查了我們其它類似的庫之后,我們收到了第二個 XSS 漏洞報告——這次存在于我們的 Markdown 渲染中。
原因
我們的文本框中以 <div dangerouslySetInnerHtml={{__html: marked(text)}} /> 方式支持 Markdown,回想起來,這是一個壞主意。
修復
將所有傳遞到 dangerouslySetInnerHtml 的文本都使用 XSS 過濾器,并創建一個 Lint 規則以在將來執行此操作。
教訓
使用任何帶有 dangerous 的功能時,都要嚴肅對待……
3. Target=“_blank”
在所有從 HackerOne 中收到的報告中,最令人驚訝的是標準 HTML 標簽的正常使用。

原因
當你用新標簽頁打開一個鏈接(<a target="_blank">),新打開的標簽頁可以利用 window.opener 屬性訪問初始標簽并改變它的 location 對象。攻擊者可以將原始頁面設置為登錄頁面或其他任何內容。只能將 rel="noopener noreferrer" 添加到 a 標簽中,來減輕這一類問題。
修復
通過在使用 target="_blank" 時增加 rel="nofollow me noopener noreferrer",我們修復了該問題,這樣新窗口就不能改變原始窗口的內容。另外,我們 向 ESLint 提交了一個 Lint 規則,防止以后大家犯同樣的錯誤。
教訓
這個漏洞的關鍵點是,安全是很難的。我們很容易信任像 HTML 這樣的準則,但保持警惕和懷疑同樣重要。
4. Wordpress的困境
修復完上述漏洞,我們沒有收到更多與前端相關的漏洞,然而我們在 HackerOne 的賞金計劃仍然在博客中延續。我們公司的博客在 Wordpress 上運行,也因此收到了各種各樣基于此的漏洞報告。
原因
每個博客漏洞都歸結于同樣的問題:過時的庫很容易受攻擊。 例如,JetPack 是一種廣泛使用(300萬次安裝)和推薦的插件,它承諾“保護所有 WordPress 網站的安全,增加流量,吸引讀者”,但在過去幾年中已經有許多 XSS 和其他漏洞。
修復
和所有軟件一樣,最不容易受攻擊的是不存在的代碼,其次是最新的代碼。 我們刪除了絕大多數的 Wordpress 插件(其中大部分都不知道何時安裝過),更新了其余部分插件,并訂閱 https://wpvulndb.com/ 以得到最新的報告。
5. 暴力破解 2FA
轉到我們的 Ruby on Rails 后端,我們收到了兩份值得注意的報告,都涉及了我們的雙重認證。一開始,我們收到一份報告,展示了如何通過暴力攻擊來獲得已泄露用戶的訪問權限。

原因
我們使用 Authy 作為我們的 2FA 合作伙伴,他們的 rails gem 不包括任何內置的速率限制。
修復
修復方法很簡單:我們添加了速率限制,即在多次錯誤嘗試后鎖定賬戶。
6. 繞過 2FA
最后,我們收到了一份報告,展示了對我們 2FA 的完全繞過,這使得第二重認證完全沒有起作用。攻擊者所要做的就是忽略 2FA 頁面并導航到另一個鏈接。

原因
在本文中所有的 bug 中,這一個是最難找到的。Authy rails gem hook 住 Devise (一個受歡迎的 rails 認證/用戶管理庫),并在登錄后使用以下代碼要求 2FA:
def check_request_and_redirect_to_verify_token
...
id = warden.session(resource_name)[:id]
warden.logout
warden.reset_session!
session["#{resource_name}_id"] = id
...
redirect_to verify_authy_path_for(resource_name)
end
理論上說,這個代碼在用戶成功登錄后會將其登出,并重新定向到第二重身份驗證頁面。 然而實際上,Devise 調用 authenticate? 檢查用戶是否進行了身份驗證(在此處的代碼之后運行):
def authenticate?(*args)
result = !!authenticate(*args) # Try to log the user in
yield if result && block_given?
result
end
這會讓用戶重新登錄。
修復
將 warden.logout 行更改為 sign_out 可以解決這個問題,因為 sign_out 有其他代碼來清除登錄。 我們在本地解決了這個問題,并向 Authy 提出了一項請求,以便能幫助大家解決問題。
教訓
連信譽良好的安全公司有時也會出錯,并且滲透測試也沒有好的替代品。 對我們來說,最經濟有效的方法仍然是 HackerOne。 我們發現這些報告對 Flexport 和我們的安全都具有很高的價值。
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/358/