前端安全:CSRFXSS该怎么防御?
Posted 椰卤工程师
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端安全:CSRFXSS该怎么防御?相关的知识,希望对你有一定的参考价值。
近几年随着业务的不断发展,前端随之面临很多安全挑战。我们在日常开发中也需要不断预防和修复安全漏洞。接下来,梳理一些场景的前端安全问题和对应的解决方案。
XSS攻击介绍
XSS是后端的责任,后端应该在用户提交数据的接口对隐私敏感的数据进行转义。
NO,这种说法不对
所有插到页面的数据,都要进行过滤转移,当没有敏感字符的时候,就可以直接插到页面上显示了。
NO,丝毫没有什么作用
XSS攻击是页面被注入了恶意的代码,利用恶意脚本,攻击者可以获取用户的Cookie、SessionID等敏感信息。
XSS注入的方法:
- 在html中内嵌的文本中,恶意内容通过script标签注入
- 在内联的JS中,拼接的数据突破了原本的限制
- 在标签属性中,恶意内容包含引导,从而突破属性值的限制
- 在标签href、src等属性中,包含
javascript:
可执行代码 - 在onload、onerror、onclick事件中,注入不受控制的代码
- 在style属性中,类似
background- image: url("javascript:..")
代码
如果开发者没有将用户输入的文本进行合适的过滤,直接插入到HTML中,很容易造成注入漏洞。
XSS攻击的分类
存储型XSS
其攻击步骤如下:
- 攻击者将恶意代码提交到目标网站的数据库
- 用户打开目标网站,服务端将恶意代码取出,拼在HTML中返回给浏览器
- 用户浏览器解析执行,混在HTML中的恶意代码也被执行
- 恶意代码窃取用户数据,冒充用户,执行攻击者制定的操作
常见场景:论坛发帖、商品评论、私信
反射型XSS
其攻击步骤如下:
- 攻击者构造特殊URL,其中包含恶意代码
- 用户点击打开该URL,服务端将恶意代码从URL中取出,拼接在HTML中返回给浏览器
- 浏览器解析执行,混在HTML中的恶意代码也被执行
- 恶意代码窃取用户数据,冒充用户,执行攻击者制定的操作
看到这里,我们发现反射型XSS和存储型XSS的区别在于恶意代码的存储位置不同:
- 反射性XSS:恶意代码存URL上
- 存储型XSS:恶意代码存数据库里
所以反射性XSS攻击通常借助URL传递参数,如网站搜索、跳转等。
DOM型XSS
其攻击步骤如下:
- 攻击者构造特殊URL,其中包含恶意代码
- 用户点击打开带有恶意代码的URL
- 用户浏览器解析执行,前端JS取出URL中恶意代码并执行
- 恶意代码窃取用户数据,冒充用户,执行攻击者制定的操作
DOM型XSS和前两种的区别在于:取出和执行恶意代码都在浏览器端执行,属于JS自身的安全漏洞,而存储型XSS、反射型XSS都属于服务端的安全漏洞。
XSS攻击的防御
通过前面的介绍可以发现,XSS攻击两大因素:
- 攻击者提交恶意代码
- 浏览器执行了恶意代码
所以,我们可以在这两个方面进行防御。
我们要考虑是否能够在用户输入的过程中,过滤到恶意代码,然后提交到后端。
这条路是不可行的,一旦攻击者绕过前端过滤,就可以直接构造请求来提交恶意代码了。
如果我们将过滤的时机转移到:在后端写入数据库前,后端进行过过滤,只存储安全的内容,并返回给前端,这样能成功防御XSS吗?
在实际的开发中,我们并不确定内容要输出到哪里,用户输入的内容可能同时提供给前端和客户端,而一旦经过escapeHtml()
,客户端显示的内容就会变成乱码。
所以,这样的方式会引入很大的不确定性和乱码问题,我们通常不这么做。
预防存储型和反射型XSS攻击
这两种攻击都发现在服务端取出恶意代码并拼接在HTML中,最终被浏览器执行,常见的预防方式:
- 改成纯前端渲染,把代码和数据分离开
- 对HTML做转义(采用适合的转义库)
预防DOM型XSS攻击
实际上是网站JS代码本身不够严谨,把不可信数据当作可执行代码。
所以我们在使用.innerHTML
、outerHTML
时要特别注意,不要把不可信数据作为HTML插入页面。
在vue和react中,也不建议使用v-html
和dangerouslySetInnerHTML
检测XSS方法
- 使用CSS攻击字符串手动检测XSS漏洞
- 使用扫描工具检测(ecsypno)
在github小有个工具库:点击直达
我们将它copy 并拼接在URL参数上,就可以检测了:
jaVasCript:/*-/*`/*\\`/*'/*"/**/(/* */oNcliCk=alert() )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\\x3csVg/<sVg/oNloAd=alert()//>\\x3e
虽然很难通过技术手段完全避免 XSS,但我们可以总结以下原则减少漏洞的产生:
- 利用模板引擎
- 避免内联事件
- 避免拼接 HTML
- 增加攻击难度,降低攻击后果
- 主动检测和发现
CSRF攻击介绍
CSRF利用受害者的注册凭证,绕过后台验证,冒充用户执行某些操作。
典型的流程:
- 受害者登录a.com,并保留了登录cookie
- 攻击者诱导用户访问b.com
- b.com向a.com发送请求
- a.com收到请求后,校验通过,误以为是受害者自己发送的请求
- a.con以受害者名义执行某些操作
- 攻击完成,受害者浑然不知
常见的CSRF攻击类型
GET
<img src="http://bank.example/withdraw?amount=10000&for=hacker" >
在受害者访问含有这个img的页面后,浏览器会自动向http://bank.example/withdraw?account=xiaoming&amount=10000&for=hacker
发出一次HTTP请求。bank.example就会收到包含受害者登录信息的一次跨域请求。
POST
通常CSRF利用一个自动提交的表单,相当于模拟用户完成一次POST操作。
CSRF的特点
- 攻击一般发起在第三方网站,被攻击的网站无法防止攻击
- 利用受害者的登录凭证,冒充受害者,而不是直接窃取数据
- 整个过程不能获取到受害者的登录凭证,仅仅是冒用
- 通常的方式:图片URL、超链接、CORS、From表单提交
CSRF通常是跨域的,所以我们可以专门制定防御策略,比如:
- 组织不明外域的访问:同源检测、Samesite Cookie
- 提交时加上本域才有的信息:CSRF Token、双重Cookie验证
同源检测
在HTTP中每个异步请求都会携带两个Header:Origin Header、Referer Header
服务器可以通过解析这两个Header中的域名,确定请求的来源域
CSRF Token
- 将CSRF Token输出到页面
- 页面提交的请求中携带这个Token
- 服务器验证Tojen是否正确
⚠️注意:Token随机生成,不会被攻击者才到
Samesite Cookie
为Set-Cookie
响应头新增Samesite属性,它用来标明这个 Cookie是个“同站 Cookie”,同站Cookie只能作为第一方Cookie,不能作为第三方Cookie,Samesite 有两个属性值,分别是 Strict 和 Lax:
- Strict:严格模式,任何情况下都不能作为第三方Cookie
- Lax:宽松模式,Cookie可作为第三方Cookie
双重Cookie验证
比CSRF Token繁琐一些,而且不能在通用的拦截上统一处理所有的接口:
- 在用户访问网站时,向请求的域名注入一个cookie,内容为随机字符串
- 前端向后端发起请求时,取出cookie,并添加在URL参数中
- 后端接口验证cookie字段与URL参数中字段是否一致
它的好处在于无需使用Session,适用面广。且Token存在客户端,也不会给服务器造成压力。但这样Cookie中增加了额外的字段。如果有其他漏洞(如XSS),攻击者可以注入cookie,防御就会失效。
为了更好的防御CSRF,最佳实践就是结合上述的防御措施的优缺点来综合考虑。
浅谈Web前端安全策略xss和csrf,及又该如何预防?
Web前端安全策略xss和csrf的攻击和防御
随着前端技术的不断革新,前端早已不再是简简单单的做页面了。现在的前端网站上会涉及到大量用户的数据和隐私,那这些用户数据安全吗?答案并不是肯定的。因此,这个时候前端安全就显得尤为重要。如果网站没有做安全策略,那么就会很容易被攻击者通过某些不为人知的操作,获取到用户的隐私信息。
在下面的这篇文章中,将讲解前端安全策略 xss
和 csrf
!一起来一探究竟吧~
一、XSS跨站请求攻击
1、什么是XSS
跨站脚本攻击,缩写为XSS(Cross Site Scripting),是利用网页的漏洞,通过某种方式给网页注入恶意代码,使用户加载网页时执行注入的恶意代码。
2、场景模拟
假设有一个博客网站,这个博客网站的安全做的很差。那么我现在准备在这个网站上发布一篇博客,在发布的这篇博客中,我嵌入了一段
写完之后呢,我成功把这篇博客发送出去了。现在,只要有人在这个网站查看我这篇博客文章,那么我就能轻松地收割访问者的 cookie
,这就是一个简单的 xss
攻击流程。
了解完 xss
的定义之后,我们再来了解 xss
的攻击类型。
3、XSS的攻击类型
XSS一共分为三种:
- 非持久型跨站(也叫反射型)
- 持久型跨站(也叫存储型)
- DOM跨站
(1)非持久型跨站(反射型)
①攻击步骤
- 攻击者构造出特殊的
URL
,其中包含恶意代码。 - 用户打开带有恶意代码的
URL
时,网站服务端将恶意代码从URL
中取出,拼接在HTML
中返回给浏览器。 - 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
- 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
②攻击场景
反射型 XSS
(也被称为非持久性 XSS
)漏洞常见于通过 URL
传递参数的功能,如网站搜索、跳转等。
③攻击方式
由于需要用户主动打开恶意的 URL
才能生效,攻击者往往会结合多种手段诱导用户点击。
POST
的内容也可以触发反射型 XSS
,只不过其触发条件比较苛刻(需要构造表单提交页面,并引导用户点击),所以非常少见。
(2)持久型跨站(存储型)
①攻击步骤
- 攻击者将恶意代码提交到目标网站的数据库中。
- 用户打开目标网站时,网站服务端将恶意代码从数据库取出,拼接在
HTML
中返回给浏览器。 - 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
- 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
②攻击场景
存储型 XSS
攻击 (也被称为持久型 XSS
)常见于带有用户保存数据功能的网站,如论坛发帖、商品评论、用户私信等。
③危害
它是最危险的一种跨站脚本,相比反射型 XSS
和 DOM
型 XSS
具有更高的隐蔽性,危害更大,因为它不需要用户手动触发。
任何允许用户存储数据的 web
程序都可能存在存储型 XSS
漏洞,当攻击者提交一段 XSS
代码后,被服务器端接收并存储,当所有浏览者访问某个页面时都会被 XSS
。
(3)DOM跨站
①攻击步骤
- 攻击者构造出特殊的
URL
,其中包含恶意代码。 - 用户打开带有恶意代码的
URL
。 - 用户浏览器接收到响应后解析执行,前端
JavaScript
取出URL
中的恶意代码并执行。 - 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
②危害
DOM通常表示 html
、xhtml
和xml
中的对象,使用 DOM
可以允许程序和脚本动态的访问和更新文档的内容、结构和样式。它不需要服务器解析响应的直接参与,触发 XSS
依靠的是浏览器端的DOM解析 。
对以上三种xss的攻击类型进行一个小结:
反射型跟存储型的区别是:
存储型 XSS 的恶意代码存在数据库里,反射型 XSS 的恶意代码存在 URL 里。
DOM 型跟前两种区别是:
DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞。
三者的对比:
类型 存储区 插入点 反射型 XSS URL HTML 存储型 XSS 后端数据库 HTML DOM 型 XSS 后端数据库/前端存储/URL 前端 JavaScript
4、如何防御XSS
只要有输入数据的地方,就可能存在 XSS
危险。
(1)设置HttpOnly
在 cookie
中设置 HttpOnly
属性后, js
脚本将无法读取到 cookie
信息。
(2)转义字符串
XSS
攻击大多都是由数据的输入和输出作为攻击点进行攻击,所以针对这几个攻击点,对数据进行过滤。
其中,数据包括前端数据的输入和输出、后端数据的输入和输出。
那么,数据过滤是什么?又如何对数据进行过滤呢?
数据过滤是对输入格式的检查,例如:邮箱,电话号码,用户名,密码……等,按照规定的格式输入。它不仅仅是前端负责,后端也要做相同的过滤检查。如果没有做数据过滤,攻击者完全可以绕过正常的输入流程,直接利用相关接口向服务器发送设置。
因此,可以通过封装过滤函数对数据进行过滤,目的是将几个攻击者常用的输入内容都进行转移,这样就避免了浏览器解析成了脚本代码。
function escape(str) {
str = str.replace(/&/g, '&');
str = str.replace(/</g, '<');
str = str.replace(/>/g, '>');
str = str.replace(/"/g, '&quto;');
str = str.replace(/'/g, ''');
str = str.replace(/`/g, '`');
str = str.replace(/\\//g, '/');
return str;
}
(3)白名单
对于显示富文本来说,不能通过上面的办法来转义所有字符,因为这样会把需要的格式也过滤掉。这种情况通常采用白名单过滤的办法,当然也可以通过黑名单过滤,但是考虑到需要过滤的标签和标签属性实在太多,更加推荐使用白名单的方式。
二、XSRF跨站请求伪造
1、什么是csrf
跨站请求伪造(Cross-site request forgery),也被称为 one-click attack
或者 session riding,通常缩写为 CSRF
或者 XSRF
,是一种挟制用户在当前已登录的 Web
应用程序上执行**非本意的操作**的攻击方法。
如:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。
2、场景模拟
(1)场景一
假设你正在购物,看重了某个商品,商品 id
是 100
。同时这个商品的付费接口时 xxx.com/pay?id=100
,但是没有任何验证。这个时候我是攻击者,我看中了一个商品,id
是 200
。那么,我如何让你来为我付款?
这个时候我像你发送了一封邮件,邮件标题很是吸引人。但邮件正文隐藏着 <img src = "xxx.com/pay?id=200">
。你一查看邮件,一点击,就帮我购买了 id
是 200
的商品。
(2)场景二
要完成一次 CSRF
攻击,受害者必须依次完成两个步骤:
- 登录受信任网站
A
,并在本地生成Cookie
。 - 在不登出
A
的情况下,访问危险网站B
。
看到这里,你也许会说:“如果我不满足以上两个条件中的一个,我就不会受到CSRF的攻击”。是的,确实如此,但是呢,你可能没办法保证以下情况不会发生哦!比如:
- 你不能保证你登录了一个网站后,不再打开一个
tab
页面并访问另外的网站。 - 你不能保证你关闭浏览器了后,你本地的
Cookie
会立刻过期,你上次的会话已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登录/结束会话了…)
上述中所说的网站,可能是一个存在其他漏洞,但又很受信任的且经常被人访问的网站。
3、CSRF的特点
- 攻击一般发起在第三方网站,而不是被攻击的网站。被攻击的网站无法防止攻击发生。
- 攻击利用受害者在被攻击网站的登录凭证,冒充受害者提交操作,而不是直接窃取数据。
- 整个过程攻击者并不能获取到受害者的登录凭证,仅仅是“冒用”。
4、CSRF攻击方式
跨站请求可以用各种方式:
- 图片
URL
、超链接、CORS
、Form
提交等等。部分请求方式可以直接嵌入在第三方论坛、文章中,难以进行追踪。 - CSRF通常是跨域的,因为外域通常更容易被攻击者掌控。但是如果本域下有容易被利用的功能,比如可以发图和链接的论坛和评论区,攻击可以直接在本域下进行,且这种攻击方式更加危险!
5、CSRF常见的攻击类型
1)GET类型的CSRF
GET
类型的 CSRF
是较为容易攻击的一种方式,只需要一个 HTTP
请求,攻击者一般做出以下操作:
<img src="http://bank.example/withdraw?amount=10000&for=hacker" >
在受害者访问含有这个 img
的页面后,浏览器会自动向http://bank.example/withdraw?account=xiaoming&amount=10000&for=hacker发出一次 HTTP
请求。 bank.example
就会收到包含受害者登录信息的一次跨域请求。
2)POST类型的CSRF
这种类型的 CSRF
攻击通常使用的是一个自动提交的表单,如:
<form action="http://bank.example/withdraw" method=POST>
<input type="hidden" name="account" value="xiaoming" />
<input type="hidden" name="amount" value="10000" />
<input type="hidden" name="for" value="hacker" />
</form>
<script> document.forms[0].submit(); </script>
访问该页面后,表单会自动提交,相当于模拟用户完成了一次 POST
操作。
POST
类型的攻击通常比 GET
要求更加严格一点,但仍并不复杂。任何个人网站、博客,被黑客上传页面的网站都有可能是发起攻击的来源,后端接口不能将安全寄托在仅允许 POST
上面。
3)链接类型的CSRF
比起其他两种用户打开页面就中招的情况,链接类型的 CSRF
比较不常见,因为这种攻击方式需要用户点击链接才会触发。这种类型通常是在论坛等平台发布的图片中嵌入恶意链接,或者以广告的形式诱导用户中招,攻击者通常会以比较夸张的词语诱骗用户点击,例如:
<a href="http://test.com/csrf/withdraw.php?amount=1000&for=hacker" taget="_blank">
重磅消息!!
<a/>
6、如何防御csrf
1)验证码
增加验证,例如密码、短信验证码、指纹等等,强制用户必须与应用进行交互,才能完成最终请求。这种方式能很好的遏制 csrf
,但是用户体验相对会比较差。
2)Referer check
referer
代表请求的来源,不可以伪造。后端可以通过写一个过滤器来检查请求的 headers
中的 referer
,检验是不是本网站的请求。但缺点是浏览器可以关闭 referer
,且低版本的浏览器会存在伪造 Referer
的风险。
referer
和 origin
的区别,只有 post
请求会携带 origin
请求头,而 referer
不论何种情况下都带。
3)token
token
是最普遍的一种防御方法,后端先生成一个 token
,之后将此放在数据库中并发送给前端,那么前端发送请求时就会携带这个 token
,后端通过校验这个 token
和数据库中的 token
是否一致,以此来判断是否是本网站的请求。
示例:
用户登录输入账号密码,请求登录接口,后端在用户登录信息正确的情况下将 token
放到数据库中,并返回 token
给前端,前端把 token
存放在 localstorage
中,之后再发送请求都会将 token
放到 header
中。
后端写一个过滤器,拦截 POST
请求,注意忽略掉不需要 token
的请求,比如登录接口,获取 token
的接口,以免还没有获取 token
就开始检验 token
。
校验原则:数据库中的 token
和前端 header
中的 token
一致的 post
请求,则说明校验成功,给客户端放行。
三、CSRF与 XSS 区别
CSRF 与 XSS 区别有以下两点:
- 通常来说
CSRF
是由XSS
实现的,CSRF
时常也被称为XSRF
(CSRF
实现的方式还可以是直接通过命令行发起请求等)。 - 本质上讲,
XSS
是代码注入问题,CSRF
是 HTTP 问题。XSS
是内容没有过滤导致浏览器将攻击者的输入当代码执行,CSRF
则是浏览器在发送HTTP
请求时候进行。
四、结束语
对于前端来说,防范攻击还是很重要的,因为谁也预测不了我们写的网站何时会受到攻击。
本文很浅很浅的谈论了关于Web前端安全中的两种攻击模式,希望对大家有帮助!
有不理解或有误的地方也欢迎评论区评论或私信我交流~
- 关注公众号 星期一研究室 ,不定期分享学习干货,学习路上不迷路~
- 如果这篇文章对你有用,记得点个赞加个关注再走哦~
以上是关于前端安全:CSRFXSS该怎么防御?的主要内容,如果未能解决你的问题,请参考以下文章