文章目录
XSS 漏洞的发生和修复
XSS 攻击是页面被注入了恶意的代码
案例
公司需要一个搜索页面,根据 URL 参数决定关键词的内容。小明写的前端页面代码如下:
<inputtype="text"value="<%= getParameter("keyword")%>">
<button>搜索</button><div>
您搜索的关键词是:<%= getParameter("keyword") %>
</div>
如果这个url是:
http://xxx/search?keyword="><script>alert('XSS');</script>
,会导致页面弹出两次弹窗,因为当浏览器请求
http://xxx/search?keyword="><script>alert('XSS');</script>
时,服务端会解析出请求参数keyword,得到
"><script>alert('XSS');</script>
,拼接到HTML中返回给浏览器。形成了如下的 HTML:
<inputtype="text"value=""><script>alert('XSS');</script>">
<button>搜索</button><div>
您搜索的关键词是:"><script>alert('XSS');</script></div>
浏览器无法分辨出
<script>alert('XSS');</script>
是恶意代码,因而将其执行。这里不仅仅div的内容被注入了,而且input的value属性也被注入,alert会弹出两次。
解决方案:对特殊字符进行转义:
<inputtype="text"value="<%= escapeHTML(getParameter("keyword"))%>">
<button>搜索</button><div>
您搜索的关键词是:<%= escapeHTML(getParameter("keyword")) %>
</div>
上述url(
http://xxx/search?keyword="><script>alert('XSS');</script>
)展示的内容如下:
<inputtype="text"value=""><script>alert('XSS');</script>"><button>搜索</button><div>
您搜索的关键词是:"><script>alert('XSS');</script></div>
总结:
- 通常页面中包含的用户输入内容都在固定的容器或者属性内,以文本的形式展示。
- 攻击者利用这些页面的用户输入片段,拼接特殊格式的字符串,突破原有位置的限制,形成了代码片段。
- 攻击者通过在目标网站上注入脚本,使之在用户的浏览器上运行,从而引发潜在风险。
- 通过 HTML 转义,可以防止 XSS 攻击
注意特殊的 HTML 属性、JavaScript API
如果要根据URL参数决定跳转路径,前端代码:
<a href="<%= escapeHTML(getParameter("redirect_to")) %>">跳转...</a>
,假如URL 为
http://xxx/?redirect_to=javascript:alert('XSS')
,服务端响应就成了:
<a href="javascript:alert('XSS')">跳转...</a>
,虽然代码不会立即执行,但一旦用户点击a标签时,浏览器会就会弹出“XSS”。
解决方案:先把
getParameter("redirect_to")
的值转换成小写,再比对,下文省略了转换成小写的代码
// 禁止 URL 以 "javascript:" 开头
xss = getParameter("redirect_to").startsWith('javascript:');
if (!xss) {
<ahref="<%= escapeHTML(getParameter("redirect_to"))%>">
跳转...
</a>
} else {
<ahref="/404">
跳转...
</a>
}
如果链接是
http://xxx/?redirect_to=%20javascript:alert('XSS')
,
%20javascript:alert('XSS')
经过URL解析后变成
javascript:alert('XSS')
,这个字符串以空格开头。这样攻击者可以绕过后端的关键词规则,又成功的完成了注入。最终,小明选择了白名单的方法,彻底解决了这个漏洞:
// 根据项目情况进行过滤,禁止掉 "javascript:" 链接、非法 scheme 等
allowSchemes = ["http", "https"];
valid = isValid(getParameter("redirect_to"), allowSchemes);
if (valid) {
<ahref="<%= escapeHTML(getParameter("redirect_to"))%>">
跳转...
</a>
} else {
<ahref="/404">
跳转...
</a>
}
总结:
- 做了 HTML 转义,并不等于高枕无忧。
- 对于链接跳转,如
<a href="xxx"
或location.href="xxx"
,要检验其内容,禁止以javascript:
开头的链接,和其他非法的scheme。
根据上下文采用不同的转义规则
版权归原作者 CaraYQ 所有, 如有侵权,请联系我们删除。