XSSTest

一个完全匿名、故意不设防的留言墙 · 想试什么就贴什么,看它到底能干什么

发一条 无需登录 · 不记 IP · 原样发布

内容不做任何过滤,最长 4000 字符。

内置示例 20 套 · 点一下自动填入上面的框

标注「详情页」的示例,发布后要点帖子上的「独立运行页」才会真正执行 <script> —— 列表页用 innerHTML 渲染,事件型 payload 立刻生效,但按 HTML 规范 script 标签不会执行。

帖子流

", d:"最经典的一句。列表页用 innerHTML 渲染时它不会执行,去「独立运行页」看它真的弹。"}, {n:"img onerror", w:"列表页", c:'', d:"src 故意写错,加载失败就触发 onerror。列表页直接生效。"}, {n:"svg onload", w:"列表页", c:'', d:"SVG 元素解析完成即触发 onload,不需要任何交互。"}, {n:"prompt / confirm", w:"详情页", c:"", d:"换成 prompt 或 confirm,还能收输入、拿确认结果。"} ]}, {cat:"02 / 事件属性(根本不用 script 标签)", items:[ {n:"details ontoggle", w:"列表页", c:'
点我展开内容
', d:"open 属性让它一渲染就 toggle,自动触发,无需点击。"}, {n:"autofocus + onfocus", w:"列表页", c:'', d:"autofocus 让输入框自动获得焦点,onfocus 立刻执行。"}, {n:"marquee onstart", w:"列表页", c:'这行字会跑', d:"老标签但事件照样触发,很多黑名单会漏掉它。"}, {n:"闭合标签改写结构", w:"列表页", c:'', d:"企图先闭合外层容器再塞自己的标签 —— 无过滤时页面结构真的会被改写。"} ]}, {cat:"03 / 编码与绕过", items:[ {n:"大小写混写", w:"列表页", c:"", d:"HTML 标签名与属性名不区分大小写,能绕开只匹配小写的黑名单。"}, {n:"HTML 实体编码", w:"列表页", c:'', d:"属性值里的字符实体会先被解码,再当作 JS 执行。"}, {n:"String.fromCharCode", w:"列表页", c:'', d:"把关键字拆成字符码,躲开字符串匹配。"}, {n:"javascript: 伪协议", w:"点击后", c:'点这个链接试试', d:"不在事件属性里,而在 href 里,点一下才触发。"} ]}, {cat:"04 / 恶作剧与页面特效", items:[ {n:"改掉页面标题", w:"详情页", c:"", d:"不动内容,只改标签页标题,最不吓人的一种。"}, {n:"整页倾斜", w:"详情页", c:"", d:"把整个页面拧一下,纯样式层面的恶作剧。"}, {n:"彩虹大字 + 跑马灯", w:"列表页", c:'

页面被接管了

