moebius#226: Consider blocking top level window data: URIs (part 2/2 without tests)

https://github.com/MoonchildProductions/moebius/pull/226
This commit is contained in:
janekptacijarabaci 2018-04-22 19:03:22 +02:00 committed by Roy Tam
commit 73f89fe562
16 changed files with 194 additions and 66 deletions

View file

@ -10,20 +10,16 @@
#include "nsIStreamListener.h"
#include "nsIDocument.h"
#include "nsMixedContentBlocker.h"
#include "nsNullPrincipal.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/TabChild.h"
NS_IMPL_ISUPPORTS(nsContentSecurityManager,
nsIContentSecurityManager,
nsIChannelEventSink)
/* static */ bool
nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
nsIURI* aURI,
nsContentPolicyType aContentPolicyType,
nsIPrincipal* aTriggeringPrincipal,
bool aLoadFromExternal)
nsContentSecurityManager::AllowTopLevelNavigationToDataURI(nsIChannel* aChannel)
{
// Let's block all toplevel document navigations to a data: URI.
// In all cases where the toplevel document is navigated to a
@ -36,17 +32,24 @@ nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
if (!mozilla::net::nsIOService::BlockToplevelDataUriNavigations()) {
return true;
}
if (aContentPolicyType != nsIContentPolicy::TYPE_DOCUMENT) {
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
if (!loadInfo) {
return true;
}
if (loadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_DOCUMENT) {
return true;
}
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, true);
bool isDataURI =
(NS_SUCCEEDED(aURI->SchemeIs("data", &isDataURI)) && isDataURI);
(NS_SUCCEEDED(uri->SchemeIs("data", &isDataURI)) && isDataURI);
if (!isDataURI) {
return true;
}
// Whitelist data: images as long as they are not SVGs
nsAutoCString filePath;
aURI->GetFilePath(filePath);
uri->GetFilePath(filePath);
if (StringBeginsWith(filePath, NS_LITERAL_CSTRING("image/")) &&
!StringBeginsWith(filePath, NS_LITERAL_CSTRING("image/svg+xml"))) {
return true;
@ -56,22 +59,29 @@ nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
StringBeginsWith(filePath, NS_LITERAL_CSTRING("application/json"))) {
return true;
}
if (!aLoadFromExternal &&
nsContentUtils::IsSystemPrincipal(aTriggeringPrincipal)) {
// Redirecting to a toplevel data: URI is not allowed, hence we make
// sure the RedirectChain is empty.
if (!loadInfo->GetLoadTriggeredFromExternal() &&
nsContentUtils::IsSystemPrincipal(loadInfo->TriggeringPrincipal()) &&
loadInfo->RedirectChain().IsEmpty()) {
return true;
}
nsAutoCString dataSpec;
aURI->GetSpec(dataSpec);
uri->GetSpec(dataSpec);
if (dataSpec.Length() > 50) {
dataSpec.Truncate(50);
dataSpec.AppendLiteral("...");
}
nsCOMPtr<nsITabChild> tabChild = do_QueryInterface(loadInfo->ContextForTopLevelLoad());
nsCOMPtr<nsIDocument> doc;
if (tabChild) {
doc = static_cast<mozilla::dom::TabChild*>(tabChild.get())->GetDocument();
}
NS_ConvertUTF8toUTF16 specUTF16(NS_UnescapeURL(dataSpec));
const char16_t* params[] = { specUTF16.get() };
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("DATA_URI_BLOCKED"),
// no doc available, log to browser console
nullptr,
doc,
nsContentUtils::eSECURITY_PROPERTIES,
"BlockTopLevelDataURINavigation",
params, ArrayLength(params));
@ -541,27 +551,6 @@ nsContentSecurityManager::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
}
}
// Redirecting to a toplevel data: URI is not allowed, hence we pass
// a NullPrincipal as the TriggeringPrincipal to
// AllowTopLevelNavigationToDataURI() which definitely blocks any
// data: URI load.
nsCOMPtr<nsILoadInfo> newLoadInfo = aNewChannel->GetLoadInfo();
if (newLoadInfo) {
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_GetFinalChannelURI(aNewChannel, getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> nullTriggeringPrincipal = nsNullPrincipal::Create();
if (!nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
uri,
newLoadInfo->GetExternalContentPolicyType(),
nullTriggeringPrincipal,
false)) {
// logging to console happens within AllowTopLevelNavigationToDataURI
aOldChannel->Cancel(NS_ERROR_DOM_BAD_URI);
return NS_ERROR_DOM_BAD_URI;
}
}
// Also verify that the redirecting server is allowed to redirect to the
// given URI
nsCOMPtr<nsIPrincipal> oldPrincipal;