介紹
Pinterest 已強制在我們的 Okta 身份驗證流程中使用托管和合規裝置,使用無密碼實施,是以通路我們的工具始終需要健康的 Pinterest 裝置。
在針對科技行業同行的基于網絡釣魚的攻擊之後,Pinterest 決定采取雙管齊下的方法來抵禦類似攻擊。我們決定:
- 要求使用受管理且健康的 Pinterest 裝置通路所有 Pinterest 資源,即使擁有有效憑據也是如此
- 需要 FIDO2 憑據進行使用者身份驗證
在這篇文章中,我們将重點關注我們如何要求在我們的 Okta 身份驗證流程中使用 Pinterest 托管裝置。
圖 1:Android 裝置上的使用者無法進行身份驗證。
圖 2:macOS 上的使用者收到有關某些合規性失敗的警告。
為什麼選擇裝置 AuthN 和合規性
這一舉措背後有一些驅動力:
- 随着PinFlex WFH政策的推出,我們預計會有更多員工在辦公室外與 Pinterest 工具和服務進行互動。
- 對于面向員工的工具,Pinterest 是一家以 SaaS 為先的公司,這意味着我們的絕大多數工具都可以通過網際網路通路。這些工具将仍然可以通過網際網路通路,要麼是出于選擇,要麼是因為缺乏基于 IP 的本機白名單功能。
- 我們對以網絡為中心的安全控制的興趣已經減弱。雖然這并不意味着 VPN 或基于内部網絡的通路将完全消失,但我們認識到我們的預設立場不會強制使用者在特定網絡上通路資源,尤其是 SaaS工具。
- 我們有一組重要的安全控制,這些控制僅存在于公司管理的裝置和/或帶有 MDM 的移動 BYOD 上。
我們認為,通過確定以下幾點,要求使用受管理且健康的裝置進行身份驗證可以減輕上述一些丢失的安全邊界:
- 仿冒的使用者憑據(無論是密碼、OTP 還是推送通知)不會導緻對 Pinterest 資源的通路。
- 無法從非托管或未知裝置通路可通路 Internet 的 Pinterest 工具,包括那些可能包含敏感資料的工具。
- 托管裝置将處于加強狀态,使對手更難立足。
與 Okta 內建
在研究 Okta 中的不同內建選項時,Okta Classic 客戶發現了一些顯而易見的事情:
- MDM 提供商和 Okta 之間确實存在的現有定制裝置相關內建,例如 Device Trust with Jamf 或 WS1,并沒有為客戶提供全面的解決方案。
- 如果 Okta 客戶或潛在供應商想要與 Okta 內建以通過身份驗證流程做一些“有趣”的事情,那麼這樣做的唯一途徑是與某些外部身份提供者 (IdP)建立互信,那些“有趣”的事情可以發生。
是以,我們别無選擇,隻能建構使用者并将其路由到我們自己的自定義身份提供程式。Zuul(向Netflix 緻歉)是 Pinterest 安全團隊建構的 OIDC 身份提供程式,目的是将我們的裝置身份驗證和合規性要求納入 Okta 身份驗證流程。
圖 3:使用 idP 路由/發現的 Okta 身份驗證的進階流程圖
與該領域的一些供應商一樣,我們使用 IdP 路由/發現将我們的 IdP 與 Okta 內建,其中我們的 IdP 充當受信任的外部身份提供者。我們使用“IdP 作為 SSO”方法而不是“IdP 作為因素/MFA”方法與 Okta 內建,因為後者與我們的 FIDO2 實施相沖突。
就其核心而言,從 Okta 的角度來看,我們的 IdP 隻不過是一個合規的 OIDC IdP。但是,現在我們處于 SSO 身份驗證的關鍵路徑,可以增強整個體驗以及身份驗證請求的成功,以強制使用托管和合規裝置。
雙向 TLS 認證
任何基于裝置的解決方案都需要克服的挑戰之一是能夠将身份驗證嘗試與特定裝置相關聯。這個要求就是為什麼基于證書的方法是一個有吸引力的選擇。
我們通過我們的 MDM 解決方案向所有托管裝置(包括桌面和移動平台)頒發證書,這需要使用者進行身份驗證才能向裝置頒發證書。這使我們能夠:
- 通過在 MDM 注冊期間在頒發給裝置的 PKI 證書中編碼使用者身份,在與他們互動之前确定使用者身份(例如 FIDO2)
- 将身份驗證嘗試與實體裝置相關聯,因為證書是在注冊期間頒發給該裝置的
- 避免特定于平台的代理,因為我們在 Pinterest 支援的平台本身支援基于證書的身份驗證,是以我們能夠利用與平台無關的身份驗證方法
我們的自定義 IdP 僅支援使用用戶端證書進行 mTLS 身份驗證,使用綁定到使用者和裝置的證書。如果沒有僅分發給托管裝置的有效用戶端證書,則無法對我們的 IdP 進行身份驗證。
對于不支援互相 TLS 身份驗證的應用程式,出于後續部落格文章中所述的原因,存在一種變通方法可以恢複為基于密碼的身份驗證。
外部 IdP 解決方案的問題
另一個需要克服的障礙是 Okta 缺乏對外部身份提供者的“執行”。盡管我們可以将使用者路由到外部身份提供者,但 Okta 不提供正确強制使用身份提供者所需的工具。
Okta明确指出使用 IdP 路由和相應的 IdP 路由規則不是安全控制:
路由規則改善了最終使用者的登入體驗,但它們不提供安全增強功能。您需要獨立于您的路由規則為您的 IdP 配置使用者身份驗證政策。
這實際上意味着我們不能将外部 IdP 視為一種“可選”形式的身份驗證。在不采取任何額外步驟來強制使用外部 IdP 的情況下,通過恢複到 Okta 基于使用者名/密碼的身份驗證來繞過外部 IdP 的使用是微不足道的。
在上面的引用中,Okta 暗示将“使用者身份驗證政策”作為一種強制執行方法。如果這些引用的政策是實際的“應用程式登入政策”,那麼執行就不是問題了。不幸的是,唯一存在的 Okta 政策是“全局登入”政策,它無法解決您可能會遇到的不可避免的應用程式異常,是以不實用。
SAML 内聯挂鈎——“自定義”應用程式登入政策
SAML 内聯挂鈎允許外部服務在 SAML 斷言由 Okta 簽名之前修改 SAML 斷言。從表面上看,這與裝置身份驗證解決方案并沒有真正相關,但有一種值得注意的傳回類型引起了我們的興趣:通過傳回錯誤來拒絕通路嘗試的能力。
Okta 在 SAML Inline Hook 中發送的請求包含一些有關應用程式通路嘗試的相關資訊,包括:
- 正在通路的應用程式
- 試圖通路應用程式的使用者
- 使用者的 Okta 會話是如何建立的
在下面的示例中,請注意這兩個應用程式通路嘗試中的“會話”之間的差別。
拒絕通路嘗試(未使用外部 IdP)
{
"context":
{
"protocol":
{
"issuer":
{
"id": "app_id",
"name": "application_name",
"uri": "http://www.okta.com/<app_id>"
}
},
"session":
{
"idp":
{
"id": "okta_idp_id",
"type": "OKTA"
}
}
}
}
允許通路嘗試(使用外部 IdP)
{
"context":
{
"protocol":
{
"issuer":
{
"id": "app_id",
"name": "application_name",
"uri": "http://www.okta.com/<app_id>"
}
},
"session":
{
"idp":
{
"id": "zuul_idp_id",
"type": "SOCIAL"
}
}
}
}
這意味着我們可以以程式設計方式為每個應用程式通路嘗試做出基于通路的決定。對于應該繼續的通路嘗試,我們傳回一個空響應。對于需要拒絕的通路嘗試,我們抛出一個錯誤。換句話說,我們可以通過使用内聯挂鈎固定我們自己的自定義應用程式登入政策來克服 Okta 應用程式登入政策中存在的任何限制。
為了改善使用者體驗,我們還會在出現此錯誤時撤銷使用者的 Okta 會話。
在下面的示例中,使用者已經建立了一個 Okta 會話,其中一種方法可以繞過 IdP 路由,試圖繞過我們的裝置要求。然而,他們仍然無法通路需要我們的外部 IdP 的應用程式。
圖 4:由于未使用正确的 idP 建立 Okta 會話,SAML Inline Hook 阻止了應用程式通路嘗試
盡管 SAML Inline Hooks 對我們來說是一個很好的臨時解決方案,但這絕不是理想的。SAML 内聯挂鈎必須在每個應用程式的基礎上啟用,并且隻能在 Okta 中手動配置的應用程式上啟用,是以可能需要對應用程式進行一些重新配置。我們計劃重新配置從Okta 內建網絡下載下傳的應用程式,其唯一目的是在這些應用程式上啟用我們的 SAML 内聯挂鈎。
我們希望 Okta 能在 Okta Classic 或 OIE 中釋出一些東西,允許我們在每個應用程式的基礎上本地執行 IdP,配置也允許 FIDO2 執行。或者,可以普遍應用于每個 Okta 應用程式的用于一般身份驗證的“Inline Hook”也是一個有趣的選擇。
裝置合規性
既然每次 Okta 身份驗證嘗試都需要使用者針對我們的 IdP 進行身份驗證,我們就有機會評估裝置的健康狀況。我們合規政策的目的是執行我們的安全強化指南,以確定能夠通路我們工具的裝置群符合規定并處于強化狀态。
如果合規性失敗的裝置嘗試進行身份驗證,我們可以采取一些措施,包括向使用者發出警告,或者根據某些政策,完全阻止身份驗證嘗試。
圖 5:macOS 上的使用者收到有關某些合規性失敗的警告。
我們的合規架構允許一些對我們很重要但在其他解決方案中不常見的功能。這包括:
- 定義為代碼的政策,允許我們在必要時建立複雜的政策
- 可以根據需要考慮來自盡可能多的資料源的資料的政策。我們目前與 Splunk、Chef、Workspace One 和 osquery 內建,并計劃進行更多內建。
- 在政策失敗時執行的“操作”,我們在這篇博文中展示了其中兩個(阻止/警告)
- 使用我們現有的用于部署實驗的生産架構,在整個隊列中緩慢分片新政策的能力
下面我們建立了一個示例政策,以確定向 Okta 進行身份驗證的使用者是從他們擁有的裝置上執行此操作并使用比對的使用者名登入該裝置。
圖 6:macOS 上的使用者無法通過身份驗證,因為他們的裝置未通過示例政策“username_misma
下面是與此示例政策關聯的代碼。為了執行此評估,我們擷取從兩個不同資料源(Airwatch MDM 和 osquery)收集的資料,并将使用者名與嘗試向 Okta 進行身份驗證的人進行比較。
@device_policy(
name="username_mismatch",
decider="zuul_device_policy_username_mismatch",
actions=[PolicyAction.BLOCK],
users=["atashjian"],
devices=[PolicyScope.ALL_DEVICES],
user_exception=[],
device_exception=[],
sources=[DataSource.OSQUERY, DataSource.AIRWATCH],
staleness_threshold=2400,
platforms=[DevicePlatform.MACOS],
remediation_message="The user attempting to auth, the local username on the device, "
"and the device owner, must all match."
)
def username_mismatch(device):
'''ensure that the user that's authenticating, the user logged in on the device, and the device owner match.
'''
authenticating_user = device.username
device_logged_in_user = device.collected_data[DataSource.OSQUERY].data['results']['data']['logged_in_user']['username']
airwatch_device_owner = device.collected_data[DataSource.AIRWATCH].data['UserName']
if authenticating_user == device_logged_in_user == airwatch_device_owner:
return PolicyResult(result=PolicyEval.PASS)
else:
return PolicyResult(result=PolicyEval.FAIL,
details=f"User Authenticating: {authenticating_user}, "
f"Device Owner: {airwatch_device_owner}, "
f"Logged In User: {device_logged_in_user}")
- 更新檔狀态
- 惡意軟體檢測
- 安全代理健康
- 日志攝取健康
- 應用程式/浏覽器擴充
- 核心/系統擴充
- 根 CA
- CIS 強化指南
- 還有很多其他的東西!
結論
我們才剛剛開始我們的裝置合規之旅,還有很多工作要做,包括:
- 不斷編纂裝置合規政策
- 額外的內建,用于收集資料以及在發生故障時執行操作
- 不僅在身份驗證時,而且在持續的基礎上評估裝置合規性
- 通過在所有應用程式中啟用 SAML 内聯挂鈎來彌補 Okta 執行方面的差距
作者:Armen Tashjian | Security Engineer, Corporate Security
出處:https://medium.com/pinterest-engineering/enforcing-device-authn-compliance-at-pinterest-a74938cb089b