安全实验场
by EpicCoder88449 lines19.7 KB
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>安全实验场</title>
<style>
* { box-sizing: border-box; }
html, body {
margin: 0;
height: 100%;
font-family: system-ui, -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
background: #1e1e1e;
color: #ddd;
overflow: hidden;
}
.layout {
display: grid;
grid-template-rows: auto 1fr auto;
grid-template-columns: 1fr 320px;
grid-template-areas:
"toolbar toolbar"
"sandbox console"
"editor editor";
height: 100vh;
gap: 6px;
padding: 6px;
}
.toolbar {
grid-area: toolbar;
display: flex;
flex-wrap: wrap;
gap: 8px;
padding: 8px;
background: #2a2a2a;
border-radius: 8px;
align-items: center;
}
.toolbar button {
padding: 8px 14px;
font-size: 13px;
border: none;
border-radius: 6px;
background: #007aff;
color: #fff;
font-weight: 600;
cursor: pointer;
}
.toolbar button.danger { background: #ff3b30; }
.toolbar button.purple { background: #af52de; }
.toolbar button.green { background: #34c759; }
.toolbar button.gray { background: #555; }
.toolbar button:hover { filter: brightness(1.15); }
.sandbox {
grid-area: sandbox;
position: relative;
background: #fff;
border-radius: 8px;
overflow: hidden;
border: 2px solid #333;
}
.sandbox iframe {
width: 100%;
height: 100%;
border: 0;
display: block;
}
.console {
grid-area: console;
background: #111;
border-radius: 8px;
padding: 8px;
overflow-y: auto;
font-family: ui-monospace, Menlo, Consolas, monospace;
font-size: 12px;
line-height: 1.5;
border: 2px solid #333;
}
.console .line { padding: 2px 0; border-bottom: 1px solid #1e1e1e; }
.console .time { color: #666; margin-right: 6px; }
.console .info { color: #4fc3f7; }
.console .warn { color: #ffb74d; }
.console .error { color: #ff5252; }
.console .ok { color: #66bb6a; }
.editor {
grid-area: editor;
display: flex;
flex-direction: column;
background: #2a2a2a;
border-radius: 8px;
padding: 8px;
gap: 6px;
height: 180px;
}
.editor textarea {
flex: 1;
width: 100%;
resize: none;
background: #1a1a1a;
color: #ddd;
border: 1px solid #444;
border-radius: 6px;
padding: 8px;
font-family: ui-monospace, Menlo, Consolas, monospace;
font-size: 12px;
line-height: 1.5;
outline: none;
}
.editor .row {
display: flex;
gap: 8px;
align-items: center;
}
.editor .row button {
padding: 6px 14px;
font-size: 12px;
border: none;
border-radius: 6px;
background: #007aff;
color: #fff;
font-weight: 600;
cursor: pointer;
}
.editor .row button.gray { background: #555; }
.badge {
display: inline-block;
padding: 1px 6px;
border-radius: 4px;
font-size: 11px;
background: #333;
color: #aaa;
margin-left: 6px;
}
</style>
</head>
<body>
<div class="layout">
<!-- 工具栏 -->
<div class="toolbar">
<strong style="color:#fff;">🧪 安全实验场</strong>
<button class="green" id="btnReload">重载沙箱</button>
<button class="danger" id="btnTest1">测试1:原始弹窗</button>
<button class="danger" id="btnTest2">测试2:iframe 绕过</button>
<button class="purple" id="btnTest3">测试3:Shadow DOM 绕过</button>
<button class="gray" id="btnClear">清空沙箱</button>
<button class="gray" id="btnClearLog">清空日志</button>
</div>
<!-- 沙箱区 -->
<div class="sandbox">
<iframe id="sandboxFrame" sandbox="allow-scripts allow-same-origin"></iframe>
</div>
<!-- 控制台 -->
<div class="console" id="console"></div>
<!-- 代码编辑区 -->
<div class="editor">
<div class="row">
<span style="font-size:12px;color:#888;">在下方粘贴 HTML / JS,点“注入运行”:</span>
<span class="badge" id="statusBadge">沙箱就绪</span>
</div>
<textarea id="codeInput" placeholder="<script>alert('hello')</script>"></textarea>
<div class="row">
<button id="btnInject">注入运行</button>
<button class="gray" id="btnWrapDoc">包裹为完整文档</button>
</div>
</div>
</div>
<script>
// ================== 控制台 ==================
const consoleEl = document.getElementById('console');
function log(msg, type) {
const now = new Date();
const t = now.toTimeString().slice(0, 8) + '.' + String(now.getMilliseconds()).padStart(3, '0');
const line = document.createElement('div');
line.className = 'line';
line.innerHTML = `<span class="time">${t}</span><span class="${type || 'info'}">${escapeHtml(msg)}</span>`;
consoleEl.appendChild(line);
consoleEl.scrollTop = consoleEl.scrollHeight;
// 限制日志条数
while (consoleEl.children.length > 300) consoleEl.removeChild(consoleEl.firstChild);
}
function escapeHtml(s) {
return String(s).replace(/[&<>"']/g, c => ({
'&':'&','<':'<','>':'>','"':'"',"'":'''
}[c]));
}
// ================== 沙箱 ==================
const frame = document.getElementById('sandboxFrame');
const statusBadge = document.getElementById('statusBadge');
function resetSandbox() {
frame.srcdoc = `<!DOCTYPE html>
<html><head><meta charset="UTF-8"><style>
html,body{margin:0;height:100%;font-family:system-ui,sans-serif;background:#f5f5f5;color:#333;}
.tip{display:flex;align-items:center;justify-content:center;height:100%;color:#999;font-size:14px;flex-direction:column;gap:8px;}
.tip code{background:#eee;padding:2px 6px;border-radius:4px;}
</style></head><body>
<div class="tip">
<div>沙箱区域</div>
<div style="font-size:12px;">点上方按钮运行测试,或在底部注入代码</div>
</div>
</body></html>`;
statusBadge.textContent = '沙箱已重载';
log('沙箱已重载', 'ok');
}
function injectToSandbox(code) {
const doc = frame.contentDocument;
if (!doc) { log('无法访问沙箱文档', 'error'); return; }
// 清掉之前注入的(保留基本结构)
doc.open();
doc.write(code);
doc.close();
statusBadge.textContent = '已注入 ' + new Date().toTimeString().slice(0, 8);
log('已注入代码到沙箱', 'ok');
}
// ================== 预置测试 ==================
// 测试1:原始弹窗(内含自己的拦截器 v2 简化版)
function test1() {
const code = `<!DOCTYPE html>
<html><head><meta charset="UTF-8"><style>
body{margin:0;font-family:system-ui,sans-serif;background:#f5f5f5;color:#333;min-height:100vh;display:flex;align-items:center;justify-content:center;}
#block-notice{position:fixed;top:20px;left:50%;transform:translateX(-50%);background:#34c759;color:#fff;padding:10px 20px;border-radius:999px;font-weight:600;opacity:0;transition:opacity .3s;z-index:2147483647;font-size:13px;}
#block-notice.show{opacity:1;}
</style></head><body>
<h1>测试1:原始弹窗</h1>
<div id="block-notice">已阻止</div>
<script>
// === 拦截器 v2 简化版 ===
(function(){
var NOTICE='block-notice', t=null;
function notice(m){var e=document.getElementById(NOTICE);if(!e)return;e.textContent=m;e.classList.add('show');clearTimeout(t);t=setTimeout(function(){e.classList.remove('show');},2000);}
var KW=['fake-virus','无害弹窗','绕过演示','overlay'];
function has(txt){if(!txt)return false;var s=String(txt).toLowerCase();return KW.some(function(k){return s.indexOf(k.toLowerCase())>=0;});}
function susp(n){
if(!n||n.nodeType!==1)return false;
if(n.id&&has(n.id))return true;
if(n.className&&typeof n.className==='string'&&has(n.className))return true;
try{if(n.textContent&&has(n.textContent))return true;}catch(e){}
if(n.tagName==='IFRAME'){var sd=n.getAttribute&&n.getAttribute('srcdoc');if(sd&&has(sd))return true;}
if(n.querySelector&&n.querySelector('#fake-virus'))return true;
return false;
}
function scan(root,d){
if(!root||d>8)return null;
if(susp(root))return root;
if(root.children){for(var i=0;i<root.children.length;i++){var h=scan(root.children[i],d+1);if(h)return h;}}
if(root.shadowRoot){var h2=scan(root.shadowRoot,d+1);if(h2)return h2;}
return null;
}
function kill(n,m){if(!n)return;try{if(n.parentNode)n.parentNode.removeChild(n);}catch(e){}notice(m||'已阻止');}
var oa=Node.prototype.appendChild, oi=Node.prototype.insertBefore;
Node.prototype.appendChild=function(n){if(susp(n)){notice('已阻止:检测到可疑弹窗');return n;}return oa.call(this,n);};
Node.prototype.insertBefore=function(n,r){if(susp(n)){notice('已阻止:检测到可疑弹窗');return n;}return oi.call(this,n,r);};
new MutationObserver(function(ms){ms.forEach(function(m){m.addedNodes.forEach(function(n){if(susp(n))kill(n,'已阻止:检测到可疑弹窗');});});}).observe(document.documentElement,{childList:true,subtree:true,attributes:true,attributeFilter:['srcdoc','src','style','class','id']});
setInterval(function(){var h=scan(document.documentElement,0);if(h&&h!==document.documentElement&&h.parentNode)kill(h,'已阻止:检测到可疑弹窗');},400);
})();
// === 被拦截的弹窗 ===
setTimeout(function(){
var o=document.createElement('div');
o.id='fake-virus';
o.innerHTML='<div style="position:fixed;inset:0;background:rgba(0,0,0,.78);display:flex;align-items:center;justify-content:center;z-index:999999;"><div style="background:#101010;color:#fff;padding:26px;border-radius:18px;text-align:center;"><div style="color:#00ff88;font-weight:700;">⚠ 无害弹窗演示</div><div style="font-size:56px;font-weight:800;">3</div></div></div>';
document.body.appendChild(o);
}, 500);
<\/script>
</body></html>`;
injectToSandbox(code);
}
// 测试2:iframe 绕过
function test2() {
const code = `<!DOCTYPE html>
<html><head><meta charset="UTF-8"><style>
body{margin:0;font-family:system-ui,sans-serif;background:#f5f5f5;color:#333;min-height:100vh;display:flex;align-items:center;justify-content:center;}
#block-notice{position:fixed;top:20px;left:50%;transform:translateX(-50%);background:#34c759;color:#fff;padding:10px 20px;border-radius:999px;font-weight:600;opacity:0;transition:opacity .3s;z-index:2147483647;font-size:13px;}
#block-notice.show{opacity:1;}
</style></head><body>
<h1>测试2:iframe 绕过</h1>
<div id="block-notice">已阻止</div>
<script>
// === 拦截器 v2 简化版(含 iframe 监控)===
(function(){
var NOTICE='block-notice', t=null;
function notice(m){var e=document.getElementById(NOTICE);if(!e)return;e.textContent=m;e.classList.add('show');clearTimeout(t);t=setTimeout(function(){e.classList.remove('show');},2000);}
var KW=['fake-virus','无害弹窗','绕过演示','overlay'];
function has(txt){if(!txt)return false;var s=String(txt).toLowerCase();return KW.some(function(k){return s.indexOf(k.toLowerCase())>=0;});}
function susp(n){
if(!n||n.nodeType!==1)return false;
if(n.id&&has(n.id))return true;
if(n.className&&typeof n.className==='string'&&has(n.className))return true;
try{if(n.textContent&&has(n.textContent))return true;}catch(e){}
if(n.tagName==='IFRAME'){var sd=n.getAttribute&&n.getAttribute('srcdoc');if(sd&&has(sd))return true;}
if(n.querySelector&&n.querySelector('#fake-virus'))return true;
return false;
}
function scan(root,d){
if(!root||d>8)return null;
if(susp(root))return root;
if(root.children){for(var i=0;i<root.children.length;i++){var h=scan(root.children[i],d+1);if(h)return h;}}
if(root.shadowRoot){var h2=scan(root.shadowRoot,d+1);if(h2)return h2;}
return null;
}
function kill(n,m){if(!n)return;try{if(n.parentNode)n.parentNode.removeChild(n);}catch(e){}notice(m||'已阻止');}
var watched=new WeakSet();
function watchIframe(f){
if(!f||watched.has(f))return; watched.add(f);
function attach(){
var d=null; try{d=f.contentDocument||(f.contentWindow&&f.contentWindow.document);}catch(e){return;}
if(!d||!d.documentElement)return;
var h=scan(d.documentElement,0); if(h){kill(f,'已阻止:iframe 内弹窗');return;}
new MutationObserver(function(){var h2=scan(d.documentElement,0);if(h2){kill(f,'已阻止:iframe 内弹窗');}}).observe(d.documentElement,{childList:true,subtree:true,attributes:true});
}
attach(); f.addEventListener('load',attach); setTimeout(attach,50); setTimeout(attach,200); setTimeout(attach,600);
}
var oa=Node.prototype.appendChild, oi=Node.prototype.insertBefore;
Node.prototype.appendChild=function(n){if(susp(n)){notice('已阻止:检测到可疑弹窗');return n;}var r=oa.call(this,n);if(n&&n.tagName==='IFRAME')watchIframe(n);if(n&&n.querySelectorAll)n.querySelectorAll('iframe').forEach(watchIframe);return r;};
Node.prototype.insertBefore=function(n,r){if(susp(n)){notice('已阻止:检测到可疑弹窗');return n;}var x=oi.call(this,n,r);if(n&&n.tagName==='IFRAME')watchIframe(n);return x;};
new MutationObserver(function(ms){ms.forEach(function(m){m.addedNodes.forEach(function(n){if(susp(n))kill(n,'已阻止:检测到可疑弹窗');if(n&&n.tagName==='IFRAME')watchIframe(n);if(n&&n.querySelectorAll)n.querySelectorAll('iframe').forEach(watchIframe);});});}).observe(document.documentElement,{childList:true,subtree:true,attributes:true,attributeFilter:['srcdoc','src','style','class','id']});
setInterval(function(){var h=scan(document.documentElement,0);if(h&&h!==document.documentElement&&h.parentNode)kill(h,'已阻止:检测到可疑弹窗');document.querySelectorAll('iframe').forEach(watchIframe);},400);
})();
// === iframe 绕过 ===
setTimeout(function(){
var f=document.createElement('iframe');
f.style.cssText='position:fixed;inset:0;width:100%;height:100%;border:0;z-index:999999;';
f.srcdoc='<!DOCTYPE html><html><head><style>html,body{margin:0;height:100%;background:transparent;}.overlay{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,.78);}.box{padding:26px;border-radius:18px;background:#101010;color:#fff;text-align:center;font-family:sans-serif;}.title{color:#00ff88;font-weight:700;font-size:20px;}.count{font-size:56px;font-weight:800;}.tip{color:#aaa;font-size:13px;}<\/style><\/head><body><div class="overlay"><div class="box"><div class="title">⚠ 绕过演示</div><div class="count" id="c">3</div><div class="tip">iframe 隔离</div></div></div><script>(function(){var e=document.getElementById("c"),n=3,t=setInterval(function(){n--;if(n>0){e.textContent=n;}else{clearInterval(t);}},1000);})();<\/script></body></html>';
document.body.appendChild(f);
}, 500);
<\/script>
</body></html>`;
injectToSandbox(code);
}
// 测试3:Shadow DOM 绕过
function test3() {
const code = `<!DOCTYPE html>
<html><head><meta charset="UTF-8"><style>
body{margin:0;font-family:system-ui,sans-serif;background:#f5f5f5;color:#333;min-height:100vh;display:flex;align-items:center;justify-content:center;}
#block-notice{position:fixed;top:20px;left:50%;transform:translateX(-50%);background:#34c759;color:#fff;padding:10px 20px;border-radius:999px;font-weight:600;opacity:0;transition:opacity .3s;z-index:2147483647;font-size:13px;}
#block-notice.show{opacity:1;}
</style></head><body>
<h1>测试3:Shadow DOM 绕过</h1>
<div id="block-notice">已阻止</div>
<script>
// === 拦截器 v2 简化版(含 shadowRoot 扫描)===
(function(){
var NOTICE='block-notice', t=null;
function notice(m){var e=document.getElementById(NOTICE);if(!e)return;e.textContent=m;e.classList.add('show');clearTimeout(t);t=setTimeout(function(){e.classList.remove('show');},2000);}
var KW=['fake-virus','无害弹窗','绕过演示','overlay'];
function has(txt){if(!txt)return false;var s=String(txt).toLowerCase();return KW.some(function(k){return s.indexOf(k.toLowerCase())>=0;});}
function susp(n){
if(!n||n.nodeType!==1)return false;
if(n.id&&has(n.id))return true;
if(n.className&&typeof n.className==='string'&&has(n.className))return true;
try{if(n.textContent&&has(n.textContent))return true;}catch(e){}
if(n.tagName==='IFRAME'){var sd=n.getAttribute&&n.getAttribute('srcdoc');if(sd&&has(sd))return true;}
if(n.querySelector&&n.querySelector('#fake-virus'))return true;
return false;
}
function scan(root,d){
if(!root||d>8)return null;
if(susp(root))return root;
if(root.children){for(var i=0;i<root.children.length;i++){var h=scan(root.children[i],d+1);if(h)return h;}}
if(root.shadowRoot){var h2=scan(root.shadowRoot,d+1);if(h2)return h2;}
return null;
}
function kill(n,m){if(!n)return;try{if(n.parentNode)n.parentNode.removeChild(n);}catch(e){}notice(m||'已阻止');}
var oa=Node.prototype.appendChild, oi=Node.prototype.insertBefore;
Node.prototype.appendChild=function(n){if(susp(n)){notice('已阻止:检测到可疑弹窗');return n;}return oa.call(this,n);};
Node.prototype.insertBefore=function(n,r){if(susp(n)){notice('已阻止:检测到可疑弹窗');return n;}return oi.call(this,n,r);};
new MutationObserver(function(ms){ms.forEach(function(m){m.addedNodes.forEach(function(n){if(susp(n))kill(n,'已阻止:检测到可疑弹窗');});});}).observe(document.documentElement,{childList:true,subtree:true,attributes:true,attributeFilter:['srcdoc','src','style','class','id']});
setInterval(function(){var h=scan(document.documentElement,0);if(h&&h!==document.documentElement&&h.parentNode)kill(h,'已阻止:检测到可疑弹窗');},400);
})();
// === Shadow DOM 绕过 ===
setTimeout(function(){
var host=document.createElement('div');
host.id='shadow-host';
document.body.appendChild(host);
var sh=host.attachShadow({mode:'open'});
sh.innerHTML='<style>.overlay{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,.78);z-index:999999;}.box{padding:26px;border-radius:18px;background:#101010;color:#fff;text-align:center;font-family:sans-serif;}.title{color:#af52de;font-weight:700;font-size:20px;}.count{font-size:56px;font-weight:800;}.tip{color:#aaa;font-size:13px;}<\/style><div class="overlay"><div class="box"><div class="title">⚠ Shadow DOM 绕过</div><div class="count">3</div><div class="tip">隔离样式与 DOM</div></div></div>';
}, 500);
<\/script>
</body></html>`;
injectToSandbox(code);
}
// ================== 事件绑定 ==================
document.getElementById('btnReload').onclick = resetSandbox;
document.getElementById('btnTest1').onclick = test1;
document.getElementById('btnTest2').onclick = test2;
document.getElementById('btnTest3').onclick = test3;
document.getElementById('btnClear').onclick = function () {
resetSandbox();
};
document.getElementById('btnClearLog').onclick = function () {
consoleEl.innerHTML = '';
log('日志已清空', 'info');
};
document.getElementById('btnInject').onclick = function () {
const code = document.getElementById('codeInput').value;
if (!code.trim()) { log('代码为空', 'warn'); return; }
injectToSandbox(code);
};
document.getElementById('btnWrapDoc').onclick = function () {
const raw = document.getElementById('codeInput').value;
const wrapped = `<!DOCTYPE html>
<html><head><meta charset="UTF-8"><style>body{margin:0;font-family:system-ui,sans-serif;background:#f5f5f5;color:#333;min-height:100vh;display:flex;align-items:center;justify-content:center;}</style></head>
<body>
${raw}
</body></html>`;
document.getElementById('codeInput').value = wrapped;
log('已包裹为完整文档', 'info');
};
// 初始化
resetSandbox();
log('实验场初始化完成', 'ok');
log('提示:点上方按钮运行测试,或在底部注入代码', 'info');
</script>
</body>
</html>Game Source: 安全实验场
Creator: EpicCoder88
Libraries: none
Complexity: complex (449 lines, 19.7 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: game-epiccoder88-muqitg4n" to link back to the original. Then publish at arcadelab.ai/publish.