Bug 1073952: inherit CSP into iframe sandbox srcdoc r=ckerschb,dveditz

MozReview-Commit-ID: KTzCLoDfYnd
This commit is contained in:
Frederik Braun 2017-01-27 01:05:00 +01:00
Родитель ca5d0ac0fd
Коммит f72672a461
12 изменённых файлов: 147 добавлений и 5 удалений

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

@ -433,6 +433,21 @@ BasePrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
return NS_OK;
}
NS_IMETHODIMP
BasePrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
{
// Never destroy an existing CSP on the principal.
// This method should only be called in rare cases.
MOZ_ASSERT(!mCSP, "do not destroy an existing CSP");
if (mCSP) {
return NS_ERROR_ALREADY_INITIALIZED;
}
mCSP = aCsp;
return NS_OK;
}
NS_IMETHODIMP
BasePrincipal::EnsureCSP(nsIDOMDocument* aDocument,
nsIContentSecurityPolicy** aCSP)

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

@ -212,6 +212,7 @@ public:
NS_IMETHOD SubsumesConsideringDomain(nsIPrincipal* other, bool* _retval) final;
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal) final;
NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override;
NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
NS_IMETHOD EnsureCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
NS_IMETHOD GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) override;
NS_IMETHOD EnsurePreloadCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;

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

