天天看点

DVWA学习之CSRF(跨站请求伪造)CSRF(Cross-site request forgery,跨站请求伪造)

DVWA学习之CSRF

  • CSRF(Cross-site request forgery,跨站请求伪造)
    • 0x01 何为CSRF?
    • 0x02 CSRF原理
    • 0x03 low级别
    • 0x04 medium级别
    • 0x05 high级别
    • 0x06 impossible级别
    • 0x07 CSRF防御
      • 服务端的防御
        • 验证HTTP Referer字段
        • 在请求地址中添加token并验证
        • 在HTTP头中自定义属性并验证
      • 用户端的防御
      • 安全设备的防御

CSRF(Cross-site request forgery,跨站请求伪造)

0x01 何为CSRF?

CSRF:全称Cross-site request forgery,翻译过来就是跨站请求伪造, 是指利用受害者尚未失效的身份认证信息(cookie、会话等),诱骗其 点击恶意链接或者访问包含攻击代码的页面,在受害人不知情的情况下 以受害者的身份向(身份认证信息所对应的)服务器发送请求,从而完 成非法操作(如转账、改密等)。CSRF与XSS最大的区别就在于,CSRF并 没有盗取cookie而是直接利用。

相信看到下面这幅图,你就对CSRF这一简写印象深刻

DVWA学习之CSRF(跨站请求伪造)CSRF(Cross-site request forgery,跨站请求伪造)

0x02 CSRF原理

csrf攻击的原理如下:

1.正常的用户通过输入口令登录了网站A(被攻击站点);

2.网站A(被攻击站点)判断该用户口令合法性,产生cookie保存在浏览器中,此时用户登录网站A成功;

3.用户在没有退出网站A(被攻击站点)的情况下,访问了网站B(攻击者的站点);

4.网站B(攻击者的站点)接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问网站A;

5.浏览器在收到攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据受害者的Cookie信息以受害者的权限处理该请求,导致来自网站B的恶意代码被执行。

crsf原理图如下:

DVWA学习之CSRF(跨站请求伪造)CSRF(Cross-site request forgery,跨站请求伪造)

0x03 low级别

low级别CSRF:只是对输入的两次密码是否相同进行了简单的判断,没有进行其他的防御,因此,只要用户在cookie还有小的时间内在相同的浏览器访问我们给定的url(该操作是服务器对请求的发送者进行了身份验证,检查cookie),就可以实现CSRF 攻击,最终修改密码。

方式一:直接指定URL,让用户进行点击(该方式,构造URL攻击小郭太过于明显,用户只要一看靠该URL即可判断是恶意链接)

构造恶意URL: http://192.168.15.164/dvwa/vulnerabilities/csrf/?password_new=my&password_conf=my&Change=Change#
           
DVWA学习之CSRF(跨站请求伪造)CSRF(Cross-site request forgery,跨站请求伪造)

此外、CSRF最关键的是利用受害者的cookie向服务器发送伪造请求,所以受害者之前用的是IE浏览器登录的系统,而后通过谷歌浏览器浏览该恶意链接,攻击是不会触发的,因为请求谷歌浏览器没有存储受害者登录cookie,而会直接跳入登录界面.

DVWA学习之CSRF(跨站请求伪造)CSRF(Cross-site request forgery,跨站请求伪造)

方式二:使用一些技巧,将url做一下改变,例如:缩短网址,将较长较明显的恶意URL变为短连接:

DVWA学习之CSRF(跨站请求伪造)CSRF(Cross-site request forgery,跨站请求伪造)

诱导用户点击短连接,当点击网短连接后,直接跳转到原来的链接,更改用户密码:

DVWA学习之CSRF(跨站请求伪造)CSRF(Cross-site request forgery,跨站请求伪造)

通过缩短链接的方式:也存在缺点,当用户点击短连接后,仍然会跳转到原有链接,出现更改密码的界面,一旦用户看到修改密码的界面,就全露馅了

方式三:通过构造一个恶意页面,让用户访问页面时,出现诸如:404错误之类的伪装页面(这里就直接恶作剧了),悄悄的更改用户的密码。

首先,构造页面demo.html:通过img标签中的src属性来加载CSRF攻击利用的URL,并进行布局隐藏,实现了受害者点击链接则会将密码修改。

<img src="http://192.168.15.164/dvwa/vulnerabilities/csrf/?password_new=my&password_conf=my&Change=Change#" border="0" style="display:none;"/> <h1>hello gay<h1> <h2>Your password has been changed!!!<h2>
           

其次:将页面放在公网上或者自己的服务器上(这里就直接上传到本地的另一台服务器),诱导受害者访问上传的页面。

受害者访问上传的恶意页面(< img>display设为none,直接执行不回显),当受害者看到该页面,密码已经被偷偷修改:

DVWA学习之CSRF(跨站请求伪造)CSRF(Cross-site request forgery,跨站请求伪造)

0x04 medium级别

首先,将级别调为medium,bp抓个包

DVWA学习之CSRF(跨站请求伪造)CSRF(Cross-site request forgery,跨站请求伪造)

