一个搜索框,站脚你输入什么它就回显什么。本漏看起来人畜无害,站脚直到某天有人在里面敲了这样一行字:<script>alert('xss')</script>。本漏页面弹出一个对话框,站脚你以为是本漏恶作剧,其实是站脚攻击者在你浏览器里跑通了第一条代码。这就是本漏XSS——跨站脚本漏洞,一个存在了二十多年,站脚却至今没被根治的本漏老问题。
它的站脚本质不复杂:服务器把用户输入的内容原封不动地当成HTML或JavaScript输出给了浏览器。你发一条评论,本漏里面藏着一段脚本,站脚其他用户点开这条评论,本漏脚本就在他们的站脚浏览器里执行了。攻击者不需要攻破你的服务器,他只需要让代码在你的浏览器里跑起来,就能偷走你的Cookie、冒充你发消息、读取你当前页面的敏感数据。最要命的是,这个过程对用户完全透明——页面看起来正常得很。
我见过最典型的案例是某电商平台的搜索框。攻击者构造了一个恶意链接,链接里的参数直接拼接到页面标题上,受害者点击后,脚本在页面加载时执行,直接调用了修改收货地址的接口。整个过程没碰服务器一下,但用户的账号已经被接管了。这种“存储型XSS”比反射型更危险,因为它不需要诱导用户点击特定链接,恶意代码就躺在数据库里,谁访问谁中招。
防御XSS的思路其实很直白:永远不要信任用户输入。但落实到代码里,总有人偷懒。要么是过滤不严,把<script>标签去掉了,却忘了<img onerror>这种不需要script标签就能执行JS的写法;要么是输出时没做转义,把用户输入的尖括号直接当成HTML解析了。更麻烦的是,现在前端框架多了,Vue、React默认会转义文本内容,但一旦开发者用了v-html或者dangerouslySetInnerHTML,等于亲手把防护栏拆了。
还有个容易被忽视的坑:XSS不只是浏览器端的事。现在很多网站有富文本编辑器,允许用户上传带格式的内容。你以为自己做了白名单过滤,只允许<b>、<i>这些安全标签,但攻击者能通过嵌套构造绕过——比如<svg><script>这种组合,或者利用CSS的expression属性在旧版IE上执行脚本。黑名单过滤永远有漏网之鱼,白名单才是正路,但即便如此,像<iframe>这种标签在某些场景下也必须禁用。
说实话,XSS漏洞之所以屡禁不止,很大程度是因为它不直接威胁服务器,很多开发者觉得“不就是弹个窗吗”。但真正的攻击场景里,没人会傻到弹窗给你看。他们会把窃取的Cookie静默地发到自己的服务器上,会伪造表单提交,会在你不知情的情况下操作你的账户。2018年英国航空公司的数据泄露事件,就是因为第三方脚本被注入,几十万用户的信用卡信息被截走——那也是XSS的变种。
最后说点实际的。如果你是普通用户,别随便点开可疑链接,浏览器插件能拦一部分,但别指望它万能。如果你是开发者,记住三条:输入校验永远做白名单,输出编码永远按上下文来(HTML属性里、JavaScript里、URL里,编码方式都不一样),Cookie设置HttpOnly属性。这三条做到,大概率能挡住九成以上的攻击。剩下的那一成,靠代码审计和渗透测试去补。XSS不会消失,但你可以让它变得很难被利用——这已经算是胜利了。