@ -137,10 +137,11 @@ interface nsIPrincipal : nsISerializable
/**
* A Content Security Policy associated with this principal.
*
* Use this function to query the associated CSP with this principal.
* Please *only* use this function to *set* a CSP when you know exactly what you are doing.
* Most likely you want to call ensureCSP instead of setCSP.
*/
[noscript] readonly attribute nsIContentSecurityPolicy csp;
[noscript] attribute nsIContentSecurityPolicy csp;
/*
* Use this function to query a CSP associated with this principal.

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

@ -106,6 +106,20 @@ nsNullPrincipal::GetHashValue(uint32_t *aResult)
return NS_OK;
}
NS_IMETHODIMP
nsNullPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp) {
// Never destroy an existing CSP on the principal.
// This method should only be called in rare cases.
MOZ_ASSERT(!mCSP, "do not destroy an existing CSP");
if (mCSP) {
return NS_ERROR_ALREADY_INITIALIZED;
}
mCSP = aCsp;
return NS_OK;
}
NS_IMETHODIMP
nsNullPrincipal::GetURI(nsIURI** aURI)
{
@ -187,4 +201,3 @@ nsNullPrincipal::Write(nsIObjectOutputStream* aStream)
return NS_OK;
}

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

@ -42,6 +42,7 @@ public:
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
NS_IMETHOD GetHashValue(uint32_t* aHashValue) override;
NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
NS_IMETHOD GetURI(nsIURI** aURI) override;
NS_IMETHOD GetDomain(nsIURI** aDomain) override;
NS_IMETHOD SetDomain(nsIURI* aDomain) override;

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

@ -303,6 +303,30 @@ nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel,
attrs.StripAttributes(OriginAttributes::STRIP_ADDON_ID);
prin = nsNullPrincipal::Create(attrs);
}
// if the new NullPrincipal (above) loads an iframe[srcdoc], we
// need to inherit an existing CSP to avoid bypasses (bug 1073952).
// We continue inheriting for nested frames with e.g., data: URLs.
if (loadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_SUBDOCUMENT) {
nsCOMPtr<nsIURI> uri;
aChannel->GetURI(getter_AddRefs(uri));
nsAutoCString URISpec;
uri->GetSpec(URISpec);
bool isData = (NS_SUCCEEDED(uri->SchemeIs("data", &isData)) && isData);
if (URISpec.EqualsLiteral("about:srcdoc") || isData) {
nsCOMPtr<nsIPrincipal> principalToInherit = loadInfo->PrincipalToInherit();
if (!principalToInherit) {
principalToInherit = loadInfo->TriggeringPrincipal();
}
nsCOMPtr<nsIContentSecurityPolicy> originalCsp;
principalToInherit->GetCsp(getter_AddRefs(originalCsp));
// if the principalToInherit had a CSP,
// add it to the newly created NullPrincipal.
if (originalCsp) {
nsresult rv = prin->SetCsp(originalCsp);
NS_ENSURE_SUCCESS(rv, rv);
}
}
}
prin.forget(aPrincipal);
return NS_OK;
}
@ -335,7 +359,7 @@ nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel,
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> principalToInherit = loadInfo->PrincipalToInherit();
if (!principalToInherit) {
principalToInherit = loadInfo->TriggeringPrincipal();

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

@ -49,7 +49,7 @@ nsSystemPrincipal::GetHashValue(uint32_t *result)
return NS_OK;
}
NS_IMETHODIMP
NS_IMETHODIMP
nsSystemPrincipal::GetURI(nsIURI** aURI)
{
*aURI = nullptr;
@ -70,6 +70,15 @@ nsSystemPrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
return NS_OK;
}
NS_IMETHODIMP
nsSystemPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
{
// Never destroy an existing CSP on the principal.
// This method should only be called in rare cases.
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsSystemPrincipal::EnsureCSP(nsIDOMDocument* aDocument,
nsIContentSecurityPolicy** aCSP)

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

@ -30,6 +30,7 @@ public:
NS_IMETHOD GetDomain(nsIURI** aDomain) override;
NS_IMETHOD SetDomain(nsIURI* aDomain) override;
NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override;
NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
NS_IMETHOD EnsureCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
NS_IMETHOD GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) override;
NS_IMETHOD EnsurePreloadCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;

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

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Bug 1073952 - CSP should restrict scripts in srcdoc iframe even if sandboxed</title>
</head>
<body>
<iframe srcdoc="<img src=x onerror='parent.postMessage({result: `unexpected-csp-violation`}, `*`);'>"
sandbox="allow-scripts"></iframe>
</body>
</html>

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

@ -0,0 +1 @@
content-security-policy: default-src *;

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

@ -203,6 +203,8 @@ support-files =
file_strict_dynamic_default_src.html
file_strict_dynamic_default_src.js
file_upgrade_insecure_navigation.sjs
file_iframe_sandbox_srcdoc.html
file_iframe_sandbox_srcdoc.html^headers^
[test_base-uri.html]
[test_blob_data_schemes.html]
@ -290,3 +292,4 @@ tags = mcb
[test_strict_dynamic_parser_inserted.html]
[test_strict_dynamic_default_src.html]
[test_upgrade_insecure_navigation.html]
[test_iframe_sandbox_srcdoc.html]

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

@ -0,0 +1,62 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Bug 1073952 - CSP should restrict scripts in srcdoc iframe even if sandboxed</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display">Bug 1073952</p>
<iframe style="width:200px;height:200px;" id='cspframe'></iframe>
<script class="testbody" type="text/javascript">
// This is used to watch the blocked data bounce off CSP and allowed data
// get sent out to the wire.
function examiner() {
SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
}
examiner.prototype = {
observe: function(subject, topic, data) {
if(topic === "csp-on-violate-policy") {
var violationString = SpecialPowers.getPrivilegedProps(SpecialPowers.
do_QueryInterface(subject, "nsISupportsCString"), "data");
// the violation subject for inline script violations is unfortunately vague,
// all we can do is match the string.
if (!violationString.includes("Inline Script")) {
return
}
ok(true, "CSP inherited into sandboxed srcdoc iframe, script blocked.");
window.finish();
}
},
// must eventually call this to remove the listener,
// or mochitests might get borked.
remove: function() {
SpecialPowers.removeObserver(this, "csp-on-violate-policy");
}
}
window.examiner = new examiner();
function finish() {
window.examiner.remove();
SimpleTest.finish();
}
addEventListener("message", function(e) {
ok(false, "We should not execute JS in srcdoc iframe.");
window.finish();
})
SimpleTest.waitForExplicitFinish();
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'file_iframe_sandbox_srcdoc.html';
</script>
</body>
</html>