', d:"标签和样式随便写,说明 HTML / CSS 完全没被过滤。"}, {n:"无限弹窗", w:"慎点 · 详情页", c:"", d:"会一直弹,想停只能关标签页。真·体会一下危害。"} ]}, {cat:"05 / 危害演示(都在本站内,不外传数据)", items:[ {n:"读 cookie", w:"详情页", c:"", d:"演示脚本能读同源 cookie。本站没有登录态所以是空的 —— 真实站点上这就是账号泄露。"}, {n:"改写整个页面", w:"详情页", c:'', d:"XSS 不只是弹窗,它能重画整个页面、放任何假内容。"}, {n:"劫持所有链接", w:"列表页", c:'', d:"把页面上所有链接指向别处,钓鱼常用手法。"}, {n:"强制跳转", w:"慎点 · 详情页", c:"", d:"直接把访问者送走,会离开本站。"} ]} ]; function renderSamples(){ var box = document.getElementById("samples"); SAMPLES.forEach(function(g){ var sec = document.createElement("div"); sec.className = "cat"; var h = document.createElement("h3"); h.textContent = g.cat; sec.appendChild(h); g.items.forEach(function(it){ var d = document.createElement("div"); d.className = "samp"; var n = document.createElement("div"); n.className = "n"; n.textContent = it.n; var tag = document.createElement("span"); tag.className = "tag" + (/慎点/.test(it.w) ? " hot" : ""); tag.textContent = it.w; n.appendChild(tag); var dd = document.createElement("div"); dd.className = "d"; dd.textContent = it.d; var code = document.createElement("code"); code.textContent = it.c; d.appendChild(n); d.appendChild(dd); d.appendChild(code); d.onclick = function(){ document.getElementById("text").value = it.c; document.getElementById("text").focus(); document.getElementById("hint").textContent = "已填入「" + it.n + "」,按发布即可。"; }; sec.appendChild(d); }); box.appendChild(sec); }); } function renderPosts(posts){ var list = document.getElementById("list"); list.innerHTML = ""; document.getElementById("count").textContent = posts.length ? "(" + posts.length + " 条)" : ""; if (!posts.length){ var e = document.createElement("p"); e.className = "hint"; e.textContent = "还没有人发帖。从左边挑一条示例点一下,再按发布。"; list.appendChild(e); return; } posts.forEach(function(p){ var card = document.createElement("article"); card.className = "post"; var meta = document.createElement("div"); meta.className = "meta"; var s = document.createElement("span"); s.textContent = "#" + p.id + " " + p.time; meta.appendChild(s); var a = document.createElement("a"); a.href = "/p/" + p.id; a.target = "_blank"; a.textContent = "独立运行页 ↗"; meta.appendChild(a); if (adminPass){ var del = document.createElement("button"); del.className = "ghost sm"; del.textContent = "删除"; del.onclick = function(){ doPost({act:"delete", pass:adminPass, id:p.id}); }; meta.appendChild(del); } var body = document.createElement("div"); body.className = "body"; body.innerHTML = p.content; // ← 故意:零过滤、零转义、零 sanitize card.appendChild(meta); card.appendChild(body); list.appendChild(card); }); } async function call(act, params, method){ var url = API + "?act=" + encodeURIComponent(act) + "&_=" + Date.now(); var opts = { method: method || "GET" }; if (opts.method === "POST"){ var fd = new URLSearchParams(); for (var k in (params || {})) fd.append(k, params[k]); opts.body = fd; opts.headers = {"Content-Type":"application/x-www-form-urlencoded"}; } else if (params){ for (var g in params) url += "&" + encodeURIComponent(g) + "=" + encodeURIComponent(params[g]); } var r = await fetch(url, opts); return r.json(); } async function load(){ var d = await call("list"); if (d.ok) renderPosts(d.posts); } async function doPost(params){ var d = await call(params.act, params, "POST"); if (!d.ok) alert(d.msg); document.getElementById("hint").textContent = d.ok ? "已处理。" : ("失败:" + d.msg); await load(); } document.getElementById("send").onclick = async function(){ var t = document.getElementById("text").value; if (!t.trim()){ alert("先写点什么,或从左边挑一条示例"); return; } var d = await call("add", {content:t}, "POST"); if (d.ok){ document.getElementById("text").value = ""; document.getElementById("hint").textContent = "发布成功。事件型 payload 已经在上面跑起来了;script 类请点「独立运行页」。"; await load(); } else { document.getElementById("hint").textContent = "失败:" + d.msg; alert(d.msg); } }; document.getElementById("adminToggle").onclick = function(){ var b = document.getElementById("adminBox"); b.style.display = b.style.display === "none" ? "inline" : "none"; }; document.getElementById("adminGo").onclick = function(){ adminPass = document.getElementById("adminPass").value; document.getElementById("adminHint").textContent = adminPass ? "已启用,每帖右侧出现删除按钮。" : "请输入口令。"; load(); }; document.getElementById("adminClear").onclick = async function(){ var p = document.getElementById("adminPass").value; if (!confirm("确定清空全部帖子?此操作不可恢复。")) return; await doPost({act:"clear", pass:p}); }; renderSamples(); load(); setInterval(load, 20000);