From a63d71ea6bba2d2ee44271537181234d33d74861 Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Fri, 20 Sep 2024 10:15:51 +0000 Subject: [PATCH] Bug 1905843, prevent unexpected use of result site origin, a=diannaS Original Revision: https://phabricator.services.mozilla.com/D215496 Differential Revision: https://phabricator.services.mozilla.com/D222921 --- caps/nsScriptSecurityManager.h | 2 - dom/security/nsContentSecurityManager.cpp | 67 +++++++++++++++++++++++ dom/security/nsContentSecurityManager.h | 1 + 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/caps/nsScriptSecurityManager.h b/caps/nsScriptSecurityManager.h index f97170b145e9..5400c9f2254c 100644 --- a/caps/nsScriptSecurityManager.h +++ b/caps/nsScriptSecurityManager.h @@ -81,8 +81,6 @@ class nsScriptSecurityManager final : public nsIScriptSecurityManager { bool aFromPrivateWindow, uint64_t aInnerWindowID = 0); - static uint32_t HashPrincipalByOrigin(nsIPrincipal* aPrincipal); - static bool GetStrictFileOriginPolicy() { return sStrictFileOriginPolicy; } void DeactivateDomainPolicy(); diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp index b36f8ac2b76b..29e3ed458270 100644 --- a/dom/security/nsContentSecurityManager.cpp +++ b/dom/security/nsContentSecurityManager.cpp @@ -27,6 +27,7 @@ #include "nsNetUtil.h" #include "nsReadableUtils.h" #include "nsSandboxFlags.h" +#include "nsScriptSecurityManager.h" #include "nsIXPConnect.h" #include "mozilla/BasePrincipal.h" @@ -1431,6 +1432,9 @@ nsresult nsContentSecurityManager::doContentSecurityCheck( rv = CheckAllowLoadByTriggeringRemoteType(aChannel); NS_ENSURE_SUCCESS(rv, rv); + rv = CheckForIncoherentResultPrincipal(aChannel); + NS_ENSURE_SUCCESS(rv, rv); + // if dealing with a redirected channel then we have already installed // streamlistener and redirect proxies and so we are done. if (loadInfo->GetInitialSecurityCheckDone()) { @@ -1713,3 +1717,66 @@ nsContentSecurityManager::PerformSecurityCheck( inAndOutListener.forget(outStreamListener); return NS_OK; } + +nsresult nsContentSecurityManager::CheckForIncoherentResultPrincipal( + nsIChannel* aChannel) { + nsCOMPtr loadInfo = aChannel->LoadInfo(); + ExtContentPolicyType contentPolicyType = + loadInfo->GetExternalContentPolicyType(); + if (contentPolicyType != ExtContentPolicyType::TYPE_DOCUMENT && + contentPolicyType != ExtContentPolicyType::TYPE_SUBDOCUMENT && + contentPolicyType != ExtContentPolicyType::TYPE_OBJECT) { + return NS_OK; + } + + nsCOMPtr resultOrPrecursor; + nsresult rv = nsScriptSecurityManager::GetScriptSecurityManager() + ->GetChannelResultPrincipalIfNotSandboxed( + aChannel, getter_AddRefs(resultOrPrecursor)); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_STATE(resultOrPrecursor); + + if (nsCOMPtr precursor = + resultOrPrecursor->GetPrecursorPrincipal()) { + resultOrPrecursor = precursor; + } + + if (!resultOrPrecursor->GetIsContentPrincipal()) { + return NS_OK; + } + + nsAutoCString resultSiteOriginNoSuffix; + rv = resultOrPrecursor->GetSiteOriginNoSuffix(resultSiteOriginNoSuffix); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr resultSiteOriginURI; + NS_NewURI(getter_AddRefs(resultSiteOriginURI), resultSiteOriginNoSuffix); + NS_ENSURE_STATE(resultSiteOriginURI); + + nsCOMPtr channelURI; + aChannel->GetURI(getter_AddRefs(channelURI)); + NS_ENSURE_STATE(channelURI); + + nsCOMPtr channelUriPrincipal = + BasePrincipal::CreateContentPrincipal(channelURI, {}); + NS_ENSURE_STATE(channelUriPrincipal); + + nsAutoCString channelUriSiteOrigin; + rv = channelUriPrincipal->GetSiteOriginNoSuffix(channelUriSiteOrigin); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr channelSiteOriginURI; + NS_NewURI(getter_AddRefs(channelSiteOriginURI), channelUriSiteOrigin); + NS_ENSURE_STATE(channelSiteOriginURI); + + if (nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin( + resultSiteOriginURI, channelSiteOriginURI) || + (!net::SchemeIsHTTP(resultSiteOriginURI) && + !net::SchemeIsHTTPS(resultSiteOriginURI) && + (net::SchemeIsHTTP(channelSiteOriginURI) || + net::SchemeIsHTTPS(channelSiteOriginURI)))) { + return NS_ERROR_CONTENT_BLOCKED; + } + + return NS_OK; +} diff --git a/dom/security/nsContentSecurityManager.h b/dom/security/nsContentSecurityManager.h index 17d42e9676f0..45757a973c15 100644 --- a/dom/security/nsContentSecurityManager.h +++ b/dom/security/nsContentSecurityManager.h @@ -87,6 +87,7 @@ class nsContentSecurityManager : public nsIContentSecurityManager, static nsresult CheckAllowLoadInPrivilegedAboutContext(nsIChannel* aChannel); static nsresult CheckChannelHasProtocolSecurityFlag(nsIChannel* aChannel); static bool CrossOriginEmbedderPolicyAllowsCredentials(nsIChannel* aChannel); + static nsresult CheckForIncoherentResultPrincipal(nsIChannel* aChannel); virtual ~nsContentSecurityManager() = default; };