前端是直面用户的窗口,其安全性却是最容易被忽略的一环。本文将介绍:
一、什么是XSS攻击
1.1 定义
1.2 XSS攻击的危害
二、 XSS攻击类型
2.1 反射型攻击
2.2 存储型攻击
2.3 DOM型攻击
2.4 三种攻击类型的区别
三、 如何防范XSS攻击
3.1 设置Cookie HttpOnly 为 true
3.2 纯前端渲染
3.3 使用合适的转义库
3.4 预防DOM型XSS攻击
四、 线上XSS检测
4.1 特殊恶意字符串
4.2 扫描工具
五、总结
XSS攻击的本质是,在url参数中加入恶意的javascript代码,通过浏览器解析和运行恶意代码,达到恶意攻击用户的目的。
官方解释:
XSS是跨站脚本攻击(Cross Site Scripting),为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而恶意攻击用户的目的。
攻击者可获取用户的敏感信息如 Cookie、SessionID 等,进而危害数据安全。或是通过前端请求操作数据库,获取数据库内容或修改数据库内容。
XSS攻击分为反射型攻击和存储型攻击。
反射型攻击也叫非持久型XSS攻击,即在请求时将恶意代码插入URL中,作为参数提交到服务器。服务器解析数据并将响应数据返回到浏览器中,最终由浏览器执行。
2.1.1 攻击步骤
2.1.2 例子
如:
http://localhost:8080/helloController/search?name=
http://localhost:8080/helloController/search?name=
http://localhost:8080/helloController/search?name=点我
存储型攻击也叫持久型攻击,即一次攻击成功后,下一次请求时就不用再带上恶意XSS代码了。第一次注入的XSS代码会被服务器存储(缓存或数据库),且在下一次被前端从服务器获取,返回到浏览器时被浏览器执行。常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。
2.2.1 攻击步骤
存储型 XSS 的攻击步骤:
2.2.2 恶意盗取用户信息
常见在留言板,IM聊天软件中出现。如某web聊天软件中,小王给小明发了一条XSS攻击消息
当小明接收到这条消息时,就会出现一个内容为 “你被XSS攻击啦” 的弹窗。若这条消息没有被删掉,则小明每次打开这个消息的窗口,弹窗都会弹出来,因为这段XSS恶意代码已经被执行了。
他可以被包装得更具有隐蔽性
hello,你好
这种攻击常用于窃取用户信息,如cookie,token,账号密码等
2.2.3 插入图片
依旧是留言板,当留言板浏览器执行到这段代码时,会出现一张图片,点击图片,则会被重定向到另一个网站
< img onclick="window.location.href='http://www.baidu.com'" width='300' src='img/webwxgetmsgimg.jpg'/>
2.2.4 流量劫持、恶意跳转
当用户打开网址时,会被恶意重定向到指定的网址
2.3.1 攻击步骤
攻击类型 | 恶意代码存储位置 | 插入点 | 解决端 |
反射型XSS | URL | HTML | 服务端 |
存储型XSS | 后端数据库或缓存中 | HTML | 服务端 |
DOM型XSS | 后端数据库/前端存储/URL | 前端JAVASCRIPT | 前端 |
服务端可以通过设置 HttpOnly 来防止XSS代码获取到用户的cookie。
@RequestMapping("/login")
@ResponseBody
public void login(HttpServletRequest request, HttpServletResponse response) throws IOException {
......
Cookie cookie = new Cookie("access_token", UUID.randomUUID().toString());
cookie.setHttpOnly(true); // 此处设置HttpOnly为true
cookie.setPath("/");
cookie.setDomain("localhost");
response.addCookie(cookie);
response.sendRedirect("http://localhost:8088/index.html");
}
纯前端渲染即避免在前端代码中出现html拼接的情况。一个合理干净的前端代码应该是:
在很多内部、管理系统中,采用纯前端渲染是非常合适的,但纯前端渲染,会带来以下问题:
onload
事件和 href
中的 javascript:xxx
等
3.3.1 前端转义函数
/**
* @function escapeHTML 转义html脚本 < > & " '
* @param a -
* 字符串
*/
escapeHTML: function(a){
a = "" + a;
return a.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'");;
},
/**
* @function unescapeHTML 还原html脚本 < > & " '
* @param a -
* 字符串
*/
unescapeHTML: function(a){
a = "" + a;
return a.replace(//g, ">").replace(/&/g, "&").replace(/"/g, '"').replace(/'/g, "'");
},
3.3.2 后端转义库
Java 工程里,常用的转义库为 org.owasp.encode
DOM型XSS攻击,实际是前端JavaScript将不可信的数据当作代码执行力。
应尽量使用 .textContent
、.setAttribute()
代替.innerHTML
、.outerHTML
、document.write()
,若必须使用时要特别小心,不要把不可信的数据作为 HTML 插到页面上
如果用 Vue/React 技术栈,并且不使用 v-html
/dangerouslySetInnerHTML
功能,就在前端 render 阶段避免 innerHTML
、outerHTML
的 XSS 隐患。
DOM 中的内联事件监听器,如 location
、onclick
、onerror
、onload
、onmouseover
等, 标签的
href
属性,JavaScript 的 eval()
、setTimeout()
、setInterval()
等,都能把字符串作为代码运行。如果不可信的数据拼接到字符串中传递给这些 API,很容易产生安全隐患,请务必避免。
将这段字符串输入到输入框中提交这个字符串,或者把它拼接到 URL 参数上,就可以进行检测了
http://xxx/search?keyword=jaVasCript%3A%2F*-%2F*%60%2F*%60%2F*%27%2F*%22%2F**%2F(%2F*%20*%2FoNcliCk%3Dalert()%20)%2F%2F%250D%250A%250d%250a%2F%2F%3C%2FstYle%2F%3C%2FtitLe%2F%3C%2FteXtarEa%2F%3C%2FscRipt%2F--!%3E%3CsVg%2F%3CsVg%2FoNloAd%3Dalert()%2F%2F%3E%3E
除了手动检测之外,还可以使用自动扫描工具寻找 XSS 漏洞,例如 Arachni、Mozilla HTTP Observatory、w3af 等
充分遵循以下原则,能够降低XSS攻击得手的概率
<%= data %>
而不是 <%- data %>
;{{! data }
而不是 {{= data }
;freemarker.core.OutputFormat
。onLoad="onload('{{data}}')"
、onClick="go('{{action}}')"
这种拼接内联事件的写法。在 JavaScript 中通过 .addEventlistener()
事件绑定会更安全。createElement
、setAttribute
之类的方法实现。或者采用比较成熟的渲染框架,如 Vue/React 等。
参考网站:
感觉大佬的无私分享
Java防止XSS攻击获取Cookie: https://www.cnblogs.com/mao2080/p/9520185.html
网络攻击-XSS攻击详解:https://www.cnblogs.com/mao2080/p/9460397.html
美团前端安全系列(一):https://www.cnblogs.com/meituantech/p/9718677.html