csrf从小白到入门(简单易懂,有逻辑)

<1>简介

csrf(cross-site-request-forgery)俗称跨站请求伪造,这种漏洞是服务端对用户审核不严格导致的。简单来说就是伪造一个用户的身份做一些违法乱纪的事情。举例说明,假如有一个人叫A,A打开了一个网站,这个网站在A打开并且登录之后返回了一个cookie,如果我这时发了一个钓鱼邮件给A,邮件中有我提前写好的html文件,A打开邮件附录的
html文件之后会直接访问他刚刚打开的网站,这时计算机会直接将刚刚的cookie发给服务器,这样就实现了冒用他的身份。有的人可能会问,这样做了之后有什么危害?有危害是肯定的,要是我冒用A的身份打开的是一个银行的网页,且这个网页有转账的功能我要是直接用脚本完成转账的动作,那么这就算是完成了一次攻击,且对A也好还是银行也好都是不好的,足以看出csrf的危害。

<2>csrf分类及实例

众所周知,在HTTP协议中规定了8种传递数据的方式,所以理论上csrf应该有八种类型,不过对于现实来说服务器上的网站一般用post和get两种方式来传递参数,所以我接下来将要用pikachu上面的几种方法来举例csrf和csrf的防御方法还有csrf跨域请求的方法。

(1)get传参的csrf

所谓get传参的csrf就是服务器接收数据是用get的方式,打开pikachu,登录一个用户的账号,比如用用户名为vince密码是123456的账户
csrf从小白到入门(简单易懂,有逻辑)csrf从小白到入门(简单易懂,有逻辑)
登录上去之后理论上前端就已经收到了后端传过来的cookie那么我们只差伪造一个url就能开始骗用户点击之后修改他的信息了
打开开发者工具查看网络种的记录可以发现传来了cookie
csrf从小白到入门(简单易懂,有逻辑)
我们伪造一个“诱人”的url骗他们点击之后就可以实现发送cookie冒用身份了。首先我们要确定修改用户页面传的get参数。
转到用户修改数据页面之后就可以根据源码看get传的参数了
csrf从小白到入门(简单易懂,有逻辑)如上图我们可以发现传的参数是如上几个,我们构造一下url,把vince用户的个人信息改成好玩的参数
原本从修改页面传回的url如下

127.0.0.1/pikachu/vul/csrf/csrfget/csrf_get_edit.php?sex=lal&phonenum=123456&add=lilian&email=dumb&submit=submit

经过修改成了这样子

&lt;a href="http://127.0.0.1/pikachu/vul/csrf/csrfget/csrf_get_edit.php?sex=你必狂吃不胖&phonenum=你必越长越好看&add=你必天天捡钱&email=你必好运连连&submit=submit"&lt;美女荷官,在线发牌,百万影片你想要的这里都有</a&gt;

那么在一个能解析html标签的环境下你就会发现它变成了如下的标签
csrf从小白到入门(简单易懂,有逻辑)要是被你骗的人真的点击之后会是这样子

csrf从小白到入门(简单易懂,有逻辑)现在你成果完成了一次csrf

(2)post传参的csrf

有些网站并不是get传参而是post传参那么此时我们怎么实现csrf呢?我会用钓鱼邮件中附加一个html的方式,有可能也会用恶意服务器的方式,也可以用xss+csrf组合拳的方式传递参数。我在这里就介绍一下伪恶意服务器的方法。之所以说他是伪恶意服务器是因为我不可能真的做一个服务器,我是将sql-labs的靶场源文件改了改成了一个在集成环境中的伪恶意网站。基于上文的原理,我们可以想到csrf的基本套路,但是我们也发现刚刚的传参方式在post类型中并不适用所以我们要用以上三种方法用post方式传递数据。
首先要写一个搭建在集成环境上的网站,我就直接用了sql-labs靶场第十一关,原本第十一关的代码如下

