I'm using a same-origin iframe to load a foreign widget (tlk.io loaded through a cross-origin script). I'm trying to give the iframe/widget the lowest possible rights to isolate it from my app.
MDN gives the following warning:
Notes about sandboxing:
When the embedded document has the same origin as the embedding page, it is strongly discouraged to use both allow-scripts and allow-same-origin, as that lets the embedded document remove the sandbox attribute — making it no more secure than not using the sandbox attribute at all.
Firefox devtools show me this warning:
An iframe which has both allow-scripts and allow-same-origin for its sandbox attribute can remove its sandboxing.
My question is: in this situation (sandbox="allow-same-origin allow-scripts"
) how could an iframe remove its sanboxing? What js code would perform this?
From the iframe, I tried looking at window.opener
but it's null. window.parent
is not referring to the parent (EDIT: NOT TRUE, I was using devtools wrongly). I can't find references to the «iframe» from the iframe itself...
I'm using a same-origin iframe to load a foreign widget (tlk.io loaded through a cross-origin script). I'm trying to give the iframe/widget the lowest possible rights to isolate it from my app.
MDN gives the following warning:
Notes about sandboxing:
When the embedded document has the same origin as the embedding page, it is strongly discouraged to use both allow-scripts and allow-same-origin, as that lets the embedded document remove the sandbox attribute — making it no more secure than not using the sandbox attribute at all.
Firefox devtools show me this warning:
An iframe which has both allow-scripts and allow-same-origin for its sandbox attribute can remove its sandboxing.
My question is: in this situation (sandbox="allow-same-origin allow-scripts"
) how could an iframe remove its sanboxing? What js code would perform this?
From the iframe, I tried looking at window.opener
but it's null. window.parent
is not referring to the parent (EDIT: NOT TRUE, I was using devtools wrongly). I can't find references to the «iframe» from the iframe itself...
1 Answer
Reset to default 3You open yourself up to DOM manipulation by the iframe.
With both of those sandbox attributes, there is nothing to stop the embedded frame from replacing itself with a new iframe. An iframe with whatever privilege's it wanted enabled.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Bad Sandboxing</title>
</head>
<body>
<p>This is here to space out iframe</p>
<iframe
src="malicious_child.html"
sandbox="allow-same-origin allow-scripts"
id="mountPoint"
>
</iframe>
<p>This is here to space out iframe</p>
</body>
</html>
malicious_child.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Child</title>
</head>
<body>
<script type="text/javascript">
document.body.innerText = "Loaded into a frame.";
let parent = window.parent;
let oldIframe = parent.document.getElementById("mountPoint");
if (oldIframe != null) {
// Build a new iframe to replace the old one.
let newIframe = parent.document.createElement("iframe");
newIframe.setAttribute("src", "malicious_child.html");
newIframe.setAttribute("id", "maliciousFrame");
// Replace Old iFrame
oldIframe.replaceWith(newIframe);
} else {
// When new frame is mounted you will see this alert
alert(
"This should not happen since the original iframe did not have 'allow-modals'."
);
}
</script>
</body>
</html>
Here's a Code Sanbox with this setup.