影片

在 2015 年 F8 大會,Jonathan Gross 和 Brent Dorman 提出一些方法以加強您「Facebook 登入」整合的安全。

安全檢查清單

下列清單應視為所有使用「Facebook 登入」的應用程式至少要實行的最低需求。其他功能將視乎您的應用程式而定,而且請您務必思考如何儘可能提升您應用程式的安全性。如果應用程式不夠安全,便會失去受眾的信任,更有可能令用戶不再使用。

請勿將您的應用程式密鑰加入用戶端或可反編譯的程式碼中

以您的應用程式密鑰簽署所有伺服器對伺服器 Graph API 呼叫

在用戶端上使用不重複的短期憑證

切勿盲目相信您應用程式所用的存取憑證必定由自己的應用程式產生

在使用登入對話框時,使用狀態參數

儘可能使用我們的官方 SDK

鎖定您的 Facebook 應用程式設定,以減少應用程式的可攻擊區域

使用 HTTPS

應用程式密鑰

應用程式密鑰可用在某些登入流程來產生存取憑證,而且密鑰本身是用來讓您的應用程式僅限信賴的用戶使用。密鑰可以用來輕鬆建立應用程式存取憑證,而應用程式存取憑證可代表這個應用程式的任何用戶提出 API 要求,因此保持應用程式密鑰不被盜用極為重要。

所以,應用程式密鑰或應用程式存取憑證一律不應加入任何程式碼之中。

我們建議只應直接從您的應用程式伺服器使用應用程式存取憑證,以提供最佳安全性。若是原生應用程式,我們建議應用程式先與您自己的伺服器溝通,之後伺服器再使用應用程式存取憑證向 Facebook 提出 API 要求。因此,如果您在應用程式管理中心進階設定中的「應用程式類型」設定為 Native/Desktop,則我們會假設您的原生應用程式在二進制檔案中包含應用程式密鑰或應用程式存取憑證,而且我們不允許由應用程式存取憑證簽署的呼叫繼續運行。這個 API 將會以沒有存取憑證的形式運作。

使用 appsecret_proof 保護伺服器端呼叫

您可以要求向 Facebook API 執行的伺服器對伺服器呼叫以 appsecret_proof 參數簽署,從而減少遭惡意軟件和垃圾訊息攻擊的風險。應用程式密鑰證明是存取憑證的 sha256 雜湊值,而且會將應用程式密鑰作為密鑰。您可以前往應用程式管理中心的設定 > 基本部分找出應用程式密鑰。

產生證明

以下程式碼範例展示了 PHP 中的呼叫:

$appsecret_proof= hash_hmac('sha256', $access_token.'|'.time(), $app_secret); 

部分作業系統和程式語言會傳回一個浮點型時戳。在計算應用程式密錀證明之前,請務必將此浮點轉換為整數值。部分程式語言會將雜湊值建立為摘要物件。請務必將雜湊值表示為十六進制物件。

新增證明

您新增結果為 appsecret_proof 參數,並將其中的 appsecret_time 設定為在您對執行每個呼叫雜湊處理應用程式密鑰時所用的時戳:

curl \
  -F 'access_token=ACCESS-TOKEN' \
  -F 'appsecret_proof=APP-SECRET-PROOF' \
  -F 'appsecret_time=APP-SECRET-TIME' \
  -F 'batch=[{"method":"GET", "relative_url":"me"},{"method":"GET", "relative_url":"me/accounts"}]' \
  https://graph.facebook.com

已設定時戳的應用程式密錀證明會被視為在 5 分鐘後到期,因此建議您在執行每個 Graph API 呼叫時在線產生新的證明。

要求證明

在應用程式管理中心設定 > 進階部分的安全部分,啟用要求應用程式密鑰。啟用此選項後,我們只會允許包含 appsecret_proof 的 API 呼叫。

使用短期憑證和程式碼流程保護用戶端呼叫

在某些配置中,應用程式會在多個用戶端之間重複使用長期憑證,但請不要這樣做。請按照我們的存取憑證文件所述,改用以代碼流程產生的短期憑證。

憑證遭入侵

若要了解憑證為何遭入侵,您可以想像有一個要執行 API 呼叫的原生 iOS 應用程式,但這個應用程式沒有直接這樣做,而是與相同應用程式所擁有的伺服器溝通,使用 iOS SDK 來向這個伺服器傳遞所產生的憑證,而伺服器之後可能會使用這個憑證來執行 API 呼叫。

這個伺服器用來接收憑證的端點可能被盜用,因此其他用戶可能會將適用於其他應用程式的存取憑證傳遞給這個伺服器。這種做法顯然不安全,但我們亦有方法避免這種情況,那就是絕不假設存取憑證來自使用這些存取憑證的應用程式,而應使用除錯端點檢查這些存取憑證。

