XSS-квест

Правила

На каждом уровне — уязвимая «страница» и цель (например вызвать alert(1)). Введите payload в поле и нажмите «Выполнить». Превью покажет, как ввод подставится в разметку. Добейтесь срабатывания. Это головоломка на конструирование эксплойта, а не тест с одним ответом.

Данные не отправляются на сервер.

Выберите уровень и введите payload.

Превью:
Уровень 1 из 6. Счёт: 0.
', '', '', "''-alert(1)-''"] }, { desc: 'Вставка в атрибут: <input value="[ВВОД]">. Цель: выйти из атрибута и выполнить alert(1).', template: function(v) { return ''; }, allowed: ['">', '">', '" onfocus=alert(1) autofocus="', "'-alert(1)-'"] }, { desc: 'Вставка внутри тега: <div [ВВОД]>контент</div>. Цель: добавить обработчик и вызвать alert(1).', template: function(v) { return '
контент
'; }, allowed: ['onclick=alert(1)', 'onmouseover=alert(1)', 'onload=alert(1)'] }, { desc: 'Фильтр убирает <script>. Вставка: <div>[ВВОД]</div>. Цель: alert(1) без тега script.', template: function(v) { return '
' + v + '
'; }, allowed: ['', '', ''] }, { desc: 'Экранируются кавычки. Контекст: <a href="[ВВОД]">ссылка</a>. Цель: выполнить alert(1).', template: function(v) { var escaped = (v || '').replace(/"/g, '"'); return 'ссылка'; }, allowed: ['javascript:alert(1)', '#" onmouseover="alert(1)" x="'] }, { desc: 'Вставка в JS-строку: var x = \'[ВВОД]\';</script>. Цель: закрыть строку и выполнить alert(1).', template: function(v) { return "var x = '" + (v || '').replace(/'/g, "\\'") + "';"; }, allowed: ["'; alert(1); //", "\\'; alert(1); //"] } ]; var state = { level: 0, score: 0, completed: {} }; var payloadInput = document.getElementById('payload-input'); var previewInjected = document.getElementById('preview-injected'); var feedbackEl = document.getElementById('feedback'); var levelDesc = document.getElementById('level-desc'); var scoreEl = document.getElementById('game-score'); var btnRun = document.getElementById('btn-run'); var btnPrev = document.getElementById('btn-prev'); var btnNext = document.getElementById('btn-next'); function escapeHtml(s) { if (!s) return ''; var div = document.createElement('div'); div.textContent = s; return div.innerHTML; } function showLevel() { var lvl = LEVELS[state.level]; levelDesc.innerHTML = 'Уровень ' + (state.level + 1) + '. ' + lvl.desc; payloadInput.value = ''; previewInjected.textContent = '(пусто)'; feedbackEl.style.display = 'none'; if (window.gsap) gsap.fromTo(levelDesc, { opacity: 0, y: -6 }, { opacity: 1, y: 0, duration: 0.25 }); } function runPayload() { var payload = (payloadInput.value || '').trim(); var lvl = LEVELS[state.level]; var preview = lvl.template(payload); previewInjected.textContent = preview.substring(0, 200) + (preview.length > 200 ? '…' : ''); if (window.gsap) gsap.fromTo(previewInjected, { opacity: 0.5 }, { opacity: 1, duration: 0.2 }); var normalized = payload.replace(/\s+/g, ' ').toLowerCase(); var allowed = lvl.allowed || []; var found = allowed.some(function(a) { return normalized.indexOf(a.replace(/\s+/g, ' ').toLowerCase()) !== -1 || payload === a; }); feedbackEl.style.display = 'block'; if (found) { feedbackEl.className = 'feedback success'; feedbackEl.textContent = 'Успех! Payload сработал. Кратко: ' + (lvl.hint || 'вы вышли из контекста и выполнили скрипт.'); if (!state.completed[state.level]) { state.completed[state.level] = true; state.score += 50; } if (window.gsap) gsap.fromTo(feedbackEl, { scale: 0.98 }, { scale: 1, duration: 0.2 }); } else { feedbackEl.className = 'feedback hint'; feedbackEl.textContent = 'Пока не сработало. Посмотрите превью: как ввод подставился? Попробуйте закрыть тег или атрибут.'; } updateScore(); } function updateScore() { var done = Object.keys(state.completed).length; scoreEl.textContent = 'Уровень ' + (state.level + 1) + ' из ' + LEVELS.length + '. Счёт: ' + state.score + '. Пройдено: ' + done + '.'; } btnRun.addEventListener('click', runPayload); payloadInput.addEventListener('keydown', function(e) { if (e.key === 'Enter') { e.preventDefault(); runPayload(); } }); btnPrev.addEventListener('click', function() { state.level = Math.max(0, state.level - 1); showLevel(); updateScore(); }); btnNext.addEventListener('click', function() { state.level = Math.min(LEVELS.length - 1, state.level + 1); showLevel(); updateScore(); }); showLevel(); updateScore(); })();