Bug 1691658 - block http redirects to data: protocol, r=necko-reviewers,ckerschb,valentin

This also adds a network.allow_redirect_to_data pref in case we need to turn
this back on for compat reasons.

Differential Revision: https://phabricator.services.mozilla.com/D173988
This commit is contained in:
Gijs Kruitbosch 2023-04-12 09:43:00 +00:00
Родитель ab8022577e
Коммит b02fe6e1e2
13 изменённых файлов: 79 добавлений и 81 удалений

Просмотреть файл

@ -88,7 +88,7 @@ BlockModuleWithWrongMimeType=Loading module from “%1$S” was blocked because
# LOCALIZATION NOTE: Do not translate "data: URI".
BlockTopLevelDataURINavigation=Navigation to toplevel data: URI not allowed (Blocked loading of: “%1$S”)
BlockSubresourceRedirectToData=Redirecting to insecure data: URI not allowed (Blocked loading of: “%1$S”)
BlockRedirectToDataURI=Redirecting to data: URI not allowed (Blocked loading of: “%1$S”)
# LOCALIZATION NOTE: Do not translate "file: URI". “%1$S” is the whole URI of the loaded file. “%2$S” is the MIME type e.g. "text/plain".
BlockFileScriptWithWrongMimeType=Loading script from file: URI (“%1$S”) was blocked because its MIME type (“%2$S”) is not a valid JavaScript MIME type.

Просмотреть файл

@ -131,10 +131,18 @@ bool nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
return true;
}
ReportBlockedDataURI(uri, loadInfo);
return false;
}
void nsContentSecurityManager::ReportBlockedDataURI(nsIURI* aURI,
nsILoadInfo* aLoadInfo,
bool aIsRedirect) {
// We're going to block the request, construct the localized error message to
// report to the console.
nsAutoCString dataSpec;
uri->GetSpec(dataSpec);
aURI->GetSpec(dataSpec);
if (dataSpec.Length() > 50) {
dataSpec.Truncate(50);
dataSpec.AppendLiteral("...");
@ -142,18 +150,20 @@ bool nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
AutoTArray<nsString, 1> params;
CopyUTF8toUTF16(NS_UnescapeURL(dataSpec), *params.AppendElement());
nsAutoString errorText;
rv = nsContentUtils::FormatLocalizedString(
nsContentUtils::eSECURITY_PROPERTIES, "BlockTopLevelDataURINavigation",
params, errorText);
NS_ENSURE_SUCCESS(rv, false);
const char* stringID =
aIsRedirect ? "BlockRedirectToDataURI" : "BlockTopLevelDataURINavigation";
nsresult rv = nsContentUtils::FormatLocalizedString(
nsContentUtils::eSECURITY_PROPERTIES, stringID, params, errorText);
if (NS_FAILED(rv)) {
return;
}
// Report the localized error message to the console for the loading
// BrowsingContext's current inner window.
RefPtr<BrowsingContext> target = loadInfo->GetBrowsingContext();
RefPtr<BrowsingContext> target = aLoadInfo->GetBrowsingContext();
nsContentUtils::ReportToConsoleByWindowID(
errorText, nsIScriptError::warningFlag, "DATA_URI_BLOCKED"_ns,
target ? target->GetCurrentInnerWindowId() : 0);
return false;
}
/* static */
@ -181,23 +191,8 @@ bool nsContentSecurityManager::AllowInsecureRedirectToDataURI(
return true;
}
nsAutoCString dataSpec;
newURI->GetSpec(dataSpec);
if (dataSpec.Length() > 50) {
dataSpec.Truncate(50);
dataSpec.AppendLiteral("...");
}
nsCOMPtr<Document> doc;
nsINode* node = loadInfo->LoadingNode();
if (node) {
doc = node->OwnerDoc();
}
AutoTArray<nsString, 1> params;
CopyUTF8toUTF16(NS_UnescapeURL(dataSpec), *params.AppendElement());
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
"DATA_URI_BLOCKED"_ns, doc,
nsContentUtils::eSECURITY_PROPERTIES,
"BlockSubresourceRedirectToData", params);
ReportBlockedDataURI(newURI, loadInfo, true);
return false;
}

Просмотреть файл