这里先介绍几个源码中用到的函数

stripos(string,find,start):函数查找字符串在另一字符串中第一次出现的位置,不区分大小写。
 eregi(string pattern, string string):检查string中是否含有pattern(不区分大小写),如果有返回True,反之False。
 
 PHP超全局变量$_SERVER中的两个值:
 
 $_SERVER['HTTP_REFERER']:PHP中获取链接到当前页面的前一页面的url链接地址,即HTTP数据包中的Referer参数的值。
 $_SERVER['SERVER_NAME']:PHP中获取服务器主机的名称,即HTTP数据包中的Host参数的值。
           

该级别检查了保留变量HTTP_REFERER(http-header的Referer参数的值,表示源地址)中是否包含SERVER_NAME(http包头的Host参数,及要访问的主机名,这里是192.168.15.164),希望通过这种机制抵御CSRF攻击。一开始就调用eregi()函数来判断HTTP头的referer字段里是不是包含“192.168.15.164”字符串,即发送请求的是不是本机,如果是则继续后面代码的执行。

简而言之,若想通过验证就必须确保在http请求中国年Referer字段中必须包含host,所以只需要在连接中添加目标的host即可通过验证。

在攻击者的服务器中将html文件命名为:192.168.15.164.html

诱导受害者访问:http://192.168.15.241/192.168.15.164.html

DVWA学习之CSRF(跨站请求伪造)CSRF(Cross-site request forgery,跨站请求伪造)

然后,我们验证是否更改成功,由于服务器没有安装bp,就直接用主机清空历史记录,重新登录:登录失败

DVWA学习之CSRF(跨站请求伪造)CSRF(Cross-site request forgery,跨站请求伪造)

0x05 high级别

high级别中:设置了token限制,它是在每次访问此页面时,会随机生成一个token,当发起服务器请求时服务器会检查它的值。思路:先获取token的值,再构造链接并诱骗受害者访问。

问题也就出来了:如何获取token呢??

这里提供一个思路:利用XSS将攻击代码直接注入到目标服务器。或者(XSS+CSRF)利用js的ajax跨域请求去得到token,然后带着token访问改密页面。(就是构造一个链接诱骗点击,这个链接执行一段放在自己服务器上js,js执行先得到token,

然后改密。)

我们的想法,想起来很简单,但实际并没有这么容易,为什么呢?我们回想一下,CSRF(Cross-site request forgery,跨站请求伪造)是属于跨站攻击,我们攻击代码放在自己的服务器上,想让受害者通过我们的脚本,而后偷偷连接受害者并修改密码,这属于跨域攻击,然而现在的浏览器 禁止跨域请求,所以我们通过在自己服务器上的脚本,无法获取受害者user_token。所以,这种通过在自己的服务器上上传脚本文件,引诱受害点击,然后脚本请求受害者主机的方法行不通。

那我们就没办法了么???程序员不能说不:

那么我们就可以:另辟蹊径:

新思路一:那就想办法,直接把脚本文件偷偷上传到受害者的服务器呗,然后引诱其访问自己服务器的脚本,至于怎么上传,你可以…哈哈,自己思考吧,谁让我们是未来的渗透工程师呢。

新思路二:利用dvwa的xss漏洞,直接获取受害者的cookie信息,然后通过bp修改cookie,进行一次重放攻击,简单粗暴,直接达到目的。但这种方法,并不是十分实用,因为我们是在实验,我们知道dvwa存在的xss漏洞,如果是实战,又怎么能晓得受害着是否存在xss漏洞呢?至于xss漏洞,在后面的章节将继续分享

0x06 impossible级别

当我们点击到impossible级别的源码,后可以清楚的发现,imposing级别不仅使用了Anti-CSRF token检验来杜绝一定上的CSRF漏洞的利用,还加入了PDO(PHP Data Objects )技术用来防御SQL注入,还要求输入当前密码来确定执行此操作的是否为用户本人用来防护CSRF。基本杜绝了恶意用户的攻击。

0x07 CSRF防御

CSRF的防御一般分为三个层面:服务端的防御、用户端的防御和安全设备的防御

服务端的防御

服务端的防御主要有三种策略:验证HTTP Referer 字段、在请求地址中添加token验证、在HTTP头中自定义属性并验证。

验证HTTP Referer字段

根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,比如需要访问 http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory,用户必须先登陆 bank.example,然后通过点击页面上的按钮来触发转账事件。这时,该转帐请求的 Referer 值就会是转账按钮所在的页面的 URL,通常是以 bank.example 域名开头的地址。而如果黑客要对银行网站实施 CSRF 攻击,他只能在他自己的网站构造请求,当用户通过黑客的网站发送请求到银行时,该请求的 Referer 是指向黑客自己的网站。因此,要防御 CSRF 攻击,银行网站只需要对于每一个转账请求验证其 Referer 值,如果是以 bank.example 开头的域名,则说明该请求是来自银行网站自己的请求,是合法的。如果 Referer 是其他网站的话,则有可能是黑客的 CSRF 攻击,拒绝该请求。

