CSRF跨站请求伪造的GET情况和POST情况攻击和防御详解
参考书目 《Web安全深度剖析》张炳帅
- CSRF 英文名:cross-site request forgery 叫做跨站请求伪造
- CSRF不是很流行,但是具有很高的危险性,相比于XSS更加难以防范。
- CSRF攻击效果:攻击者盗用身份,以被害者的姓名执行某些非法操作。比如使用账户发邮件、获取敏感信息,盗取银行账户。
CSRF攻击原理
- 当打开某个网站的时候,可以在网站上 进行一些操作,比如发邮件发消息
- 当结束会话的时候,这个网站可能会让你重新登录,或者提示身份过期,这是这个web在防范CSRF攻击的手段。
- CSRF攻击是建立在会话之上的,比如当登录到银行账户进行转账的时候,攻击者给你发送一个URL,利用了社会工程学让你点开了这个URL ,而这个URL是黑客精心设计的转账业务代码,和你所登录的是同一个银行,当你点击这个URL的时候,会发现自己的钱被划走了。
- 其实并不神奇,你的会话是合法的,攻击者的这段代码也是正常的转账代码,比如你想给admin转账1000元,点击提交之后可能会有如下请求:
http://www.bank.com/pay.jsp?username=admin&money=1000
- 而攻击者hacker提供给你的URL里面的代码是这样的
http://www.bank.com/pay.jsp?username=hacker&money=1000
- 这样,你转发给admin的钱到位了,但是由于你中途点开了恶意URL,你的钱也转发给了hacker。
所以CSRF攻击有两个要点:
- 需要建立在浏览器与web服务器之间的会话中
- 社会工程学欺骗用户访问URL
CSRF攻击场景(GET)
- 假如http://www.xxser.com是全球最大的微博平台,全天下所有人都有它的账号。
- 偶然的条件下,黑客Tom对微博收听功能做了个抓包,收听的对象是xxser,报文截取如下:
- 然后它开始分析这个HTTP请求报文,发现在收听某人时,两个参数至关重要——uid和listenid。它猜测uid是自己的id,listenid是收听方的ID。但是不知道开发人员是不是这样想,所以Tom创建了个新的用户(小号)进行测试:pentest。
- 然后收听Tom的大号,报文如下:
- 发现listenid就是大号的uid,所以Tom的猜想是正确的。
- Tom关掉小号,使用大号尝试收听pentest账号,但是没有使用界面化的web程序,而是直接构造url:
http://www.xxser.com/listen?id=218805&listenid=228820
- Tom访问这个页面的时候,刷新列表,发现已经收听了pentest账户
- Tom心想,如果让别人访问这个URL,肯定会收听到自己,成为自己的听众,但是不知道别人的id,这样就无法构造url。
- Tom想,干脆就不写id,所以URL就成了这样:
http://www.xxser.com/listen?id=228820
- 然后Tom又去注册了一个小小号,访问这个URL,没想到收听成功了。
- 于是这Tom胆大包天,想做一次蠕虫攻击。
- 然后Tom想做一个答题充话费的活动,引导大家点击URL,但是他没有流量,效率太低,而且看起来很假。
- Tom想让每个用户都让自己发站内信,或者转发微博,这样效率可以高很多,然后他截取转发微博的报文:
- 经过测试,发现转发微博文章的id是928978,说明只要用户访问
http://www.xxser.com/publish?id=928978
就可以转发他的微博了 - 那么问题来了,如何让一个用户单机一个URL就同时访问两个URL?
- Tom做了一个单独的HTML页面open.html 代码如下:
- 这段代码使用的是iframe标签,用户打开这个网站的时候,也同时会加载下面的两个网站,而且用户还看不见,这样就让用户自动转发了,然后用户的列表好友看到链接说不定也会点进去,这样就导致这个蠕虫在微博中传播。
以上的果树可以知道,CSRF攻击是黑客借助受害者的Cookie骗取到服务器的信任,黑客获取不到Cookie,也看不到Cookie,也因为浏览器的同源策略,黑客无法获得任何东西,CSRF能做的就是给服务器发送请求。
CSRF攻击场景(POST)
- 上面使用的是GET提交请求,即直接使用的是URL,Java中的Servlet和PHP都可以自己选择只接收哪种请求。
- 所以导致有时候GET请求的攻击无法被执行,但是仍然有POST请求的CSRF攻击存在。
- POST请求只有一下的报文服务器才能接收:
- 如下是使用post提交的post.html代码:
- 解释一下: 使用的form表单,type是hidden,就是用户不可见,然后方法是post提交,最后使用js代码实现自动提交,这样用户知道打开URL,就直接进行转发,而且这样,URL就具有很强的隐蔽性。
- 放入jsp代码中进行测试:
- 这里面中,只接收POST请求,访问html页面时,就会跳转:
- 为了让其不跳转,有更好的隐蔽性,可以用form表单中的target来解决这个问题,用target来隐藏跳转;https://www.runoob.com/tags/att-form-target.html
target 属性规定一个名称或一个关键词,指示在何处打开 action URL,即在何处显示提交表单后接收到的响应。
target 属性定义浏览器上下文(比如选项卡、窗口或内联框架)的名称或关键词。
- 我们执行的ifame代码打开页面之后被隐藏,就上面都看不见了,然后黑客自己写点东西伪造一下,就是完美的攻击过程
所以,对于CSRF来时,只是POST的代码要多一点而已,并没有什么本质上的区别。
CSRF的预防
CSRF的预防比较简单,加一些小操作就可以了
二次确认
比如黑客用CSRF让你转账,但是这个时候提示你——是否转账?,或者让你输入验证码什么的,提醒你的误操作,就可以有效防止CSRF。
Token认证
- Token是标志、记号的意思,在IT领域也叫令牌
- Token类似于验证码,但是这种验证码不需要用户输入
- 传统验证码思路是生成验证字符串保存在Session中,然后再客户端生成一个验证图片,只要这个图片和服务器里面的session对应,就通过验证。
- Token是一个不要输入的验证码,当用户进入某些页面的时候,服务器会随机生成一段字符串分给用户,存储再session中,当用户进入某些页面时,就直接传递到Cookie上去了。如果在html中,一般会隐藏起来,如;
<input type="hidden" name="token" value="8wen23kl23j4b1230fweh8">
- 当用户提交表单操作的时候,就会判断这个value和服务器session存储的value是否一样,如果不一样,就有可能时CSRF攻击 。
- 有时用户操作不需要提交表单,比如删除一个人的信息:
http://www.xxser.com/deluser.action?userid=2
- 这样的form表单中插入URL就不太合适,此时,通常就会在Token中存储Cookie。
所以使用Token防御CSRF的步骤如下:
- 当用户登录的时候随机生成一段字符串,存储在session
- 在铭感操作中加入隐藏标签,比如:
- 提交请求后,服务器取出session和token对比
- 更新token值:如果存在XSS漏洞,Token值可能会被窃取
CSRF漏洞相当于XSS漏洞的缩小版,如果网站存在XSS漏洞,那么CSRF漏洞也防不住。
本文来自博客园,作者:{Zeker62},转载请注明原文链接:https://www.cnblogs.com/Zeker62/p/15167765.html