本文仅用于安全技术学习交流,所有目标信息已脱敏处理。
⚠️ 新手向文章,大佬勿喷,直接掠过即可。(新手,有错误欢迎指正)
信息收集
进入目标网站首页,页面风格明显偏老。查看源码发现使用了 jQuery(版本较旧),这类老站点往往对用户输入的过滤不够严格,存在 XSS 风险。
初步探测
在搜索框输入经典 payload:
<script>alert(1)</script>结果:直接被 WAF 拦截。
尝试 URL 编码绕过:
%3Cscript%3Ealert(1)%3C/script%3E结果:依然被拦截。
猜测 WAF 可能过滤了alert()函数,尝试替换:
<script>console.log(1)</script>结果:还是被拦截。
再次进行 URL 编码:
%3Cscript%3Econsole.log(1)%3C/script%3E结果:这次没有触发 WAF。
分析 WAF 规则
三次测试的对比:
Payload | 是否拦截 | 说明 |
| ✅ 拦截 | 包含 |
| ✅ 拦截 | 包含 |
| ❌ 未拦截 | URL 编码后绕过了 |
结论:WAF 的规则是匹配<script这个字符串模式,而非单纯的尖括号<>。
为什么编码后的 payload 没成功?
虽然绕过了 WAF,但控制台并没有输出1。
查看页面源码中输入的回显位置,发现:
HTML
<input type="text" value="console.log(1)</script>">WAF 的处理逻辑:直接删除了<script>字符串,剩余部分原样保留。
WAF 的规则是匹配并删除<script>字符串,而非拦截整个请求。编码后的 payload 绕过了字符串匹配,但解码后仍被过滤。
此时:
console.log(1)只是HTML 属性值中的普通文本</script>被 HTML 实体编码为</script>或浏览器当作纯文本- 没有任何代码执行的环境
核心问题:输入被当作 HTML 属性值处理,没有进入 JavaScript 执行上下文。
转换思路:跳出字符串执行
既然输入被包裹在双引号中,尝试闭合前面的字符串和语句,然后注入代码。
构造 payload:
";console.log(1);//分解执行逻辑:
部分 | 作用 |
| 闭合 |
| 结束变量赋值语句 |
| 注入的恶意代码 |
| 注释掉后面多余的 |
最终页面中的代码变为:
var keyword = "";console.log(1);//";验证
将 payload 进行 URL 编码:
%22%3Bconsole.log(1)%3B%2F%2F提交后观察浏览器控制台:
控制台成功回显,证明反射型 XSS 存在。
修复建议
- 输出编码:对用户输入进行 HTML 实体编码(
"→",<→<等) - 避免直接拼接:不要将用户输入直接拼接到
<script>标签内的字符串中 - 使用安全的 DOM 操作:避免使用
innerHTML、document.write()处理不可信数据 - 启用 CSP:配置 Content-Security-Policy 限制内联脚本执行
总结
阶段 | 关键动作 |
探测 | 经典 payload 测试 WAF 边界 |
分析 | 通过对比测试确定 WAF 规则是匹配 |
定位 | 查看源码确认输入回显位置( |
绕过 | 闭合字符串 + 语句注释,跳出上下文执行代码 |
验证 | 控制台回显确认漏洞存在 |
免责声明:本文所述技术仅用于合法授权的安全测试和学习研究,请勿用于非法用途。