🎮ArcadeLab

安全实验场

by EpicCoder88
449 lines19.7 KB
▶ Play
<!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="&lt;script&gt;alert('hello')&lt;/script&gt;"></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 => ({
      '&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'
    }[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.