网络安全挑战里,XSS(跨站脚本攻击)是最经典的题型之一。找到注入点,弹出alert框,任务完成。听起来简单,但真正的难点往往藏在那些看似无害的细节里。

这次Intigriti的0526挑战搭建了一个社区动态网站:注册登录、用户留言板、个人资料编辑。表面上处处都是潜在的注入入口,但页脚的一行小字引起了注意——"SCA Shield v1.0"。是侧信道攻击防护?还是别的什么?

打开网易新闻 查看精彩图片

查看源码后发现,整个站点靠单一的app.js动态渲染,innerHTML被大量使用来插入内容。奇怪的是,DOMPurify这个知名的XSS过滤库只用来清理用户评论,用户名却直接原样塞进innerHTML:

打开网易新闻 查看精彩图片

nameDiv.innerHTML = t.user_name;

注入点找到了?把用户名改成典型XSS脚本提交,结果被SCA Shield拦下。这是服务端检测,不是前端过滤。错误信息很直白:引号、括号、点号、逗号、分号全部禁用。换成script标签试试?提示变成"恶意载荷特征 detected"。

但至少现在有了明确的黑名单。测试发现,style、svg这类标签并不在拦截范围内。想起之前读过的一种利用CSS动画触发的XSS技巧,决定试试keyframes方案。

第一轮payload长这样:

打开网易新闻 查看精彩图片

window被block,换成top——在普通页面里top就是页面本身。alert被block,用base64编码绕过,atob函数没被禁。引号也用标签模板字面量替代。成了。

但挑战还要求验证origin域名。需要进一步改造。注意到SCA Shield做的是精确字符串匹配,那用十六进制编码就能 masking 敏感词。\x61代替a,\x28代替(,\x29代替)。最终payload:

提交后Intigriti的回复出乎意料:这是非预期解。预期解法应该和app.js里的PixelAnalyticsConfig有关,官方提示也指向这个方向。虽然还没去研究那条路径,但这次"歪打正着"本身就说明了XSS过滤的复杂性——黑名单再长,也总有绕过的缝隙。