完整阅读本文大约需要5分钟。
开启本文前,先提出两个我在面试时被问到的题:
XSS攻击是Cross-Site Scripting的缩写,直白来说,就是页面被注入了恶意的代码——用户输入的内容跳出文本的限制,成了可执行的代码。
根据入侵代码的来源,通常将XSS攻击分成三类:
特点:恶意代码已经落库,被拼接到HTML中返回。
除了论坛,这类攻击还常见于用户私信发送。
比如用户提交评论<script>alert('XSS');</script>
到网站的数据库中。
<div> 评论内容:<%= getContent("comment") %> </div>
被后端拼接后:
<div> 评论内容:<script>alert('XSS');</script> </div>
其他用户访问到这个页面,会跳出写着”XSS”的对话框
特点:恶意代码被拼接到URL上,被拼接到HTML中返回。
这类攻击需要用户主动点击受害网站的URL,攻击者会通过通过QQ群或者邮件等方式诱导点击。
比如一个恶意URL可以长这样:http://xxx/search?keyword="<script>alert('XSS');</script>
<div> 你好<%= getParameter("keyword") %> </div>
被后端拼接后:
<div> 你好<script>alert('XSS');</script> </div>
点击后,页面会跳出写着”XSS”的对话框。
特点:恶意代码被拼接到URL上,被前端JavaScript代码执行。
DOM型和反射型的区别在于,DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞。而其他两种 XSS 都属于服务端的安全漏洞。
上述三种XSS攻击的目的都一致:恶意代码在浏览器端运行后,窃取用户的本地存储数据:通过document.cookie
获取用户的身份凭证,然后通过网络请求将数据发送给恶意服务器。
接下来就可以进行下一步:冒充用户去对受害网站发起请求完成指定操作,比如转账给攻击者的账户。
XSS攻击的实现需要有两个必要条件:
先看第一点,是否可以避免攻击者输入恶意代码,先进行HTML转义呢?
如果我们在前端对输入的内容进行转义过滤,那么攻击者只要模拟发起请求,便绕了过前端,一样可以攻击成功。
如果落库时在后端进行转义过滤,我们会发现:
如果内容要提供给多端,只会在前端正常展示,在iOS/安卓上会变成乱码;
返回给前端的方式不一样,也不一定能正常展示,比如,正常的用户输入了 5 < 7
这个内容,在写入数据库前,被转义,变成了 5 < 7
;
5 < 7
。所以我们需要通过“防止浏览器执行恶意代码”来防范 XSS 攻击。
纯前端渲染是指,浏览器首先加载一个空白的HTML,然后执行该HTML引入的JS文件,JS通过AJAX获取业务数据,调用DOM API,更新到页面上。
因为是在前端,我们可以清楚地告诉浏览器:这是文本.innerText
而不是HTML.innerHTML
。这样浏览器就不会执行预期意外的代码。
纯前端渲染可以避免存储型和反射型的攻击,但没法避免DOM型,攻击者可以通过onload事件、href中嵌入javascript:...
进行攻击。
对于需要考虑SEO的SSR项目,不得不在服务端拼接HTML文件。那么必须使用HTML转义库,基本规则是将& < > " ' /
几个字符转义掉。
在前端渲染时,要谨慎使用.innerHTML
、.outerHTML
、document.write()
等直接插入HTML的API,其来源必须是可信的。
此外location
、onclick
、onerror
、onload
、onmouseover
、还有 <a>
标签的 href
都可以把字符串当作代码执行。
读完本文,回到开头两个问题,我们知道了:
如果这篇文章对你有帮助,给我点个赞呗~对我很重要