XSS漏洞修复,洞修说白了就是洞修跟浏览器抢解释权。攻击者把恶意脚本塞进你的洞修页面,浏览器傻乎乎地当成正经代码执行了。洞修这事的洞修根源不在于攻击者多聪明,而在于开发者把不可信的洞修数据直接丢进了HTML上下文。
我见过最典型的洞修翻车现场——一个搜索框,用户输入什么,洞修页面就原样回显什么。洞修攻击者输入<img src=x onerror=alert(1)>,洞修好家伙,洞修弹窗了。洞修更狠的洞修会窃取cookie,把session偷走。洞修这种问题在2010年前后的洞修老系统里遍地都是,现在偶尔还能碰上。
修复XSS,第一原则是“输出编码”,不是“输入过滤”。很多人一上来就写正则,把<script>、onerror这些关键词全过滤掉。这思路从根上就偏了——黑名单永远有漏网之鱼,攻击者用<svg/onload=alert(1)>就能绕过大部分关键词过滤。而且过滤输入会误伤正常业务,用户名字里带个<符号怎么了?人家合法。
正确的做法是,数据在进入HTML、属性、JavaScript、CSS、URL等不同上下文时,用对应的编码函数处理。PHP的htmlspecialchars、Java的StringEscapeUtils.escapeHtml4、前端框架自带的模板转义,都是在输出端做文章。核心逻辑就一句:把用户数据当纯文本,不当代码。
但编码也不是万能药。有些场景你根本没法编码——比如富文本编辑器。用户要发带格式的帖子,图片、加粗、超链接都得支持。这时候编码会把所有标签都变成纯文本,功能就废了。这种场景得靠白名单过滤,用DOMPurify这类库,只允许安全标签和属性,其余全剥掉。注意,白名单要严格,style属性能省则省,CSS注入也能搞出数据窃取。
还有一个容易被忽视的角落——前端JavaScript里的DOM操作。你用innerHTML拼接字符串,就算后端输出做了编码,前端再拼一次又把编码后的实体还原成HTML了。等于后端辛苦做的防护,前端一棍子打回原形。正确姿势是使用textContent或者createElement + appendChild,让浏览器自己处理文本节点。
另外,CSP(内容安全策略)是个好东西。就算XSS真发生了,CSP能限制脚本只能从你指定的域名加载,内联脚本直接禁掉。这相当于最后一道防火墙,能拦住大部分利用方式。但CSP配置起来会踩坑,内联样式、eval()都会被拦,老代码可能直接跑不起来。
修复完别忘了验证。别光看弹窗没了就完事,得用攻击payload逐个测——<script>、<img onerror>、javascript:伪协议、<iframe srcdoc>……多试几种编码变体,比如<script>这种HTML实体编码。有时候开发者只过滤了尖括号,没过滤引号,结果属性值里的注入照样能成。
说个实在的经验:修XSS最怕的是“看起来修好了”。你给输出加了转义,但某个接口返回的数据经过三层流转,中途某层用JSON.parse把字符串还原成了HTML,转义就失效了。所以修完要追数据流,从源头到渲染,每一层都确认一遍。别嫌麻烦,XSS的坑基本都埋在这种间接路径上。
最后提醒一句:别依赖WAF(Web应用防火墙)。WAF能挡常规攻击,但绕过姿势太多,而且它只保护到你的服务器,挡不住前端自身逻辑漏洞。真正的修复永远在代码层,别把安全寄托在外部设备上。