在DOM型跨站脚本(XSS)攻击中,有一类非常经典的漏洞触发场景:从前端JavaScript代码中获取浏览器的URL查询参数。攻击者可能通过精心构造的URL参数,利用这些参数处理逻辑中的缺陷,注入恶意脚本。
经典漏洞模式:获取URL参数
假设一个页面的URL是 http://example.com?name=John&age=30。
前端通常需要一个函数来获取特定参数的值,例如获取参数 name 的值 ‘John’。一种常见的实现如下:
var getUrlParameter = function getUrlParameter(sParam) {
var sPageURL = window.location.search.substring(1),
sURLVariables = sPageURL.split('&'),
sParameterName,
i;
for (i = 0; i < sURLVariables.length; i++) {
sParameterName = sURLVariables[i].split('=');
if (sParameterName[0] === sParam) {
return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]);
}
}
};
这段代码的逻辑清晰:
var sPageURL = window.location.search.substring(1):获取当前URL中 ? 之后的部分。
var sURLVariables = sPageURL.split('&'):将参数字符串按 & 分割成数组。
- 通过
for 循环遍历数组,将每个键值对按 = 分割。
- 如果找到目标参数名(
sParameterName[0] === sParam),则返回其值,并使用 decodeURIComponent 进行解码。
关键点:window.location.search 的取值
理解 window.location.search 的取值是分析此类漏洞的关键。我们以一个真实的微博搜索URL为例:
https://s.weibo.com/weibo?q=%23%E8%A1%80%E6%B0%A7%E4%BB%AA%E5%AF%B9%E5%86%9C%E6%9D%91%E6%84%8F%E5%91%B3%E7%9D%80%E4%BB%80%E4%B9%88%23&t=31&band_rank=2&Refer=top
其解码后等价于:
https://s.weibo.com/weibo?q=#血氧仪对农村意味着什么#&t=31&band_rank=2&Refer=top
对于这个URL:
window.location.search 获取的是 包含问号 的完整查询字符串:
?q=%23%E8%A1%80%E6%B0%A7%E4%BB%AA%E5%AF%B9%E5%86%9C%E6%9D%91%E6%84%8F%E5%91%B3%E7%9D%80%E4%BB%80%E4%B9%88%23&t=31&band_rank=2&Refer=top
window.location.search.substring(1) 获取的是 去掉问号 的查询字符串:
q=%23%E8%A1%80%E6%B0%A7%E4%BB%AA%E5%AF%B9%E5%86%9C%E6%9D%91%E6%84%8F%E5%91%B3%E7%9D%80%E4%BB%80%E4%B9%88%23&t=31&band_rank=2&Refer=top
其他常见的参数获取写法
除了上述循环分割的方法,还有另外两种在DOM操作中常见的URL参数获取方式。
第二种:使用正则表达式匹配
function getQueryParamByName(e) {
var t = window.location.href;
e = e.replace(/[\[\]]/g, "\\$&");
var a = new RegExp("[?&]" + e + "(=([^]*)|&|#|$)").exec(t);
return a ? a[2] ? decodeURIComponent(a[2].replace(/\+/g, " ")) : "" : null
}
这种写法直接对完整的URL(window.location.href)使用正则表达式进行匹配和提取,逻辑更为紧凑。
第三种:使用现代的 URLSearchParams API
new URLSearchParams(window.location.search).get('ParamName')
这是现代浏览器提供的标准API,使用起来非常简洁。例如,对于URL http://example.com?name=John&age=30,执行 new URLSearchParams(window.location.search).get('age') 将直接返回 “30”。
安全风险与审计要点
上述三种获取URL参数的写法本身并无问题,关键在于获取到参数值后如何处理。如果未经充分过滤或编码,就直接将其写入HTML、eval() 或作为脚本执行,就会产生DOM XSS漏洞。
因此,在进行代码审计或黑盒测试时,需要重点关注前端JavaScript代码中是否出现了 getUrlParameter、getQueryParamByName、URLSearchParams().get() 等敏感函数或API调用。追踪其返回值的数据流向,是发现潜在DOM XSS漏洞的关键切入点。
希望这篇关于DOM XSS经典模式的分析,能帮助你在安全研究和开发中更好地识别此类风险。更多Web安全与前端技术的深度讨论,欢迎访问云栈社区进行交流。