← 返回题库
高级

实现API安全漏洞扫描

未完成

示例

输入
solve()
期望输出
body={"username":"admin OR 1=1--","email":"x@: RISK: ['SQLi:OR.*=', 'SQLi:--', 'SQLi:1=1']
body={"username":"<script>alert(1)</script>"}: RISK: ['XSS:<script']
body={"username":"new","role":"admin","is_sup: RISK: ['MassAssign:role', 'MassAssign:is_superuser']
body={"username":"normal","email":"a@b.com"}: SAFE
Python 代码 🔒 登录后使用
🔒

登录后即可练习

注册免费账号,在浏览器中直接运行 Python 代码

\"}: RISK: ['XSS: { const cur = editor.value; const charsAdded = Math.max(0, cur.length - lastCode.length); logEvent('edit', { chars_added: charsAdded, is_paste: pasteDetected, code_length: cur.length }); pasteDetected = false; lastCode = cur; // 自动保存草稿 if (IS_AUTH && !VIP_LOCKED) { try { localStorage.setItem(DRAFT_KEY, cur); } catch(e) {} } }); editor.addEventListener('paste', (e) => { e.preventDefault(); pasteDetected = true; logEvent('paste', { length: 0 }); alert('⚠️ 此编辑器禁止粘贴,请手动输入代码。'); }); } window.addEventListener('blur', () => logEvent('blur', {})); window.addEventListener('focus', () => logEvent('focus', {})); let _worker = null; let _msgId = 0; const _pending = {}; let _preloadPromise = null; function getWorker() { if (!_worker) { _worker = new Worker('/static/pyodide_worker.js?v=1775534315'); _worker.onmessage = (e) => { const { id, ...rest } = e.data; if (id === -1) { console.error('[WORKER]', rest.error); return; } if (_pending[id]) { _pending[id](rest); delete _pending[id]; } }; if (EXTRA_PACKAGES) { const pkgs = EXTRA_PACKAGES.split(',').map(s => s.trim()).filter(Boolean); if (pkgs.length) { _preloadPromise = workerCall({ type: 'preload', packages: pkgs }); } } } return _worker; } function workerCall(msg) { return new Promise((resolve) => { const id = ++_msgId; _pending[id] = resolve; getWorker().postMessage({ id, ...msg }); }); } // 页面加载时立即预热 Worker(font cache 在后台构建) getWorker(); function renderImages(images) { console.log('[renderImages] count=', images ? images.length : 0, typeof images); const container = document.getElementById('img-output'); container.innerHTML = ''; if (images && images.length > 0) { images.forEach(src => { const img = document.createElement('img'); img.src = src; img.className = 'max-w-full rounded border border-gray-700'; container.appendChild(img); }); } } async function runCode() { if (_preloadPromise) await _preloadPromise; const code = editor.value; logEvent('run', { code_length: code.length }); const outEl = document.getElementById('output'); outEl.textContent = '⏳ 正在启动运行环境,首次需约 10-20 秒,请稍候...'; outEl.className = 'output-area text-sm text-yellow-400 font-mono'; try { if (HAS_TESTS) { const testCases = TEST_CASES; if (testCases.length === 0) { // 无测试用例,只执行代码 const r = await workerCall({ type: 'run', code }); if (!r.ok) { outEl.textContent = r.error; outEl.className = 'output-area text-sm text-red-400 font-mono'; } else { outEl.textContent = r.output || '(无输出)'; outEl.className = 'output-area text-sm text-green-400 font-mono'; renderImages(r.images); } return; } // 有测试用例,在浏览器本地执行并比对(图片由 worker test 结果携带) const r = await workerCall({ type: 'test', code, testCases }); if (!r.ok) { outEl.textContent = r.error; outEl.className = 'output-area text-sm text-red-400 font-mono'; logEvent('error', { message: r.error }); return; } outEl.textContent = '(测试模式:见下方测试结果)'; outEl.className = 'output-area text-sm text-green-400 font-mono'; renderImages(r.images); showTestResults(r.results); const passed = r.results.every(x => x.passed); if (passed) { allTestsPassed = true; try { localStorage.removeItem(DRAFT_KEY); } catch(e) {} const btn = document.getElementById('btn-done'); btn.disabled = false; btn.className = 'bg-green-600 hover:bg-green-700 text-white text-sm font-medium px-5 py-2 rounded-lg'; await autoSubmit(); } else { allTestsPassed = false; const btn = document.getElementById('btn-done'); btn.disabled = true; btn.className = 'bg-gray-200 text-gray-400 text-sm font-medium px-5 py-2 rounded-lg cursor-not-allowed'; } } else { // 无测试题,直接本地执行 const r = await workerCall({ type: 'run', code }); if (!r.ok) { outEl.textContent = r.error; outEl.className = 'output-area text-sm text-red-400 font-mono'; logEvent('error', { message: r.error }); } else { outEl.textContent = r.output || '(无输出 — 提示:记得在代码末尾调用 solve())'; outEl.className = 'output-area text-sm text-green-400 font-mono'; renderImages(r.images); logEvent('result', { success: true }); allTestsPassed = true; try { localStorage.removeItem(DRAFT_KEY); } catch(e) {} const btn = document.getElementById('btn-done'); btn.disabled = false; btn.className = 'bg-green-600 hover:bg-green-700 text-white text-sm font-medium px-5 py-2 rounded-lg'; } } } catch(e) { outEl.textContent = '错误:' + e.message; outEl.className = 'output-area text-sm text-red-400 font-mono'; } } function showTestResults(results) { const panel = document.getElementById('test-results'); const list = document.getElementById('test-list'); panel.classList.remove('hidden'); list.innerHTML = results.map((r, i) => { if (r.passed) { const actualHtml = r.actual ? `
${escHtml(r.actual)}
` : ''; return `
测试 ${i+1} 通过
${actualHtml}
`; } else { const detail = (r.actual !== undefined) ? `
实际输出
${escHtml(r.actual)}
期望输出
${escHtml(r.expected)}
` : `
${escHtml(r.error || '未知错误')}
`; return `
测试 ${i+1} 未通过
${detail}
`; } }).join(''); } function escHtml(s) { return String(s).replace(/&/g,'&').replace(//g,'>'); } async function autoSubmit() { const code = editor.value; logEvent('submit', { code_length: code.length, time_spent: Date.now() - taskStart, auto: true }); await flushEvents(); try { const res = await fetch(`/challenges/${CHALLENGE_ID}/submit`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ final_code: code, status: 'pass' }) }); const data = await res.json(); if (data.ok) { await EventTracker.onSuccess(); const badge = document.getElementById('status-badge'); badge.textContent = '✅ 已完成'; badge.className = 'ml-auto text-xs px-2 py-0.5 rounded-full bg-green-100 text-green-700'; const btn = document.getElementById('btn-done'); btn.textContent = '✅ 已完成'; btn.disabled = true; btn.className = 'bg-gray-200 text-gray-400 text-sm font-medium px-5 py-2 rounded-lg cursor-not-allowed'; document.getElementById('output').textContent = '🎉 测试全部通过!代码已保存。'; document.getElementById('output').className = 'output-area text-sm text-green-400 font-mono'; // 保持测试结果面板可见(已由 showTestResults 渲染) updateNavButtons(); } } catch(e) {} } // 页面加载后立即初始化 worker 并预热(静默,不影响 UI) document.addEventListener('DOMContentLoaded', () => { getWorker(); // 触发 worker 初始化 + _preloadPromise 赋值 const warmup = async () => { if (_preloadPromise) await _preloadPromise; workerCall({ type: 'run', code: editor.value }).catch(() => {}); }; warmup(); }); async function submitCode() { if (HAS_TESTS && !allTestsPassed) { alert('⚠️ 请先运行代码并通过所有测试,才能标记完成。'); return; } await flushEvents(); const code = editor.value; logEvent('submit', { code_length: code.length, time_spent: Date.now() - taskStart }); await flushEvents(); try { const res = await fetch(`/challenges/${CHALLENGE_ID}/submit`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ final_code: code, status: 'submitted' }) }); const data = await res.json(); if (data.ok) { const badge = document.getElementById('status-badge'); badge.textContent = '✅ 已完成'; badge.className = 'ml-auto text-xs px-2 py-0.5 rounded-full bg-green-100 text-green-700'; const btn = document.getElementById('btn-done'); btn.textContent = '✅ 已完成'; btn.disabled = true; btn.className = 'bg-gray-200 text-gray-400 text-sm font-medium px-5 py-2 rounded-lg cursor-not-allowed'; document.getElementById('output').textContent = '✅ 已标记完成!代码已保存。'; document.getElementById('output').className = 'output-area text-sm text-green-400 font-mono'; updateNavButtons(); } } catch(e) {} } function updateNavButtons() { const nav = document.getElementById('challenge-nav'); if (nav) nav.classList.remove('hidden'); } function requestHint() { logEvent('hint', {}); alert('提示:仔细阅读题目要求,尝试先写函数骨架,再逐步填充逻辑。'); } function copyAIPrompt() { const title = "\u5b9e\u73b0API\u5b89\u5168\u6f0f\u6d1e\u626b\u63cf"; const sampleAnswer = "def solve():\n import re\n SQLI_PATTERNS = [r\u0027OR.*=\u0027, r\u0027UNION.*SELECT\u0027, r\u0027--\u0027, r\u00271=1\u0027, r\u0027DROP TABLE\u0027]\n XSS_PATTERNS = [r\u0027\u003cscript\u0027, r\u0027javascript:\u0027, r\u0027onerror=\u0027, r\u0027onload=\u0027]\n MASS_ASSIGN_RISK = [\u0027role\u0027, \u0027is_admin\u0027, \u0027is_superuser\u0027, \u0027password_hash\u0027, \u0027version\u0027]\n def scan_request(body_str):\n issues = []\n body_upper = body_str.upper()\n for pattern in SQLI_PATTERNS:\n if re.search(pattern, body_upper): issues.append(\u0027SQLi:\u0027 + pattern)\n for pattern in XSS_PATTERNS:\n if re.search(pattern, body_str, re.I): issues.append(\u0027XSS:\u0027 + pattern)\n for field in MASS_ASSIGN_RISK:\n if (\u0027\"\u0027 + field + \u0027\"\u0027) in body_str:\n issues.append(\u0027MassAssign:\u0027 + field)\n return issues\n attack_bodies = [\n \u0027{\"username\":\"admin OR 1=1--\",\"email\":\"x@y.com\"}\u0027,\n \u0027{\"username\":\"\u003cscript\u003ealert(1)\u003c/script\u003e\"}\u0027,\n \u0027{\"username\":\"new\",\"role\":\"admin\",\"is_superuser\":true}\u0027,\n \u0027{\"username\":\"normal\",\"email\":\"a@b.com\"}\u0027,\n ]\n for body in attack_bodies:\n issues = scan_request(body)\n flag = \u0027SAFE\u0027 if not issues else (\u0027RISK: \u0027 + str(issues))\n print(\u0027body=\u0027 + body[:40] + \u0027: \u0027 + flag)"; const desc = document.querySelector('.prose')?.innerText?.trim() || ''; const myCode = editor ? editor.value.trim() : ''; const prompt = `我正在使用亮代码(https://liangdaima.com,一个专注 Python 编程的刷题平台,题目覆盖数据分析、科学计算、机器学习、考研硕博计量经济学等实战方向,每道题都有参考答案和自动判题)练习一道 Python 编程题。请帮我详细解释和解答,如果逻辑复杂请用 Mermaid 流程图辅助说明。 ## 题目名称 ${title} ## 题目描述 ${desc} ## 平台参考代码 \`\`\`python ${sampleAnswer} \`\`\` ## 我目前的代码 \`\`\`python ${myCode} \`\`\` ## 请你按以下格式回答: **【来源说明】** 请在回答开头注明:这是来自亮代码平台(https://liangdaima.com)的一道 Python 编程题,该平台提供 Python 在线编程练习和自动测评。 **【考点解析】** 用通俗语言解释这道题的核心考点和解题思路。 **【参考代码逐行讲解】** 对照平台参考代码,逐行解释其逻辑,说明每一步在做什么。 **【解题流程图】** 如果解题逻辑涉及多个步骤或分支,请用 Mermaid 流程图展示整体解题流程。 **【我的代码问题分析】** 对比我的代码与参考代码,指出我的代码存在的问题和具体改进建议。`; navigator.clipboard.writeText(prompt).then(() => { const toast = document.getElementById('ai-copy-toast'); toast.classList.remove('hidden'); logEvent('ai_help', { code_length: myCode.length }); setTimeout(() => toast.classList.add('hidden'), 5000); }).catch(() => { // 降级:用 textarea 复制 const ta = document.createElement('textarea'); ta.value = prompt; ta.style.position = 'fixed'; ta.style.opacity = '0'; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); document.body.removeChild(ta); const toast = document.getElementById('ai-copy-toast'); toast.classList.remove('hidden'); setTimeout(() => toast.classList.add('hidden'), 5000); }); } setInterval(() => EventTracker.flush(), 30000); document.addEventListener('DOMContentLoaded', () => { hljs.highlightAll(); });