csrf从小白到入门(简单易懂,有逻辑)

更改之后第十一关的代码改成了如下样子
csrf从小白到入门(简单易懂,有逻辑)此时在一个新的窗口中访问sql-labs靶场第十一关,会是如下

csrf从小白到入门(简单易懂,有逻辑)
原本vince的信息是如下图

csrf从小白到入门(简单易懂,有逻辑)
再点击sql-labs的submit按钮之后就能实现csrf,实现之后vince信息被改成了如下样子

csrf从小白到入门(简单易懂,有逻辑)

(3)加入token的csrf

在服务器传回的数据中加入名为token的变量,那么就能有效防范csrf。但是可以肯定的是世上没有绝对的东西,token虽然能有效防御csrf,但是做不到完全。csrf的重点是冒用正常用户的身份,用他的身份做一些事情。用之前讲的老套路套路加入token的csrf明显是行不通的,因为你自己写的网页也好、url也好是不能用javascript等语言写的脚本调取另一个窗口的数据的。他们循序了同源策略。下面首先介绍一下同源策略之后再说绕过实例。

  • token简单来说就是服务器随机生成的一个字符串,在一个请求到达服务器的时候,服务器会首先查看请求中是否有合法的token,有的话才会正常处理。

<3>同源策略

同源策略是指同源的脚本才能互相调用dom树、cookie、token的情况。下面是判断两个脚本同源的条件。

1.协议:比如用http协议的网站文件不能调用用https协议的网站文件。
2.域名:比如一个域名是forming.com那么与handsome.com就不遵守同源协议。值得一提的是一级域名与二级域名之间也是不遵守同源策略的,比如forming.com和handsome.forming.com之间也不遵守同源策略。
3.端口:就是字面意思的端口也没有什么好解释的。

同源策略是一种安全策略,为的就是保护用户的隐私,但是本着“既然存在就一定有漏洞”的原则,同源策略也是有办法绕过的。

<4>加入token后实现csrf

