`
yinwufeng
  • 浏览: 288693 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

防止CSRF攻击

阅读更多

<script src="http://luoq.net/include/jscript/ajax.js" type="text/javascript"></script><script src="http://luoq.net/include/jscript/show.js" type="text/javascript"></script><script src="http://luoq.net/include/jscript/fiximage.js" type="text/javascript"></script><script type="text/javascript"></script>  

防止CSRF攻击

最近在做项目的安全。找了些资料研究了一番,不错,有意思

 

 

标题:防止csrf攻击
作者:Nexus
网站:http://nexus.playhack.net
日期:2007-10-25 (ISO 8601)

译者:韩国峰 http://www.hanguofeng.com

概览:

1. Hello World
2. 介绍
3. 关于认证技术
3.1 Cookies Hashing
3.2 HTTP来路
3.3 验证码
4. 一次性令牌
5. 最后的话

1.Hello World

欢迎来到崭新的Playhack.net的新季度开题项目报告。我非常高兴您能够再次回来让我们的c001项目重现。

希望您能喜欢这个新的短篇论文,我邀请你浏览位于http://www.playhack.net的全部新项目。

开始:几乎没有什么,只是一点香烟!:

呐喊:我向我的playhack m8s null,omni,god and emdel,ofc o str0ke大声呐喊!NEX 回来了。

2.介绍

我对跨站请求伪造(Cross Site Request Forgery,即csrf)技术有一定研究,但是对网站开发者应当采取的措施研究不深。这些日子在编写一个对用户和管理员(这些人对他们的任务并不明晰:P)有高度安全要求的分布式网站程序时,我被这个话题深刻的纠缠了。

针对这种情况,我必须考虑程序最终可能受到的各个方面的可能的攻击威胁。

给我最多麻烦的就是Session欺骗(或者CSRF,你可以按照自己喜欢的方式称呼),因为这种攻击是完全以用户的身份,因此并没有百分百的可能性来防止它。

如果你对我刚才说所的Session欺骗并不太了解,那么你可以阅读:http://www.playhack.net/view.php?id=30

3.可行措施

Ok,从这里开始,我必须假定你对Session欺骗攻击的实施方法已经深刻领会了:P

让我们开始新的继续。

考虑到一个已经登录到网站的受信用户可以完成一些重要的或者私密的操作,攻击者尝试记性一个可能的登录攻击(但是大多数情况下是不可行的)并且得到已经登录用户的Session来实现其巧妙的行为。

为了劫持用户的Seession,入侵者精心构造一个适当的网页,在这个网页中包含了隐藏的JavaScript函数来重新创造一个原始操作表单,但是攻击者却修改了一些表单值,然后攻击者让受攻击者访问该页面,此时页面加载过程会提交上述表单到一个远程页面,以隐秘地完成一个请求(此时受攻击者并不知道),他们用这种方法利用了用户的受信身份。

这种方式简单解释了Session欺骗攻击是如何工作的,但是一个重要的问题是,“我如何避免我的用户成为这种攻击的受害者?”

现在,你可能想到如下的几种方法:

检查Cookies凭据
检查HTTP请求来路
使用验证码
但是经过一些尝试,你会发现这些方法不是我们应当采取的最合适的解决方式,让我们一个个的来看为什么。

3.1 Cookies Hashing

第一个方案可能是解决这个问题的最简单和快捷的方案了,因为攻击者不能够获得被攻击者的Cookies内容,也就不能够构造相应的表单。

这个问题的实现方法与下面的类似。在某些登录页面我们根据当前的会话创建Cookies:

  1. <!-- login.php -->  
  2. <?php  
  3. // Cookie value  
  4. $value = "Something from Somewhere";  
  5. // Create a cookie which expires in one hour  
  6. setcookie("cookie"$value, time()+3600);  
  7. ?>  
  8. <!-- EOF -->  

 

在这里,我们在Cookies中使用了散列来使得这个表单可被认证。

  1. <!-- form.php -->  
  2.       <?php  
  3.       // Hash the cookie  
  4.       $hash = md5($_COOKIE['cookie']);  
  5.       ?>  
  6.       <form method="POST" action="resolve.php">  
  7.            <input type="text" name="first_name">  
  8.            <input type="text" name="last_name">  
  9.            <input type="hidden" name="check" value="<?=$hash;?>">  
  10.            <input type="submit" name="submit" value="Submit">  
  11.       </form>  
  12.       <!-- EOF -->  

 

此时,后台的动态网页部分可以进行如下操作:

  1. <!-- resolve.php -->  
  2.  <?php  
  3.  // Check if the "check" var exists  
  4.  if(isset($_POST['check'])) {  
  5.       $hash = md5($_COOKIE['cookie']);  
  6.       // Check if the values coincide  
  7.       if($_POST['check'] == $hash) {  
  8.            do_something();  
  9.       } else {  
  10.            echo "Malicious Request!";  
  11.       }  
  12.  } else {  
  13.       echo "Malicious Request!";  
  14.  }  
  15.  ?>  
  16.  <!-- EOF -->  

 

事实上,如果我们不考虑用户的Cookies很容易由于网站中存在xss漏洞而被偷窃(我们已经知道这样的事情并不少见)这一事实,这是一个很好的应对对CSRF的解决方案。如果我们为用户的每一个表单请求中都加入随机的Cookies,那么这种方法会变得更加安全,但是这并不是十分合适。

3.2 HTTP来路

检测访问来路是否可信的最简单方法是,获得HTTP请求中的来路信息(即名为Referer的HTTP头—译者注)并且检查它来自站内还是来自一个远程的恶意页面:这是一个很好的解决方法,但是由于可以对服务器获得的请求来路进行欺骗以使得他们看起来合法,这种方法不能够有效防止攻击。

让我们来看看为什么这并不是一个合适的方法。

下面的代码展示了HTTP Referer实现方法的一个例子:

  1. <!-- check.php -->  
  2.  if(eregi("www.playhack.net"$_SERVER['HTTP_REFERER'])) {  
  3.       do_something();  
  4.  } else {  
  5.       echo "Malicious Request!";  
  6.  }  
  7.  <!-- EOF -->  

 

这个检测则会轻易的忽略掉来自某个攻击者伪造的HTTP Referer欺骗,攻击者可以使用如下代码:

  1. header("Referer: www.playhack.net");  

 

或者其他在恶意脚本中伪造HTTP头并发送的方法。

由于HTTP Referer是由客户端浏览器发送的,而不是由服务器控制的,因此你不应当将该变量作为一个信任源。

3.3 验证码

另外一个解决这类问题的思路则是在用户提交的每一个表单中使用一个随机验证码,让用户在文本框中填写图片上的随机字符串,并且在提交表单后对其进行检测。

这个方法曾经在之前被人们放弃,这是由于验证码图片的使用涉及了一个被称为MHTML的Bug,可能在某些版本的微软IE中受影响。

你可以在Secunia的站点上获得关于此缺陷的详细信息:http://secunia.com/advisories/19738/ 。

这里是Secunia关于此Bug解释的概述:

“此缺陷是由于处理“mhtml:”的URL处理器重定向引起的。它可以被用来利用从另外一个网站访问当前的文档”

在同一个页面你会找到来自Secunia工作人员的网站测试方法。

事实上,我们知道,这个Bug已经被微软放出的Windows XP和Windows Vista及其浏览器IE6.0的修复包所解决了。

即使他的确出现了安全问题,这么长时间也会有其他的可靠方案出现。

4.一次性令牌

 现在让我们来看经过研究,我希望介绍的最后一种解决方案:在使用这些不可靠的技术后,我尝试做一些不同然而却是更有效的方法。

为了防止Web表单受到Session欺骗(CSRF)的攻击,我决定检测可能被伪装或伪造的每一个项目。因此我需要来创造一次性令牌,来使得在任何情况下都不能够被猜测或者伪装,这些一次性令牌在完成他们的工作后将被销毁。

让我们从令牌值的生成开始:

  1. <!-- start function -->  
  2. <?php  
  3. function gen_token() {  
  4.      // Generate the md5 hash of a randomized uniq id  
  5.      $hash = md5(uniqid(rand(), true));  
  6.      // Select a random number between 1 and 24 (32-8)  
  7.      $n = rand(1, 24);  
  8.      // Generate the token retrieving a part of the hash starting from  
  9.      // the random N number with 8 of lenght  
  10.      $token = substr($hash$n, 8);  
  11.      return $token;  
  12. }  
  13. ?>  
  14. <!-- EOF -->  

 

 PHP函数uniqid()允许web开发者根据当前的时间(毫秒数)获得一个唯一的ID,这个唯一ID有利于生成一个不重复的数值。

我们检索相应ID值的MD5散列,而后我们从该散列中以一个小于24的数字为开始位置,选取8位字母、

返回的$token变量将检索一个8位长的随机令牌。

现在让我们生成一个Session令牌,在稍后的检查中我们会用到它。

  1. <!-- start function -->  
  2. <?php  
  3. function gen_stoken() {  
  4.      // Call the function to generate the token  
  5.      $token = gen_token();  
  6.      // Destroy any eventually Session Token variable  
  7.      destroy_stoken();  
  8.      // Create the Session Token variable  
  9.      session_register(STOKEN_NAME);  
  10.      $_SESSION[STOKEN_NAME] = $token;  
  11. }  
  12. ?>  
  13. <!-- EOF -->  

 

 在这个函数中我们调用gen_token()函数,并且使用返回的令牌将其值复制到一个新的$_SESSION变量。

现在让我们来看启动完整机制中为我们的表单生成隐藏输入域的函数:

  1. <!-- start function -->  
  2. <?php  
  3. function gen_input() {  
  4.      // Call the function to generate the Session Token variable  
  5.      gen_stoken();  
  6.      // Generate the form input code  
  7.      echo "<input type=\"hidden\" name=\"" . FTOKEN_NAME . "\" 
  8.           value=\"" . $_SESSION[STOKEN_NAME] . "\"> ";  
  9. }  
  10. ?>  
  11. <!-- EOF -->  

 

我们可以看到,这个函数调用了gen_stoken()函数并且生成在WEB表单中包含隐藏域的HTML代码。

接下来让我们来看实现对隐藏域中提交的Session令牌的检测的函数:

  1. <!-- start function -->  
  2. <?php  
  3. function token_check() {  
  4.      // Check if the Session Token exists  
  5.      if(is_stoken()) {  
  6.           // Check if the request has been sent  
  7.           if(isset($_REQUEST[FTOKEN_NAME])) {  
  8.                // If the Form Token is different from Session Token  
  9.                // it's a malicious request  
  10.                if($_REQUEST[FTOKEN_NAME] != $_SESSION[STOKEN_NAME]) {  
  11.                     gen_error(1);  
  12.                     destroy_stoken();  
  13.                     exit();  
  14.                } else {  
  15.                     destroy_stoken();  
  16.                }  
  17.           // If it isn't then it's a malicious request  
  18.           } else {  
  19.                gen_error(2);  
  20.                destroy_stoken();  
  21.                exit();  
  22.           }  
  23.      // If it isn't then it's a malicious request  
  24.      } else {  
  25.           gen_error(3);  
  26.           destroy_stoken();  
  27.           exit();  
  28.      }  
  29. }  
  30. ?>  
  31. <!-- EOF -->  

 

这个函数检测了$_SESSION[STOKEN_NAME]和$_REQUEST[FTOKEN_NAME]的存在性(我使用了$_REQUEST方法来使得GET和POST两种方式提交的表单变量均能够被接受),而后检测他们的值是否相同,因此判断当前表单提交是否是经过认证授权的。

这个函数的重点在于:在每次检测步骤结束后,令牌都会被销毁,并且仅仅在下一次表单页面时才会重新生成。

这些函数的使用方法非常简单,我们只需要加入一些PHP代码结构。

下面是Web表单:

  1. <!-- form.php -->  
  2. <?php  
  3.      session_start();  
  4.      include("functions.php");  
  5. ?>  
  6. <form method="POST" action="resolve.php">  
  7.      <input type="text" name="first_name">  
  8.      <input type="text" name="last_name">  
  9.      <!-- Call the function to generate the hidden input -->  
  10.      <? gen_input(); ?>  
  11.      <input type="submit" name="submit" value="Submit">  
  12. </FORM>  
  13. <!-- EOF -->  

 

 下面是解决的脚本代码:

  1. <!-- resolve.php -->  
  2. <?php  
  3.      session_start();  
  4.      include("functions.php");  
  5.        
  6.      // Call the function to make the check  
  7.      token_check();  
  8.        
  9.      // Your code  
  10.      ...  
  11. ?>  
  12. <!-- EOF -->  

 

你可以看到,实现这样一个检测是十分简单的,但是它可以避免你的用户表单被攻击者劫持,以避免数据被非法授权。

5.结论

让我们对这篇简短的论文做一个结论,你的Web应用程序没有百分百的安全,但是你可以开始避免绝大多数普通的攻击技术。

我希望您关注的另一个要点是,Web开发者不应当忽视一般的程序错误(例如xss 浏览器漏洞等等),不将这些考虑为对您的用户的潜在威胁是一个巨大的错误:你应该永远记得它们将影响程序的信任性、安全性和互操作性。

分享到:
评论

相关推荐

    防止CSRF攻击.txt

    ### 防止CSRF攻击 #### 1. 引言 跨站请求伪造(Cross-Site Request Forgery,简称CSRF)是一种攻击方法,它迫使已登录的Web应用程序用户在其当前已经认证的情况下执行未授权的操作。攻击者通过在用户浏览器上发起...

    详解如何在spring boot中使用spring security防止CSRF攻击

    Spring Boot 中使用 Spring Security 防止 CSRF 攻击 CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。CSRF 攻击可以盗用用户的...

    Tomcat怎样防止跨站请求伪造(CSRF) 1

    为了防止这种攻击,Tomcat 提供了一个名为 CSRF Prevention Filter 的工具,该工具能够帮助开发者保护他们的 Web 应用免受 CSRF 攻击。 一、CSRF 攻击的原理 CSRF 攻击的原理是攻击者诱骗受信任用户访问恶意网站,...

    【ASP.NET编程知识】浅谈ASP.NET MVC 防止跨站请求伪造(CSRF)攻击的实现方法.docx

    浅谈 ASP.NET MVC 防止跨站请求伪造(CSRF)攻击的实现方法 本文档对 ASP.NET MVC 中防止跨站请求伪造(CSRF)攻击的实现方法进行了详细的探讨。首先,文章介绍了 CSRF 攻击的定义和历史,然后通过一个模拟的示例,...

    CSRF攻击的应对之道

    在请求地址中添加一个随机生成的 token,并在服务器端验证该 token 是否正确,以防止 CSRF 攻击。 3. 在 HTTP 头中自定义属性并验证 在 HTTP 头中添加一个自定义的属性,并在服务器端验证该属性,以防止 CSRF 攻击。...

    基于JSP的Java Web项目的CSRF防御示例

    确保令牌的随机性和一次性使用,能有效防止CSRF。 3. **HTTPOnly Cookie**:设置Cookie为HTTPOnly可以防止JavaScript通过DOM访问,降低Cookie被XSS攻击窃取的风险,从而间接增强CSRF防护。 4. **Double Submit ...

    详解利用django中间件django.middleware.csrf.CsrfViewMiddleware防止csrf攻击

    **Django CSRF防护详解** CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种...确保在所有可能的POST请求中包含CSRF令牌,并更新你的前端代码以处理CSRF保护,可以有效地防止CSRF攻击,保护用户数据的安全。

    使用ASP.NET Core,JavaScript和Angular防止CSRF攻击

    在ASP.NET Core、JavaScript和Angular开发的Web应用中,防止CSRF攻击是至关重要的。本文将详细探讨如何在这些技术栈中实施有效的防护措施。 **ASP.NET Core中的CSRF防护** ASP.NET Core提供了一种内置的CSRF防护...

    安全 毕设 csrf的攻击实现

    四、防止CSRF攻击的策略 1. 验证Referer字段:检查请求的来源是否为预期的网站,但这并非绝对安全,因为Referer可以被篡改。 2. 使用CSRF令牌:每个表单提交时都应包含一个随机生成的CSRF令牌,服务器端验证该令牌...

    环形防伪:环形中间件可防止CSRF攻击

    如果请求中没有正确的令牌或者令牌不匹配,服务器将拒绝处理该请求,从而防止CSRF攻击。 环形中间件的工作流程如下: 1. **令牌生成**:当用户登录成功后,服务器生成一个随机且唯一的防伪令牌,并将其存储在会话...

    切记ajax中要带上AntiForgeryToken防止CSRF攻击

    在程序项目中经常看到ajax post数据到服务器没有加上防伪标记,导致CSRF被攻击,下面小编通过本篇文章给大家介绍ajax中要带上AntiForgeryToken防止CSRF攻击,感兴趣的朋友一起学习吧

    ring-anti-forgery:环中间件以防止CSRF攻击

    Ring-Anti-Forgery中间件通过生成和验证一个随机的、一次性使用的令牌来防止CSRF攻击。这个令牌通常被包含在表单隐藏字段中或作为HTTP头部的一部分,当用户提交表单时,服务器会检查这个令牌是否匹配,如果不匹配,...

    CSRF跨站请求伪造CSRF PHP demo代码

    因此,`login.php`需要包含防止CSRF攻击的安全措施,例如使用CSRF令牌。 CSRF令牌是一种验证机制,每个表单提交时都应携带一个独一无二且难以预测的令牌。在`index.html`和`exciting.html`中,可以看到表单的示例,...

    Web应用安全:CSRF攻击手段与影响.pptx

    防止CSRF攻击的方法主要包括: 1. **令牌验证** - 在关键操作中使用一次性或随机生成的令牌,每次请求都需验证。 2. **Referer检查** - 检查请求的来源(Referer头),确保请求来源于预期的页面。 3. **用户确认** ...

    浅谈CSRF攻击方式

    ### 浅谈CSRF攻击方式 #### 一、CSRF是什么? CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种常见的网络攻击手段,它利用用户在浏览器中保存的有效凭证(如Cookie等),通过伪装成受害者的身份对目标...

    Web应用安全:CSRF防范对策.pptx

    防止CSRF攻击的关键在于确保请求的完整性和合法性,通过验证额外的安全信息(如Token)以及监控请求来源,可以显著提高Web应用的安全性。开发者应当根据应用的具体情况选择合适的防范措施,以确保用户的数据安全不受...

    基础漏洞csrf挖掘实战

    身份认证是防止CSRF攻击的关键环节。常见的认证方式包括基础身份认证协议、Session和Cookie。这里主要讨论Cookie。Cookie是服务器在用户浏览器上存储的小型文本文件,用于跟踪用户状态。它们包含名/值对,可以设置...

    简解:CSRF的原理及防御

    简解:CSRF的原理及防御

Global site tag (gtag.js) - Google Analytics