定期檢查存取憑證的有效性

如果您不使用 Facebook SDK,請定期檢查存取憑證是否有效。雖然存取憑證有預先設定的過期期限,但憑證可能會出於安全原因而提前過期。如果您沒有在自己的應用程式中使用 Facebook SDK,則務必時常自行檢查憑證的有效性(至少每天一次),以確保您應用程式所使用的憑證不會出於安全原因而提前過期。

狀態參數

如果您的網站使用 Facebook 登入對話框,則可透過 state 參數這個不重複字串抵禦跨網站偽造要求攻擊,從而保護您的應用程式。

啟用 Strict 模式

Strict 模式可防止有心人士入侵您的重新導向,藉此保護應用程式的安全。所有應用程式都必須啟用 Strict 模式。

在應用程式管理中心啟用 Strict 模式前,請在 Facebook 登入設定中採取以下動作,確保您目前的重新導向流量可正常運作:

  • 應用程式如果使用動態重新導向 URI,請使用狀態參數傳回動態資訊至數量有限的重新導向 URI。之後,將此等數量有限的重新導向 URI 逐一加入有效 OAuth 重新導向 URI 清單。

  • 應用程式如果使用數量有限的重新導向 URI,請將所有 URI 逐一加入有效 OAuth 重新導向 URI 清單。

  • 應用程式如果僅使用 Facebook JavaScript SDK,其重新導向流量已得到保護。您無須採取額外的措施。

完成這些動作後,請務必啟動 Strict 模式。

Strict 模式的運作方式

Strict 模式能預防重新導向 URI 遭到入侵,方法是從有效 OAuth 重新導向 URI 清單獲取完全相符的配對結果。舉例來說,如果您的清單含有 www.example.com,則 Strict 模式不會允許 www.example.com/token 作為有效的重新導向。另外,此模式也不會允許任何不在有效 OAuth 重新導向 URI 清單中的其他查詢參數。

使用 HTTPS

請放棄 HTTP,改用 HTTPS 作為網絡通訊協定,因為後者有使用加密,能以私密方式傳輸數據,並防止遭受竊聽攻擊。另外,這亦可防止數據在傳輸期間遭到竄改,例如被加入廣告或惡意程式碼。

由 2018 年 10 月 6 日起,所有應用程式都必須使用 HTTPS。

就 Facebook 登入啟用 JavaScript SDK

如果將使用 JavaScript SDK 登入設定切換開關設為「是」,表明您正在使用 JavaScript SDK 執行 Facebook 登入,則您託管該 SDK 的網頁網域必須與 JavaScript SDK 許可的網域清單其中一項條目相符。這樣能確保存取憑證只會傳回至已授權網域的回呼。只有 https 網頁支援使用 Facebook JavaScript SDK 進行驗證動作。

若是在 2021 年 8 月 10 日或之前建立的現有 JSSDK 整合,此清單會根據現時使用情況回填相關值。您無需採取任何操作。

若是在 2021 年 8 月 10 日之後建立的新整合,您必須在此清單加入相關值。

如果您發現應用程式的 JSSDK 網域欄位包含以 *. 開頭的網址,請作出更改並改用絕對網域網址,以加強安全。

重新導向 URI 檢查的運作方式

當有心人士在登入要求中提供未授權的 redirect_uri 參數,便會出現開放式重新導向攻擊,導致存取憑證等敏感性資料有可能透過重新導向 URI 內的查詢字串或片段洩漏出去。

您應該在自己的應用程式設定中,為自訂網絡整合提供已授權的重新導向 URI,以預防此類攻擊。履行登入要求時,系統會對比 redirect_uri 參數和此清單中的條目以作檢查。整個 URI 必須完全符合清單條目,包含所有其他參數在內,惟選用狀態參數除外,其值會被系統略過。

應用程式內瀏覽器及 JavaScript SDK

JavaScript SDK 通常會使用彈出式視窗和回呼來完成 Facebook 登入流程。部分應用程式內瀏覽器會阻擋彈出式視窗,導致此流程無法完成。出現此情況時,SDK 便會使用存取憑證,自動嘗試重新導向至觸發 SDK 的網頁。有效 OAuth 重新導向 URI 清單中必須列有此網頁的完整 URI,SDK 才能安全地執行此重新導向。

如果應用程式內瀏覽器情景對您的網頁版應用程式很重要,請在「允許的網域」內加入您登入頁面的網域,並在「有效 OAuth 重新導向 URI」內加入其完整 URI,包括路徑及查詢參數。如果您用於執行自家應用程式 Facebook 登入的 URI 有大量不同版本,可以自行在 FB.login() 呼叫中將一個 fallback_redirect_uri 指定為選項,這樣您便只需將該單一條目加入您的有效 OAuth 重新導向 URI 清單。