这种方法的显而易见的好处就是简单易行,网站的普通开发人员不需要操心 CSRF 的漏洞,只需要在最后给所有安全敏感的请求统一增加一个拦截器来检查 Referer 的值就可以。特别是对于当前现有的系统,不需要改变当前系统的任何已有代码和逻辑,没有风险,非常便捷。

然而,这种方法并非万无一失。Referer 的值是由浏览器提供的,虽然 HTTP 协议上有明确的要求,但是每个浏览器对于 Referer 的具体实现可能有差别,并不能保证浏览器自身没有安全漏洞。使用验证 Referer 值的方法,就是把安全性都依赖于第三方(即浏览器)来保障,从理论上来讲,这样并不安全。事实上,对于某些浏览器,比如 IE6 或 FF2,目前已经有一些方法可以篡改 Referer 值。如果 bank.example 网站支持 IE6 浏览器,黑客完全可以把用户浏览器的 Referer 值设为以 bank.example 域名开头的地址,这样就可以通过验证,从而进行 CSRF 攻击。

即便是使用最新的浏览器,黑客无法篡改 Referer 值,这种方法仍然有问题。因为 Referer 值会记录下用户的访问来源,有些用户认为这样会侵犯到他们自己的隐私权,特别是有些组织担心 Referer 值会把组织内网中的某些信息泄露到外网中。因此,用户自己可以设置浏览器使其在发送请求时不再提供 Referer。当他们正常访问银行网站时,网站会因为请求没有 Referer 值而认为是 CSRF 攻击,拒绝合法用户的访问。

在请求地址中添加token并验证

CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。

这种方法要比检查 Referer 要安全一些,token 可以在用户登陆后产生并放于 session 之中,然后在每次请求时把 token 从 session 中拿出,与请求中的 token 进行比对,但这种方法的难点在于如何把 token 以参数的形式加入请求。对于 GET 请求,token 将附在请求地址之后,这样 URL 就变成 http://url?csrftoken=tokenvalue。 而对于 POST 请求来说,要在 form 的最后加上 ,这样就把 token 以参数的形式加入请求了。但是,在一个网站中,可以接受请求的地方非常多,要对于每一个请求都加上 token 是很麻烦的,并且很容易漏掉,通常使用的方法就是在每次页面加载时,使用 javascript 遍历整个 dom 树,对于 dom 中所有的 a 和 form 标签后加入 token。这样可以解决大部分的请求,但是对于在页面加载之后动态生成的 html 代码,这种方法就没有作用,还需要程序员在编码时手动添加 token。

该方法还有一个缺点是难以保证 token 本身的安全。特别是在一些论坛之类支持用户自己发表内容的网站,黑客可以在上面发布自己个人网站的地址。由于系统也会在这个地址后面加上 token,黑客可以在自己的网站上得到这个 token,并马上就可以发动 CSRF 攻击。为了避免这一点,系统可以在添加 token 的时候增加一个判断,如果这个链接是链到自己本站的,就在后面添加 token,如果是通向外网则不加。不过,即使这个 csrftoken 不以参数的形式附加在请求之中,黑客的网站也同样可以通过 Referer 来得到这个 token 值以发动 CSRF 攻击。这也是一些用户喜欢手动关闭浏览器 Referer 功能的原因。

在HTTP头中自定义属性并验证

这种方法也是使用 token 并进行验证,和上一种方法不同的是,这里并不是把 token 以参数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自定义的属性里。通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中。这样解决了上种方法在请求中加入 token 的不便,同时,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer 泄露到其他网站中去。

然而这种方法的局限性非常大。XMLHttpRequest 请求通常用于 Ajax 方法中对于页面局部的异步刷新,并非所有的请求都适合用这个类来发起,而且通过该类请求得到的页面不能被浏览器所记录下,从而进行前进,后退,刷新,收藏等操作,给用户带来不便。另外,对于没有进行 CSRF 防护的遗留系统来说,要采用这种方法来进行防护,要把所有请求都改为 XMLHttpRequest 请求,这样几乎是要重写整个网站,这代价无疑是不能接受的。

用户端的防御

对于普通用户来说,都学习并具备网络安全知识以防御网络攻击是不现实的。但若用户养成良好的上网习惯,则能够很大程度上减少CSRF攻击的危害。例如,用户上网时,不要轻易点击网络论坛、聊天室、即时通讯工具或电子邮件中出现的链接或者图片;及时退出长时间不使用的已登录账户,尤其是系统管理员,应尽量在登出系统的情况下点击未知链接和图片。除此之外,用户还需要在连接互联网的计算机上安装合适的安全防护软件,并及时更新软件厂商发布的特征库,以保持安全软件对最新攻击的实时跟踪。

安全设备的防御

至于安全设备的防御,普通用户就通过安装防火墙等软件设置好过滤规则进行防御;企业等机构就使用实体设备进行防御,直接架设专门的防火墙进行防御。

注:防御阶段实现方法引用自:https://blog.csdn.net/stpeace/article/details/53512283

继续阅读