@ -39,6 +39,8 @@ class nsContentSecurityManager : public nsIContentSecurityManager,
nsIChannel* aChannel, nsCOMPtr<nsIStreamListener>& aInAndOutListener);
static bool AllowTopLevelNavigationToDataURI(nsIChannel* aChannel);
static void ReportBlockedDataURI(nsIURI* aURI, nsILoadInfo* aLoadInfo,
bool aIsRedirect = false);
static bool AllowInsecureRedirectToDataURI(nsIChannel* aNewChannel);
static void MeasureUnexpectedPrivilegedLoads(nsILoadInfo* aLoadInfo,
nsIURI* aFinalURI,

Просмотреть файл

@ -47,11 +47,25 @@ var origins =
//['https://example.com:443'],
//['https://sub1.test1.example.com:443'],
window.addEventListener("message", function(e) {
gen.next(e.data);
});
gen = runTest();
function initTest() {
// Allow all cookies, then do the actual test initialization
SpecialPowers.pushPrefEnv({
"set": [
// Some of this test relies on redirecting to data: URLs from http.
["network.allow_redirect_to_data", true],
]
}).then(initTestCallback);
}
function initTestCallback() {
window.addEventListener("message", function(e) {
gen.next(e.data);
});
gen = runTest();
gen.next();
}
function* runTest() {
var loader = document.getElementById('loader');
@ -158,9 +172,8 @@ function* runTest() {
SimpleTest.finish();
}
addLoadEvent(function() {
gen.next();
});
addLoadEvent(initTest);
</script>
</pre>
</body>

Просмотреть файл

@ -24,7 +24,8 @@ async function expectBlockedToplevelData() {
return;
}
if (ChromeUtils.getXPCOMErrorName(status) != "NS_ERROR_DOM_BAD_URI") {
if (!["NS_ERROR_DOM_BAD_URI", "NS_ERROR_CORRUPTED_CONTENT"].includes(ChromeUtils.getXPCOMErrorName(status))) {
info(ChromeUtils.getXPCOMErrorName(status));
isnot(request.URI.scheme, "data");
return;
}

Просмотреть файл

@ -12563,6 +12563,11 @@
value: 1
mirror: always
- name: network.allow_redirect_to_data
type: RelaxedAtomicBool
value: false
mirror: always
- name: network.allow_raw_sockets_in_content_processes
type: bool
value: false

Просмотреть файл

@ -1412,7 +1412,7 @@ nsresult nsHttpChannel::SetupTransaction() {
EnsureRequestContext();
HttpTrafficCategory category = CreateTrafficCategory();
std::function<void(TransactionObserverResult &&)> observer;
std::function<void(TransactionObserverResult&&)> observer;
if (mTransactionObserver) {
observer = [transactionObserver{std::move(mTransactionObserver)}](
TransactionObserverResult&& aResult) {
@ -5246,6 +5246,15 @@ nsresult nsHttpChannel::AsyncProcessRedirection(uint32_t redirectType) {
return NS_ERROR_CORRUPTED_CONTENT;
}
if (!StaticPrefs::network_allow_redirect_to_data() &&
!mLoadInfo->GetAllowInsecureRedirectToDataURI() &&
mRedirectURI->SchemeIs("data")) {
LOG(("Invalid data URI for redirect!"));
nsContentSecurityManager::ReportBlockedDataURI(mRedirectURI, mLoadInfo,
true);
return NS_ERROR_DOM_BAD_URI;
}
// Perform the URL query string stripping for redirects. We will only strip
// the query string if it is redirecting to a third-party URI in the top
// level.

Просмотреть файл

@ -33,8 +33,11 @@ support-files =
# interception, we need to explicitly enable the pref.
# Consider enabling it in StaticPrefList.yaml
# https://bugzilla.mozilla.org/show_bug.cgi?id=1816325
# Several tests rely on redirecting to data: URIs, which was allowed for a long
# time but now forbidden. So we enable it just for these tests.
prefs =
dom.serviceWorkers.enabled=true
network.allow_redirect_to_data=true
[test_trr_nat64.js]
run-sequentially = node server exceptions dont replay well

Просмотреть файл

@ -1,6 +1,10 @@
[DEFAULT]
head = head_channels_clone.js head_trr_clone.js head_http3_clone.js ../unit/head_servers.js
skip-if = socketprocess_networking
# Several tests rely on redirecting to data: URIs, which was allowed for a long
# time but now forbidden. So we enable it just for these tests.
prefs =
network.allow_redirect_to_data=true
support-files =
child_channel_id.js
!/netwerk/test/unit/test_XHR_redirects.js

Просмотреть файл

@ -1,41 +0,0 @@
[redirect-to-dataurl.any.worker.html]
expected:
if (os == "android") and fission: [OK, TIMEOUT]
[Testing data URL loading after same-origin redirection (no-cors mode)]
expected: FAIL
[Testing data URL loading after same-origin redirection (same-origin mode)]
expected: FAIL
[Testing data URL loading after cross-origin redirection (no-cors mode)]
expected: FAIL
[redirect-to-dataurl.any.html]
expected:
if (os == "android") and fission: [OK, TIMEOUT]
[Testing data URL loading after same-origin redirection (no-cors mode)]
expected: FAIL
[Testing data URL loading after same-origin redirection (same-origin mode)]
expected: FAIL
[Testing data URL loading after cross-origin redirection (no-cors mode)]
expected: FAIL
[redirect-to-dataurl.any.serviceworker.html]
expected:
if (os == "android") and fission: [TIMEOUT, OK]
[redirect-to-dataurl.any.sharedworker.html]
expected:
if (os == "android") and fission: [OK, TIMEOUT]
[Testing data URL loading after cross-origin redirection (no-cors mode)]
expected: FAIL
[Testing data URL loading after same-origin redirection (same-origin mode)]
expected: FAIL
[Testing data URL loading after same-origin redirection (no-cors mode)]
expected: FAIL

Просмотреть файл

@ -1,4 +0,0 @@
[data.window.html]
[<img> fetch that redirects to data: URL]
expected: FAIL

Просмотреть файл

@ -1,6 +1,16 @@
[redirect-to-data.html]
# This test relies on iframe.onload, which doesn't work:
# https://bugzilla.mozilla.org/show_bug.cgi?id=1194350
expected: TIMEOUT
[Loading an iframe with src=redirecting URL]
expected: FAIL
expected: TIMEOUT
[Navigating an iframe to a redirecting URL]
expected: FAIL
expected: NOTRUN
[Loading a popup directly to the redirecting URL]
expected: NOTRUN
[Loading a popup that eventually goes to the redirecting URL]
expected: NOTRUN

Просмотреть файл

@ -29,6 +29,7 @@ function test() {
SpecialPowers.pushPrefEnv(
{
set: [
["network.allow_redirect_to_data", true],
["security.data_uri.block_toplevel_data_uri_navigations", false],
// Relax the user input requirements while running this test.
["xpinstall.userActivation.required", false],