mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-08 00:38:39 +09:00
CSP 2 - ignore (x-)frame-options if CSP with frame-ancestors directive exists
This commit is contained in:
parent
ed463cec3e
commit
a01c9abce8
13 changed files with 197 additions and 34 deletions
|
|
@ -22,6 +22,7 @@
|
|||
#include "nsIScriptError.h"
|
||||
#include "nsDocShellLoadTypes.h"
|
||||
#include "nsIMultiPartChannel.h"
|
||||
#include "mozilla/dom/nsCSPUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
|
@ -84,14 +85,6 @@ nsDSURIContentListener::DoContent(const nsACString& aContentType,
|
|||
NS_ENSURE_ARG_POINTER(aContentHandler);
|
||||
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
|
||||
|
||||
// Check whether X-Frame-Options permits us to load this content in an
|
||||
// iframe and abort the load (unless we've disabled x-frame-options
|
||||
// checking).
|
||||
if (!CheckFrameOptions(aRequest)) {
|
||||
*aAbortProcess = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*aAbortProcess = false;
|
||||
|
||||
// determine if the channel has just been retargeted to us...
|
||||
|
|
@ -265,9 +258,10 @@ nsDSURIContentListener::SetParentContentListener(
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
/* static */ bool
|
||||
nsDSURIContentListener::CheckOneFrameOptionsPolicy(nsIHttpChannel* aHttpChannel,
|
||||
const nsAString& aPolicy)
|
||||
const nsAString& aPolicy,
|
||||
nsIDocShell* aDocShell)
|
||||
{
|
||||
static const char allowFrom[] = "allow-from";
|
||||
const uint32_t allowFromLen = ArrayLength(allowFrom) - 1;
|
||||
|
|
@ -285,7 +279,7 @@ nsDSURIContentListener::CheckOneFrameOptionsPolicy(nsIHttpChannel* aHttpChannel,
|
|||
aHttpChannel->GetURI(getter_AddRefs(uri));
|
||||
|
||||
// XXXkhuey when does this happen? Is returning true safe here?
|
||||
if (!mDocShell) {
|
||||
if (!aDocShell) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -293,7 +287,7 @@ nsDSURIContentListener::CheckOneFrameOptionsPolicy(nsIHttpChannel* aHttpChannel,
|
|||
// window, if we're not the top. X-F-O: SAMEORIGIN requires that the
|
||||
// document must be same-origin with top window. X-F-O: DENY requires that
|
||||
// the document must never be framed.
|
||||
nsCOMPtr<nsPIDOMWindowOuter> thisWindow = mDocShell->GetWindow();
|
||||
nsCOMPtr<nsPIDOMWindowOuter> thisWindow = aDocShell->GetWindow();
|
||||
// If we don't have DOMWindow there is no risk of clickjacking
|
||||
if (!thisWindow) {
|
||||
return true;
|
||||
|
|
@ -313,7 +307,7 @@ nsDSURIContentListener::CheckOneFrameOptionsPolicy(nsIHttpChannel* aHttpChannel,
|
|||
// content-type docshell doesn't work because some chrome documents are
|
||||
// loaded in content docshells (see bug 593387).
|
||||
nsCOMPtr<nsIDocShellTreeItem> thisDocShellItem(
|
||||
do_QueryInterface(static_cast<nsIDocShell*>(mDocShell)));
|
||||
do_QueryInterface(static_cast<nsIDocShell*>(aDocShell)));
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentDocShellItem;
|
||||
nsCOMPtr<nsIDocShellTreeItem> curDocShellItem = thisDocShellItem;
|
||||
nsCOMPtr<nsIDocument> topDoc;
|
||||
|
|
@ -402,22 +396,66 @@ nsDSURIContentListener::CheckOneFrameOptionsPolicy(nsIHttpChannel* aHttpChannel,
|
|||
return true;
|
||||
}
|
||||
|
||||
// Ignore x-frame-options if CSP with frame-ancestors exists
|
||||
static bool
|
||||
ShouldIgnoreFrameOptions(nsIChannel* aChannel, nsIPrincipal* aPrincipal)
|
||||
{
|
||||
NS_ENSURE_TRUE(aChannel, false);
|
||||
NS_ENSURE_TRUE(aPrincipal, false);
|
||||
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
aPrincipal->GetCsp(getter_AddRefs(csp));
|
||||
if (!csp) {
|
||||
// if there is no CSP, then there is nothing to do here
|
||||
return false;
|
||||
}
|
||||
|
||||
bool enforcesFrameAncestors = false;
|
||||
csp->GetEnforcesFrameAncestors(&enforcesFrameAncestors);
|
||||
if (!enforcesFrameAncestors) {
|
||||
// if CSP does not contain frame-ancestors, then there
|
||||
// is nothing to do here.
|
||||
return false;
|
||||
}
|
||||
|
||||
// log warning to console that xfo is ignored because of CSP
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
|
||||
uint64_t innerWindowID = loadInfo ? loadInfo->GetInnerWindowID() : 0;
|
||||
const char16_t* params[] = { u"x-frame-options",
|
||||
u"frame-ancestors" };
|
||||
CSP_LogLocalizedStr(u"IgnoringSrcBecauseOfDirective",
|
||||
params, ArrayLength(params),
|
||||
EmptyString(), // no sourcefile
|
||||
EmptyString(), // no scriptsample
|
||||
0, // no linenumber
|
||||
0, // no columnnumber
|
||||
nsIScriptError::warningFlag,
|
||||
"CSP", innerWindowID);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if X-Frame-Options permits this document to be loaded as a subdocument.
|
||||
// This will iterate through and check any number of X-Frame-Options policies
|
||||
// in the request (comma-separated in a header, multiple headers, etc).
|
||||
bool
|
||||
nsDSURIContentListener::CheckFrameOptions(nsIRequest* aRequest)
|
||||
/* static */ bool
|
||||
nsDSURIContentListener::CheckFrameOptions(nsIChannel* aChannel,
|
||||
nsIDocShell* aDocShell,
|
||||
nsIPrincipal* aPrincipal)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIChannel> chan = do_QueryInterface(aRequest);
|
||||
if (!chan) {
|
||||
if (!aChannel || !aDocShell) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(chan);
|
||||
if (ShouldIgnoreFrameOptions(aChannel, aPrincipal)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
|
||||
if (!httpChannel) {
|
||||
// check if it is hiding in a multipart channel
|
||||
rv = mDocShell->GetHttpChannel(chan, getter_AddRefs(httpChannel));
|
||||
rv = nsDocShell::Cast(aDocShell)->GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -442,11 +480,11 @@ nsDSURIContentListener::CheckFrameOptions(nsIRequest* aRequest)
|
|||
nsCharSeparatedTokenizer tokenizer(xfoHeaderValue, ',');
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
const nsSubstring& tok = tokenizer.nextToken();
|
||||
if (!CheckOneFrameOptionsPolicy(httpChannel, tok)) {
|
||||
if (!CheckOneFrameOptionsPolicy(httpChannel, tok, aDocShell)) {
|
||||
// cancel the load and display about:blank
|
||||
httpChannel->Cancel(NS_BINDING_ABORTED);
|
||||
if (mDocShell) {
|
||||
nsCOMPtr<nsIWebNavigation> webNav(do_QueryObject(mDocShell));
|
||||
if (aDocShell) {
|
||||
nsCOMPtr<nsIWebNavigation> webNav(do_QueryObject(aDocShell));
|
||||
if (webNav) {
|
||||
webNav->LoadURI(u"about:blank",
|
||||
0, nullptr, nullptr, nullptr);
|
||||
|
|
@ -459,7 +497,7 @@ nsDSURIContentListener::CheckFrameOptions(nsIRequest* aRequest)
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
/* static */ void
|
||||
nsDSURIContentListener::ReportXFOViolation(nsIDocShellTreeItem* aTopDocShellItem,
|
||||
nsIURI* aThisURI,
|
||||
XFOHeader aHeader)
|
||||
|
|
|
|||
|
|
@ -28,6 +28,12 @@ public:
|
|||
|
||||
nsresult Init();
|
||||
|
||||
// Determine if X-Frame-Options allows content to be framed
|
||||
// as a subdocument
|
||||
static bool CheckFrameOptions(nsIChannel* aChannel,
|
||||
nsIDocShell* aDocShell,
|
||||
nsIPrincipal* aPrincipal);
|
||||
|
||||
protected:
|
||||
explicit nsDSURIContentListener(nsDocShell* aDocShell);
|
||||
virtual ~nsDSURIContentListener();
|
||||
|
|
@ -39,12 +45,9 @@ protected:
|
|||
mExistingJPEGStreamListener = nullptr;
|
||||
}
|
||||
|
||||
// Determine if X-Frame-Options allows content to be framed
|
||||
// as a subdocument
|
||||
bool CheckFrameOptions(nsIRequest* aRequest);
|
||||
bool CheckOneFrameOptionsPolicy(nsIHttpChannel* aHttpChannel,
|
||||
const nsAString& aPolicy);
|
||||
|
||||
static bool CheckOneFrameOptionsPolicy(nsIHttpChannel* aHttpChannel,
|
||||
const nsAString& aPolicy,
|
||||
nsIDocShell* aDocShell);
|
||||
enum XFOHeader
|
||||
{
|
||||
eDENY,
|
||||
|
|
@ -52,9 +55,9 @@ protected:
|
|||
eALLOWFROM
|
||||
};
|
||||
|
||||
void ReportXFOViolation(nsIDocShellTreeItem* aTopDocShellItem,
|
||||
nsIURI* aThisURI,
|
||||
XFOHeader aHeader);
|
||||
static void ReportXFOViolation(nsIDocShellTreeItem* aTopDocShellItem,
|
||||
nsIURI* aThisURI,
|
||||
XFOHeader aHeader);
|
||||
|
||||
protected:
|
||||
nsDocShell* mDocShell;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue