安全性测试--CSRF攻击

一.CSRF是什么?

CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。

二.CSRF可以做什么?

你这可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于**商品,虚拟货币转账......造成的问题包括:个人隐私泄露以及财产安全。

三.CSRF漏洞现状

CSRF这种攻击方式在2000年已经被国外的安全人员提出,但 在国内,直到06年才开始被关注,08年,国内外的多个大型**和交互网站分别爆出CSRF漏洞,如:NYTimes.com(纽约时报)、 Metafilter(一个大型的BLOG网站),YouTube和百度HI......而现在,互联网上的许多站点仍对此毫无防备,以至于安全业界称 CSRF为“沉睡的巨人”。

四.CSRF的原理

下图简单阐述了CSRF攻击的思想:

从上图可以看出,要完成一次CSRF攻击,受害者必须依次完成两个步骤:

1.登录受信任网站A,并在本地生成Cookie。

2.在不登出A的情况下,访问危险网站B。

看到这里,你也许会说:“如果我不满足以上两个条件中的一个,我就不会受到CSRF的攻击”。是的,确实如此,但你不能保证以下情况不会发生:

1.你不能保证你登录了一个网站后,不再打开一个tab页面并访问另外的网站。

2.你不能保证你关闭浏览器了后,你本地的Cookie立刻过期,你上次的会话已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登录/结束会话了......)

3.上图中所谓的攻击网站,可能是一个存在其他漏洞的可信任的经常被人访问的网站。

上面大概地讲了一下CSRF攻击的思想,下面我将用几个例子详细说说具体的CSRF攻击,这里我以一个银行转账的操作作为例子(仅仅是例子,真实的银行网站没这么傻:>)

示例1:

银行网站A,它以GET请求来完成银行转账的操作,如:http://www.mybank.com/Transfer.php?toBankId=11&money=1000

危险网站B,它里面有一段HTML的代码如下:

<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>

首先,你登录了银行网站A,然后访问危险网站B,噢,这时你会发现你的银行账户少了1000块......

为什么会这样呢?原因是银行网站A违反了HTTP规范,使用 GET请求更新资源。在访问危险网站B的之前,你已经登录了银行网站A,而B中的<img>以GET的方式请求第三方资源(这里的第三方就是 指银行网站了,原本这是一个合法的请求,但这里被不法分子利用了),所以你的浏览器会带上你的银行网站A的Cookie发出Get请求,去获取资源 “http://www.mybank.com/Transfer.php?toBankId=11&money=1000”,结果银行网站服务 器收到请求后,认为这是一个更新资源操作(转账操作),所以就立刻进行转账操作......

示例2:

为了杜绝上面的问题,银行决定改用POST请求完成转账操作。

银行网站A的WEB表单如下:

<form action="Transfer.php" method="POST">    <p>ToBankId: <input type="text" name="toBankId" /></p>    <p>Money: <input type="text" name="money" /></p>    <p><input type="submit" value="Transfer" /></p>  </form>

后台处理页面Transfer.php如下:

<?php    session_start();    if (isset($_REQUEST[‘toBankId‘] && isset($_REQUEST[‘money‘]))    {        buy_stocks($_REQUEST[‘toBankId‘], $_REQUEST[‘money‘]);    }  ?>

危险网站B,仍然只是包含那句HTML代码:

<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>

和示例1中的操作一样,你首先登录了银行网站A,然后访问危险网站B,结果.....和示例1一样,你再次没了1000块~T_T,这次事故的原因是:银行后台使用了$_REQUEST去获取请求的数据,而$_REQUEST既可以获取GET请求的数据,也可以获取POST请求的数据,这就造成了在后台处理程序无法区分这到底是GET请求的数据还是POST请求的数据。在PHP中,可以使用$_GET和$_POST分别获取GET请求和POST请求的数据。在JAVA中,用于获取请求数据request一样存在不能区分GET请求数据和POST数据的问题。

示例3:

经过前面2个惨痛的教训,银行决定把获取请求数据的方法也改了,改用$_POST,只获取POST请求的数据,后台处理页面Transfer.php代码如下:

<?php    session_start();    if (isset($_POST[‘toBankId‘] && isset($_POST[‘money‘]))    {        buy_stocks($_POST[‘toBankId‘], $_POST[‘money‘]);    }  ?>

然而,危险网站B与时俱进,它改了一下代码:

<html>  <head>    <script type="text/javascript">      function steal()      {               iframe = document.frames["steal"];               iframe.document.Submit("transfer");      }    </script>  </head>

<body >
    <iframe name="steal" display="none">
      <form method="POST" name="transfer" action="http://www.myBank.com/Transfer.php">
        <input type="hidden" name="toBankId"
value="11">
        <input type="hidden" name="money"
value="1000">
      </form>
    </iframe>
  </body>
</html>

如果用户仍是继续上面的操作,很不幸,结果将会是再次不见1000块......因为这里危险网站B暗地里发送了POST请求到银行!

总结一下上面3个例子,CSRF主要的攻击模式基本上是以上的3种,其中以第1,2种最为严重,因为触发条件很简单,一个<img>就可以了,而第3种比较麻烦,需要使用JavaScript,所以使用的机会会比前面的少很多,但无论是哪种情况,只要触发了CSRF攻击,后果都有可能很严重。

理解上面的3种攻击模式,其实可以看出,CSRF攻击是源于WEB的隐式身份验证机制!WEB的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的!

五.CSRF的防御

我总结了一下看到的资料,CSRF的防御可以从服务端和客户端两方面着手,防御效果是从服务端着手效果比较好,现在一般的CSRF防御也都在服务端进行。

1.服务端进行CSRF防御

服务端的CSRF方式方法很多样,但总的思想都是一致的,就是在客户端页面增加伪随机数。

(1).Cookie Hashing(所有表单都包含同一个伪随机值):

这可能是最简单的解决方案了,因为攻击者不能获得第三方的Cookie(理论上),所以表单中的数据也就构造失败了:>

<?php    //构造加密的Cookie信息    $value = “DefenseSCRF”;    setcookie(”cookie”, $value, time()+3600);  ?>

在表单里增加Hash值,以认证这确实是用户发送的请求。

<?php    $hash = md5($_COOKIE[‘cookie‘]);  ?>  <form method=”POST” action=”transfer.php”>    <input type=”text” name=”toBankId”>    <input type=”text” name=”money”>    <input type=”hidden” name=”hash” value=”<?=$hash;?>”>    <input type=”submit” name=”submit” value=”Submit”>  </form>

然后在服务器端进行Hash值验证

<?php        if(isset($_POST[‘check‘])) {             $hash = md5($_COOKIE[‘cookie‘]);             if($_POST[‘check‘] == $hash) {                  doJob();             } else {        //...             }        } else {      //...        }      ?>

这个方法个人觉得已经可以杜绝99%的CSRF攻击了,那还有1%呢....由于用户的Cookie很容易由于网站的XSS漏洞而被盗取,这就另外的1%。一般的攻击者看到有需要算Hash值,基本都会放弃了,某些除外,所以如果需要100%的杜绝,这个不是最好的方法。

(2).验证码

这个方案的思路是:每次的用户提交都需要用户在表单中填写一个图片上的随机字符串,厄....这个方案可以完全解决CSRF,但个人觉得在易用性方面似乎不是太好,还有听闻是验证码图片的使用涉及了一个被称为MHTML的Bug,可能在某些版本的微软IE中受影响。

(3).One-Time Tokens(不同的表单包含一个不同的伪随机值)

在实现One-Time Tokens时,需要注意一点:就是“并行会话的兼容”。如果用户在一个站点上同时打开了两个不同的表单,CSRF保护措施不应该影响到他对任何表单的提交。考虑一下如果每次表单被装入时站点生成一个伪随机值来覆盖以前的伪随机值将会发生什么情况:用户只能成功地提交他最后打开的表单,因为所有其他的表单都含有非法的伪随机值。必须小心操作以确保CSRF保护措施不会影响选项卡式的浏览或者利用多个浏览器窗口浏览一个站点。

以下我的实现:

1).先是令牌生成函数(gen_token()):

<?php     function gen_token() {     //这里我是贪方便,实际上单使用Rand()得出的随机数作为令牌,也是不安全的。    //这个可以参考我写的Findbugs笔记中的《Random object created and used only once》          $token = md5(uniqid(rand(), true));          return $token;     }

2).然后是Session令牌生成函数(gen_stoken()):

<?php       function gen_stoken() {      $pToken = "";      if($_SESSION[STOKEN_NAME]  == $pToken){        //没有值,赋新值        $_SESSION[STOKEN_NAME] = gen_token();      }          else{        //继续使用旧的值      }       }     ?>

3).WEB表单生成隐藏输入域的函数:

<?php       function gen_input() {            gen_stoken();            echo “<input type=\”hidden\” name=\”" . FTOKEN_NAME . “\”                 value=\”" . $_SESSION[STOKEN_NAME] . “\”> “;       }     ?>

4).WEB表单结构:

<?php          session_start();          include(”functions.php”);     ?>     <form method=”POST” action=”transfer.php”>          <input type=”text” name=”toBankId”>          <input type=”text” name=”money”>          <? gen_input(); ?>          <input type=”submit” name=”submit” value=”Submit”>     </FORM>

5).服务端核对令牌:

这个很简单,这里就不再啰嗦了。

上面这个其实不完全符合“并行会话的兼容”的规则,大家可以在此基础上修改。

转载:http://www.uml.org.cn/Test/201508124.asp

时间: 2024-10-25 07:44:56

安全性测试--CSRF攻击的相关文章

安全测试 - CSRF攻击及防御

CSRF(Cross-site request forgery跨站请求伪造) 尽管听起来像跨站脚本(XSS),但它与XSS非常不同,并且攻击方式几乎相左.XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站. 信任站点A, 恶意站点B, 用户C 攻击流程: 1. 前提: 用户C登录站点A --> 站点A会在用户本地浏览器产生COOKIE 2. 用户C在登录情况下,访问恶意站点B --> B会偷偷发出访问A的请求给用户C 3. 根据B的请求,用户C的浏览器带着c

安全性测试入门 (三):CSRF 跨站请求伪造攻击和防御

安全性测试入门 (三):CSRF 跨站请求伪造攻击和防御 本篇继续对于安全性测试话题,结合DVWA进行研习. CSRF(Cross-site request forgery):跨站请求伪造 1. 跨站请求伪造攻击 CSRF则通过伪装成受信任用户的请求来利用受信任的网站,诱使用户使用攻击性网站,从而达到直接劫持用户会话的目的. 由于现在的主流浏览器比如火狐和谷歌,都倾向于使用单个进程来管理用户会话(比如我们在FF和Chrome中,当要访问一个新页面时,通常是通过新增浏览器页面来达到的,而不是新开一

安全性测试入门(二):Command Injection命令行注入攻击和防御

安全性测试入门(二):Command Injection命令行注入攻击和防御 本篇继续对于安全性测试话题,结合DVWA进行研习. Command Injection:命令注入攻击. 1. Command Injection命令注入 命令注入是通过在应用中执行宿主操作系统的命令,来达到破坏目的的一种攻击方式.如果我们的应用程序将不安全的用户输入传递给了系统命令解析器(shell),那么命令攻击就有可能发生. 通常来说,由应用程序传递操作系统命令会赋有和应用一样的权限,所以如果没有合理防御机制会给系

安全相关的问题、CSRF攻击、怎么确保数据传输中的安全性?

CSRF攻击 又叫“跨站请求伪造”.可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求.CSRF能够做的事情包括:以你的名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账......造成的问题包括:个人隐私泄露以及财产安全. 下图简单阐述了CSRF攻击的思想: 1.用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登陆网站A: 2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登陆网站A成功,可以正常发送请求到网站A: 3.用户未

SameSite Cookie,防止 CSRF 攻击

因为 HTTP 协议是无状态的,所以很久以前的网站是没有登录这个概念的,直到网景发明 cookie 以后,网站才开始利用 cookie 记录用户的登录状态.cookie 是个好东西,但它很不安全,其中一个原因是因为 cookie 最初被设计成了允许在第三方网站发起的请求中携带,CSRF 攻击就是利用了 cookie 的这一"弱点",如果你不了解 CSRF,请移步别的地方学习一下再来. 当我们在浏览器中打开 a.com 站点下的一个网页后,这个页面后续可以发起其它的 HTTP 请求,根据

代码审计:安全性测试方案

安全性测试方案 一.静态代码测试 主要通过对源代码进行安全扫描,根据程序中数据流.控制流.语义等信息与其特有软件安全规则库进行匹对,从中找出代码中潜在的安全漏洞.   代码审计工具RIPS:   介绍:RIPS是一个用php编写的源代码分析工具,它使用了静态分析技术,能够自动化地挖掘PHP源代码潜在的安全漏洞.渗透测试人员可以直接容易的审阅分析结果,而不用审阅整个程序代码.由于静态源代码分析的限制,漏洞是否真正存在,仍然需要代码审阅者确认.RIPS能够检测XSS, SQL注入, 文件泄露,Hea

代码审核:安全性测试方案

安全性测试方案 一.静态代码测试 主要通过对源代码进行安全扫描,根据程序中数据流.控制流.语义等信息与其特有软件安全规则库进行匹对,从中找出代码中潜在的安全漏洞.   代码审计工具RIPS:   介绍:RIPS是一个用php编写的源代码分析工具,它使用了静态分析技术,能够自动化地挖掘PHP源代码潜在的安全漏洞.渗透测试人员可以直接容易的审阅分析结果,而不用审阅整个程序代码.由于静态源代码分析的限制,漏洞是否真正存在,仍然需要代码审阅者确认.RIPS能够检测XSS, SQL注入, 文件泄露,Hea

如何防止CSRF攻击?

CSRF攻击 CSRF漏洞的发生 相比XSS,CSRF的名气似乎并不是那么大,很多人都认为CSRF“不那么有破坏性”.真的是这样吗? 接下来有请小明出场~~ 小明的悲惨遭遇 这一天,小明同学百无聊赖地刷着Gmail邮件.大部分都是没营养的通知.验证码.聊天记录之类.但有一封邮件引起了小明的注意: 甩卖比特币,一个只要998!! 聪明的小明当然知道这种肯定是骗子,但还是抱着好奇的态度点了进去(请勿模仿).果然,这只是一个什么都没有的空白页面,小明失望的关闭了页面.一切似乎什么都没有发生…… 在这平

SQL 注入、XSS 攻击、CSRF 攻击

SQL 注入.XSS 攻击.CSRF 攻击 SQL 注入 什么是 SQL 注入 SQL 注入,顾名思义就是通过注入 SQL 命令来进行攻击,更确切地说攻击者把 SQL 命令插入到 web 表单或请求参数的查询字符串里面提交给服务器,从而让服务器执行编写的恶意的 SQL 命令. 对于 web 开发者来说,SQL 注入已然是非常熟悉的,而且 SQL 注入已经生存了 10 多年,目前已经有很成熟的防范方法,所以目前的 web 应用都很少会存在漏洞允许进行 SQL 注入攻击. 除非是入门开发人员,在开发