鎖定您的 Facebook 應用程式設定

啟用和/或停用任何應用程式不使用的驗證流程,以將可攻擊範圍減到最少。

  • 在用戶端使用程式碼產生的短期存取憑證,而非用戶端產生的憑證,或伺服器提供的長期憑證。程式碼所產生的短期存取憑證流程將要求應用程式伺服器使用程式碼來換取憑證,這樣做會比在瀏覽器中取得憑證來得安全。應用程式應儘量優先使用這個流程,這樣才會更加安全;如果應用程式只啟用這個流程,在用戶電腦上執行的惡意軟件就無法取得存取憑證及將之濫用。請參閱我們的存取憑證文件了解詳情。

  • 如果您的應用程式不會用到用戶端 OAuth 登入功能,請停用此功能。用戶端 OAuth 登入是使用 OAuth 用戶端憑證流程時的全域開關。如果您的應用程式不使用任何包含 Facebook 登入 SDK 的用戶端 OAuth 流程,您就應該停用這個流程。但請注意,如果您停用用戶端 OAuth 登入,您將無法繼續要求獲取存取憑證的權限。若要執行此設定,請前往應用程式管理中心的產品 > Facebook 登入 > 設定部分。

  • 停用網絡 OAuth 流程或指定重新導向許可名單。網絡 OAuth 登入設定可啟用任何使用 Facebook 網頁版登入對話框的 OAuth 用戶端憑證流程,以便它將憑證傳回到您自己的網站。若要執行此設定,請前往應用程式管理中心的產品 > Facebook 登入 > 設定部分。如果您不打算建立的自訂網頁版登入流程,或在網絡上使用 Facebook 登入 SDK,請停用這項設定。

  • 執行 HTTPS。此設定要求 OAuth 重新導向使用 HTTPS,並且要求所有傳回或需要存取憑證的 Facebook JavaScript SDK 呼叫只能在 HTTPS 頁面中執行。若是在 2018 年 3 月或之後建立的應用程式,則其此項設定已預設為開啟,而您必須在 2018 年 10 月 6 日或之前將所有現有應用程式改為只使用 HTTPS 網址。大多數的主要雲端應用程式託管服務商都會為您的應用程式免費提供 TLS 憑證自動配置服務。如果您自行託管應用程式,或是您的託管服務預設不提供 HTTPS,則您可使用 Let's Encrypt,為您的網域免費取得憑證。

  • 如果您的應用程式不會使用內嵌瀏覽器 OAuth 流程,請停用此功能。有些桌面版和流動版原生應用程式會在內嵌 WebView 中執行 OAuth 用戶端流程,以驗證用戶身分。如果您的應用程式不會執行此流程,請在應用程式管理中心的產品 > Facebook 登入 > 設定部分中停用此設定。

  • 若您的應用程式不會使用流動版單一登入流程,請停用此流程。如果您的應用程式無需使用 iOS 或 Android 登入功能,請在設定 > 基本當中的 iOS 及 Android 部分停用「單一登入」設定。

應用程式管理中心包含許多額外設定,以便開發人員用來關閉可能會導致安全問題的可攻擊範圍:

  • 基本 > 應用程式密鑰:如果您的應用程式密鑰不幸被盜用,您可以在此將其重設。
  • 基本 > 應用程式網域:請使用這項設定來鎖定可代表您應用程式執行 Facebook 登入的網域和子網域。
  • 進階 > 應用程式類型:當您建立流動版或桌面版原生應用程式,且當中包含應用程式密鑰時,請將這個選項設定為 Native/Desktop,以防止您的應用程式被反編譯,或您的應用程式密鑰遭竊。
  • 進階 > 伺服器 IP 許可名單:此項設定可指定 IP 位址清單,而您的應用程式密鑰可使用這些 IP 位址來執行 Graph API 調用。所有不屬於這個範圍、以您的應用程式密鑰執行的 Graph API 呼叫都會失敗。以用戶存取憑證執行的呼叫則不會受這項設定影響。
  • 進階 > 更新設定 IP 許可名單:此項設定可鎖定用戶用來修改這些應用程式至特定範圍的 IP 位址。設定家用寬頻的 IP 允許清單時,請小心處理。如果您的 IP 位址有所改變,您將無法編輯您的應用程式設定。
  • 進階 > 更新通知電郵:每當應用程式管理中心有任何應用程式設定變更時,系統便會將通知傳送到此電郵地址。
  • 進階 > 串流帖子網址安全:這個選項將防止您的應用程式發佈任何不會指回自己網域的網址。這樣做並不一定有用,特別是如果您知道您的應用程式將發佈其他網站的連結時更是如此。