前端相关的网络安全问题有挺多的,这里主要介绍有3个:
跨站脚本(XSS)
Cross Site Scripting
,因其简写与CSS
(层叠样式表)冲突,所以改用XSS
。它主要是指攻击者可以在页面中插入恶意脚本代码,当用户访问这些页面时,浏览器会解析并执行这些恶意代码,从而达到窃取用户身份、钓鱼、传播恶意代码等行为。
它一般有3种类型:
反射型
反射型XSS也叫非持久型XSS,是指攻击者将恶意代码拼写在URL
中提交给服务器,服务器返回的内容,也带上这段XSS
代码,最后浏览器执行了这段恶意代码。存储型
破坏性较大,因为存储的恶意代码存储在数据库等地方,每次访问页面都会触发XSS
。
比如个性签名,攻击者在个性签名输入恶意代码并提交到服务器,如果这段代码没做任何处理直接存储到数据库,那么其它用户访问这个人主页时就会执行这段恶意代码。DOM型
在搜索关键字的URL
时,在search
后输入恶意脚本,然后url由前端解析回显时,那么攻击就变成了DOM
型了。
<script>
var search = location.search.replace('?search=', '')
document.write('你搜索了:' + decodeURI(search))
</script>
XSS防御手段
参数校验
对HTTP请求的URL参数和请求体payload的数据进行校验 ,在后端,需要判断数据是否是正常类型,对于不符合校验规则的数据及时抛出错误
字符转义
对一些特殊符号,比如<>&"'/
等,前端对其进行转义,后端保存转义后的内容。当前端要回显时,再把它们转义成原来的字符串显示。
对于用户输入的字符串内容,不要使用eval, new Function
等动态执行方法,也不要将这些字符串通过innerHTML、outerHTML、document.write()
方式写到HTML
中。
对于非客户端cookie
,比如保存用户凭证的session
,将其设置为http only
,避免前端访问cookie
跨站请求伪造(CSRF攻击)
CSRF是在受害者毫不知情的情况下,以受害者名义伪造请求发送给受攻击站点,从而在并未授权情况下执行在权限保护之下的操作。
和XSS相比,CSRF并不需要直接获取用户信息,只需要“借用”用户的登录信息相关操作即可,隐蔽性更强。
比如用户转账http://bank.com/widthdraw?amout=100&to=B
,攻击者往往通过广告、图片等方式诱使用户点击,从而使用用户的cookie信息向第三方发送恶意请求,比如下面这种嵌入的隐藏表单
<form action="http://bank.com/widthdraw" method="POST">
<input type="hidden" name="amout" value="10000">
<input type="hidden" name="to" value="hacker">
</form>
<script>document.forms[0].sumbit();</script>
CSRF防御
携带referer请求头
发送请求方,会在设置请求头处添加referer
防盗链字段,用于说明请求源,服务器判断referer
来拒绝不受信任的源发出的请求。
添加请求头token
攻击者大多使用cookie
来通过验证,所以可以通过添加请求头,比如token
,服务器通过token才响应正确的内容。
添加验证码
由于用户是在不知情情况下发送请求的,可以通过添加让用户二次确认的手段,比如验证码,来防御攻击。不过验证码会影响用户体验,所以不能频繁使用。
点击劫持(Click Jacking)
点击劫持主要是利用iframe
,把要攻击的页面嵌套到恶意网站,隐藏显示iframe,并覆盖在恶意网站上。当点击恶意网站时,就会触发嵌套页面的事件,这就是点击劫持。
比如,利用iframe
把页面A嵌入到其它页面B,通过设置样式,让页面A透明显示,将A中的按钮与B页面的按钮位置重叠,当点击B页面的按钮时,实际上就点击了我A页面的按钮,触发了A页面事件
<!-- (hack)B页面,劫持A页面 -->
<body>
<button onclick="console.log('点击B页面的按钮')">B页面按钮</button>
<!-- A页面被B页面点击劫持了 -->
<iframe src="http://other.com/8888/a.html" frameborder="0" style="position: absolute;top: 0;left: 0;opacity: 0;"></iframe>
</body>
<!-- A页面-->
<button onclick="alert('我是A页面被点击劫持的按钮')">A页面按钮</button>
当我把opacity: 0;
注释掉后,会发现A页面是完全覆盖在B页面的按钮上的
去掉注释,点击B页面按钮,实际点击到了A页面
这样,A页面内容就被恶意嵌套到别人网站上了,如果此按钮是发送请求之类的,那么A服务器就会一直收到请求
ok,知道了它怎么攻击,接下来看它的防御
点击劫持防御
因为它攻击的原理是利用了iframe
,所以服务器可以通过设置响应头X-Frame-Options
来告诉浏览器允许哪些域名引用当前页面。它可以设置这几个值:
- DENY:表示页面不允许在iframe中引用,即使是相同域名页面嵌套也不允许,比如github用了这个
- SAMEORIGIN:表示该页面可以在相同域名页面的iframe中引用,比如知乎响应头用了这个
- ALLOW-FROM [URL]:表示该页面指定来源的iframe中引用
ctx.set('X-FRAME-OPTIONS', 'DENY')
除了人工手段防御外,我们还可以使用漏洞扫描工具对网站进行测试,提前发现安全漏洞。