diff options
author | Moonchild <moonchild@palemoon.org> | 2022-07-25 20:41:23 +0000 |
---|---|---|
committer | Moonchild <moonchild@palemoon.org> | 2022-07-25 20:41:23 +0000 |
commit | 562ff3e9abc716bef4a8276e189611d3df57d30a (patch) | |
tree | 7149aae0c33ad31ea9bb9c06ba50bd0fb7a69c0d | |
parent | 7802bdb5f78f430de34fdfd9ac899f29f9974537 (diff) | |
parent | b20b9797dcb42766f9ad114e3093cb241f4258a0 (diff) | |
download | uxp-562ff3e9abc716bef4a8276e189611d3df57d30a.tar.gz |
Merge pull request 'Implement Origin header CSRF mitigation.' (#1976) from jobbautista9/UXP:origin-csrf into master
Reviewed-on: https://repo.palemoon.org/MoonchildProductions/UXP/pulls/1976
-rw-r--r-- | modules/libpref/init/all.js | 4 | ||||
-rw-r--r-- | netwerk/protocol/http/HttpBaseChannel.cpp | 36 | ||||
-rw-r--r-- | netwerk/protocol/http/HttpBaseChannel.h | 2 | ||||
-rw-r--r-- | netwerk/protocol/http/nsHttpAtomList.h | 1 | ||||
-rw-r--r-- | netwerk/protocol/http/nsHttpChannel.cpp | 53 | ||||
-rw-r--r-- | netwerk/protocol/http/nsHttpChannel.h | 1 |
6 files changed, 82 insertions, 15 deletions
diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index f391dd4739..d17082364a 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1462,6 +1462,10 @@ pref("network.http.referer.XOriginTrimmingPolicy", 0); // 0=always send, 1=send iff base domains match, 2=send iff hosts match pref("network.http.referer.XOriginPolicy", 0); +// Include an origin header on non-GET and non-HEAD requests regardless of CORS +// 0=never send, 1=send when same-origin only, 2=always send +pref("network.http.sendOriginHeader", 0); + // Controls whether referrer attributes in <a>, <img>, <area>, <iframe>, and <link> are honoured pref("network.http.enablePerElementReferrer", true); diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp index e62ec3a2e7..0b4929bbc8 100644 --- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -1398,22 +1398,10 @@ HttpBaseChannel::SetReferrerWithPolicy(nsIURI *referrer, referrer = referrerGrip.get(); } - // - // block referrer if not on our white list... - // - static const char *const referrerWhiteList[] = { - "http", - "https", - "ftp", - nullptr - }; - match = false; - const char *const *scheme = referrerWhiteList; - for (; *scheme && !match; ++scheme) { - rv = referrer->SchemeIs(*scheme, &match); - if (NS_FAILED(rv)) return rv; + // Enforce Referrer whitelist + if (!IsReferrerSchemeAllowed(referrer)) { + return NS_OK; // kick out.... } - if (!match) return NS_OK; // kick out.... // // Handle secure referrals. @@ -2844,6 +2832,24 @@ HttpBaseChannel::AddCookiesToRequest() SetRequestHeader(nsDependentCString(nsHttp::Cookie), cookie, false); } +/* static */ +bool +HttpBaseChannel::IsReferrerSchemeAllowed(nsIURI *aReferrer) +{ + NS_ENSURE_TRUE(aReferrer, false); + + nsAutoCString scheme; + nsresult rv = aReferrer->GetScheme(scheme); + NS_ENSURE_SUCCESS(rv, false); + + if (scheme.EqualsIgnoreCase("https") || + scheme.EqualsIgnoreCase("http") || + scheme.EqualsIgnoreCase("ftp")) { + return true; + } + return false; +} + bool HttpBaseChannel::ShouldRewriteRedirectToGET(uint32_t httpStatus, nsHttpRequestHead::ParsedMethodType method) diff --git a/netwerk/protocol/http/HttpBaseChannel.h b/netwerk/protocol/http/HttpBaseChannel.h index 6b28eb455c..c915e86622 100644 --- a/netwerk/protocol/http/HttpBaseChannel.h +++ b/netwerk/protocol/http/HttpBaseChannel.h @@ -319,6 +319,8 @@ public: public: /* Necko internal use only... */ bool IsNavigation(); + static bool IsReferrerSchemeAllowed(nsIURI *aReferrer); + // Return whether upon a redirect code of httpStatus for method, the // request method should be rewritten to GET. static bool ShouldRewriteRedirectToGET(uint32_t httpStatus, diff --git a/netwerk/protocol/http/nsHttpAtomList.h b/netwerk/protocol/http/nsHttpAtomList.h index 867ac0010d..e4b22e8da3 100644 --- a/netwerk/protocol/http/nsHttpAtomList.h +++ b/netwerk/protocol/http/nsHttpAtomList.h @@ -64,6 +64,7 @@ HTTP_ATOM(Lock_Token, "Lock-Token") HTTP_ATOM(Link, "Link") HTTP_ATOM(Location, "Location") HTTP_ATOM(Max_Forwards, "Max-Forwards") +HTTP_ATOM(Origin, "Origin") HTTP_ATOM(Overwrite, "Overwrite") HTTP_ATOM(Pragma, "Pragma") HTTP_ATOM(Prefer, "Prefer") diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index 915a80fb68..ca2644f6ab 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -5710,6 +5710,7 @@ nsHttpChannel::BeginConnect() mRequestHead.SetHTTPS(isHttps); mRequestHead.SetOrigin(scheme, host, port); + SetOriginHeader(); SetGPC(); NeckoOriginAttributes originAttributes; @@ -7936,6 +7937,58 @@ nsHttpChannel::ResumeInternal() return NS_FAILED(rvTransaction) ? rvTransaction : rvCache; } +// Step 10 of HTTP-network-or-cache fetch +void +nsHttpChannel::SetOriginHeader() +{ + if (mRequestHead.IsGet() || mRequestHead.IsHead()) { + return; + } + nsAutoCString existingHeader; + Unused << mRequestHead.GetHeader(nsHttp::Origin, existingHeader); + if (!existingHeader.IsEmpty()) { + LOG(("nsHttpChannel::SetOriginHeader Origin header already present")); + return; + } + + DebugOnly<nsresult> rv; + + // Instead of consulting Preferences::GetInt() all the time we + // can cache the result to speed things up. + static int32_t sSendOriginHeader = 0; + static bool sIsInited = false; + if (!sIsInited) { + sIsInited = true; + Preferences::AddIntVarCache(&sSendOriginHeader, + "network.http.sendOriginHeader"); + } + if (sSendOriginHeader == 0) { + // Origin header suppressed by user setting + return; + } + + nsCOMPtr<nsIURI> referrer; + mLoadInfo->TriggeringPrincipal()->GetURI(getter_AddRefs(referrer)); + + nsAutoCString origin("null"); + if (referrer && IsReferrerSchemeAllowed(referrer)) { + nsContentUtils::GetASCIIOrigin(referrer, origin); + } + + // Restrict Origin to same-origin loads if requested by user + if (sSendOriginHeader == 1) { + nsAutoCString currentOrigin; + nsContentUtils::GetASCIIOrigin(mURI, currentOrigin); + if (!origin.EqualsIgnoreCase(currentOrigin.get())) { + // Origin header suppressed by user setting + return; + } + } + + rv = mRequestHead.SetHeader(nsHttp::Origin, origin, false /* merge */); + MOZ_ASSERT(NS_SUCCEEDED(rv)); +} + void nsHttpChannel::SetGPC() { diff --git a/netwerk/protocol/http/nsHttpChannel.h b/netwerk/protocol/http/nsHttpChannel.h index 6e0680178c..2681f34764 100644 --- a/netwerk/protocol/http/nsHttpChannel.h +++ b/netwerk/protocol/http/nsHttpChannel.h @@ -452,6 +452,7 @@ private: void SetPushedStream(Http2PushedStreamWrapper *stream); + void SetOriginHeader(); void SetGPC(); private: |