1162 字
6 分钟
26/2-XSS-Challenge
直接先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/