зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1073952: inherit CSP into iframe sandbox srcdoc r=ckerschb,dveditz
MozReview-Commit-ID: KTzCLoDfYnd
This commit is contained in:
Родитель
ca5d0ac0fd
Коммит
f72672a461
|
@ -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>
|
Загрузка…
Ссылка в новой задаче