CSRF全名是 Cross Site Request Forgery,翻成中文就是跨站请求伪造。
攻击原理
因为一般cookie是存放在浏览器的,网页开发者不必另外写程式取用cookie,浏览器就会自动带上先前登入过的状态到网页,CSRF攻击就是利用浏览器会自动带入cookie中存的使用者当前已登入网页的登入状态的这个漏洞,将一些攻击脚本塞进网页里,再利用浏览器储存的使用者权限来进行非本意的操作(翻成白话就是让使用者在不知情的情况下做出一些攻击者预先埋藏在网页里的动作)。
举例
小美常常在XX论坛发表文章,而因为经常登入这个论坛网站,登入状态被浏览器cookie自动存了下来,而这个网站没有任何阻挡CSRF攻击的机制。坏蛋小明发现这件事后,决定要来恶作剧。他知道小美喜欢猫,于是有天在某个部落格网站,放了一个按钮『可爱猫咪相簿连结』,但按钮点下去产生的动作是『 删除 https://XX论坛.com/post/1
」这样的脚本,当小美上当点了下去,就在不知不觉间把自己写的一篇文章给删除了。
身为网页开发者该如何防範?
CSRF token:由网页server端产生一组安全验证码,每次发送post请求时都要在form表单里带入这组验证码,如此一来就能辨识该请求来源是否为本网页。蛮多MVC框架现在都有内建这个功能,让开发者不用自己手动加入,例如Laravel, Rails。以Rails为例:
class ApplicationController < ActionController::Base protect_from_forgery with: :exceptionend
这个功能会在所有的表单中自动插入安全验证码,在进行所有post请求之前,rails server端都会先检查有没有戴上正确的安全验证码:
<form action="/technical_infos" enctype="multipart/form-data" method="post"> <input type="hidden" name="authenticity_token" value="zXeOqhmF0VLxDhtTJVxfDGv1ik5jmIyreAA1qNHtC3/0rTo1dwUr4b4uIUtS2plnD3+PrsCO/aZVrw==">
将coockie存在local storage:前面有提到,CSRF攻击的前提是『浏览器有自动带上登入状态』,若登入资讯存放在local storage(也就是使用者的电脑),当使用者再次浏览登入过的网页时,网页开发者必须额外写程式来取用先前的登入状态。危险的操作就要求使用者再次输入密码:例如现实中多数银行APP对于身份验证是很严格的,尤其在付款、转帐这种敏感的操作前都会要求使用者再次输入密码或透过简讯验证码都来确认身份,唯有如此才能更严谨的确认这个操作是来自使用者本人的意志(密码被盗就另当别论了)。另外,浏览器的同源政策,也就是用来阻挡跨域请求(CORS)以避免钓鱼网站在网页内容里放一些攻击脚本的一种机制。同源政策某种程度上也可预防CSRF(但只能防止一部份),而身为网页开发者总不能期望每个浏览器都有这层保护机制,该处理的一些安全性问题还是得靠自己。