直接用之前提的两种方法因为同源策略的原因是不行的。基于此一般要用xss+csrf组合拳的方式再结合上跨域的方法将数据传递出去实现绕过,首先需要本页面具有xss漏洞(对xss了解不多的童鞋可以看看这篇文章xss(cross site script)注入点、注入语句及危害知识总结)实现javascript脚本的注入,之后调取必要信息和token实现csrf。

  • 举例:假如www.first.com的a.html存在xss漏洞,注入一个iframe框架,框架的网页指向是之前的恶意网站www.second.com的b.html,其中iframe的src属性中要包含hash记录(就是#后面要有东西),其中的hash值是a.html的cookie和token,这样实现了数据的跨域传递。然后b.html中有根据hash记录接受cookie和token实现csrf。这种方法根据下文跨域方法中的location.hash的跨域思路,不过不完全相同。

<5>跨域的方法(克服同源策略的方法)

(1)可以跨域的HTML标签

1.<img>标签
通过src属性

2.<audio>标签
通过src属性

3.<video>标签
通过src属性

4.<embed>标签
通过src属性

5.<script>标签
通过src属性

6.<applet>标签
通过code属性

7.<object>标签
通过data属性

8.<link>标签
通过src属性

9.<iframe>标签
通过src属性

还有其它很多类似的标签,它们都有类似的属性,src属性code属性等访问属性中url的功能更多的标签就不再这里一 一列举。但是值得注意的是,用src属性实现的跨域是没办法用javascript实现读、写的,这是因为内在配置的问题。

(2)jsonp跨域

jsonp的全程是json with padding,其实就是通过刚刚的一些可以跨域的标签将数据以json的方式将数据在不同域之间传输,还可以将js脚本放到此域下文件然后通过跨域标签引入到这个html文件中。

(3)window.name

这里要先引入一个"window对象"的概念,所谓window对象就是在浏览器上打开的窗口,又或者是在iframe标签中嵌套的框架打开的网页。而每一个window对象都有一个window.name的属性,这个属性有一个特性是当上一个窗口定义了该属性之后,即使跳转也不会刷新这个属性,同时每一个网页都对它有读写的权力。

(4)CORS(跨域资源共享)

简单理解来说这就是一种规则,可以让浏览器向服务器发出xmlhttprequst请求,这其实就是在http消息头中加入一些参数,让双方通过参数来认识彼此之后,以此来跨域进行数据交互。CORS请求有两种类型

  • 1.简单请求
    【1】简单请求要同时满足两大条件:
    <1>请求方式:1.HEAD 2.GET 3.POST
    <2>消息头中有只有这几个参数:
    1.Accept(告诉服务端自己接受什么介质类型)
    2.Accept-Language(浏览器申明自己接收的语言)
    3.Content-Language(服务端表明自己响应对象的语言)
    4.Content-Type(服务端告诉浏览器响应对象的类型)
    【2】浏览器
    客户端会在跨域的请求中加入一些参数,比如origin参数来说明这个请求的发起源,服务端就可以由此判断接下来的反应。
    【3】服务端
    服务端有三个参数access-control-allow-credentials、access-control-allow-origin、access-control-expose-header可以被用于http消息头。以"allow-credentials"结尾的参数的值有且仅有一个就是"true",这个参数的作用是要不要客户端发送cookie。以“allow-origin”结尾的参数的值就是发送这个消息头的服务器的url,这个参数的作用是说明这个请求来自哪个源(有协议、域名、端口)让服务端据此作出回应。“expose-header”结尾的参数是明确标注出要客户端在消息头中添加的数据。
  • 2.非简单请求
    只要不是简单请求的都是非简单请求,它们的不同之处在于,非简单请求在简单请求的基础上加了一个预检请求,这个请求要在刚刚描述的请求之前
    (1)预检请求
    【1】浏览器
    本质上就是在发出真正的请求之前,先在http消息头中加一些参数和服务端通信,加入的参数有origin、access-control-allow-methods、access-control-allow-header这三个参数的值和之前的类似就不再赘述,这些参数在传给服务端之后,服务端会核对这些参数,并做出如下应答。
    【2】服务端
    服务端会在应答消息头中放的参数有access-control-allow-origin、access-control-allow-methods、access-control-allow-header参数值和之前说的一样,就不在赘述。还有一个参数是access-control-max-age,这个参数是规定这个预检请求在多长时间内有效,意思就是浏览器在规定时间内不用再发送预检请求。这个参数的值是以毫秒为单位的值,比如值为300000意思就是50分钟内要是再和服务端建立联系的话都不用发送预检请求。
    (2)正常请求
    正常请求就和简单请求的参数一样了。

(5)location.hash

【1】首先要知道什么是hash,所谓hash就是url中最后#后面的参数
【2】浏览器请求的时候这个跨域的方法其实就是应用iframe标签,将forming.com下的first.html中的内联框架指向handsome.com下的second.html,然后将传进来的hash值进行编辑之后传递给一个与first.html同源的网页thirth.html,通过first.html和thirth.html同源实现脚本的调用。这就实现了“私货”的夹带。

(6)window.postmessage

可以通过这个js脚本语言将不同源的网页间的脚本调用。

(7)document.domain

这个函数的先决条件是,在主域名同源的子域名间设置参数实现不同源的脚本的调用。

<6>其它防护方法的介绍

浏览器之外对于服务器的安全策略,CSP(content security policy)内容安全策略,你可以把它理解为服务器的”配置器“,服务器支不支持哪些标签都可以由它来定义,想要绕过它就是多尝试,毕竟它把什么东西都禁用了,网站也不能正常运行了,比如标签用不了就去用标签,只要思路骚就没有绕不过去的东西。

上一篇:常见web安全及防护原理


下一篇:Django csrf