PHP中CSRF(跨站点请求伪造)攻击实例及防范

PHP中CSRF(跨站点请求伪造)攻击实例及防范,php,csrf,owasp,Php,Csrf,Owasp,我有一个网站,人们可以这样投票: http://mysite.com/vote/25 http://mysite.com/vote/30 这将对项目25进行表决。我只想让注册用户可以使用,而且只有当他们想这样做的时候。现在我知道当有人在网站上忙碌时,有人会给他们这样的链接: http://mysite.com/vote/25 http://mysite.com/vote/30 然后,投票将是他在该项目上的位置,而不是他想这样做 我读过这本书,但我不太懂 这是CSRF的一个例子,我怎样才能

我有一个网站,人们可以这样投票:

http://mysite.com/vote/25
http://mysite.com/vote/30
这将对项目25进行表决。我只想让注册用户可以使用,而且只有当他们想这样做的时候。现在我知道当有人在网站上忙碌时,有人会给他们这样的链接:

http://mysite.com/vote/25
http://mysite.com/vote/30
然后,投票将是他在该项目上的位置,而不是他想这样做

我读过这本书,但我不太懂

这是CSRF的一个例子,我怎样才能防止这种情况发生。我能想到的最好的办法就是在链接中添加一些东西,比如散列。但是在所有链接的末尾加上一些东西会让人非常恼火。没有其他方法可以做到这一点


还有一件事,也许有人能给我举一些其他的例子,因为这个网站对我来说似乎相当令人神魂颠倒。

如果:

  • 获取该链接(通过
    
    
    您只需对该项目投赞成票;-)


    通常使用的解决方案是在URL中放置一个生命周期有限的令牌,并且在获取URL时,检查该令牌是否仍然有效

    其基本思想是:

    • 生成页面时:
      • 生成唯一的令牌
      • 将其存储在用户会话中
      • 并将其放置在页面的链接中,如下所示:
        http://mysite.com/vote/30?token=AZERTYUHQNWGST
    • 调用投票页面时:
      • 检查URL中是否存在令牌
      • 检查它是否存在于用户会话中
      • 如果没有=>请不要登记投票
    这里的想法是:

    • 代币的使用寿命不长,很难猜测
    • 这意味着您的攻击者:
      • 只有几分钟的注射有效期
      • 必须善于猜测^^
      • 必须为每个用户生成不同的页面

    另外,请注意,用户离开您的站点后,会话保持活动状态的时间越短,当他访问坏网站时,会话仍然有效的风险就越小

    但在这里,您必须在安全性和用户友好性之间进行选择


    另一个想法(这不是很安全,但有助于对付那些不知道如何强制发布请求的家伙),就是只在人们投票时接受发布请求:

    • 浏览器正在发送注入标记的GET请求
    • 由于此URL正在修改某些数据,无论如何,它不应与GET一起使用,而应仅与POST一起使用

    但请注意,这并不是完全安全的:可以(可能?)使用一些Javascript强制/伪造POST请求。

    首先,GET请求不应用于更改服务器上的状态,因此对于您的投票服务,我建议使用POST/PUT。这只是一个指导方针,但很聪明

    所以对于您的问题,CSRF是一个客户机问题,所以无论您使用哪种服务器语言(您使用的是PHP)。标准的修复方法是相同的,如下所示:在URI/POST数据中有一个随机值,在Cookie头中有相同的值。如果这些匹配,你可以确定没有CSRF。在StackOverflow上有很多关于如何实现这一点的信息,例如…

    祝你好运

    OWASP有一个用于PHP的CSRFGuard和一个用于PHP的ESAPI,这是我很久以前为XMB->Ultimab->GaiaBB编写的

    似乎其他人已经清理了该代码,并允许使用更强大的令牌:

    谢谢,
    安德鲁

    有3名球员参与CSRF攻击

  • 受害者网站(您示例中的投票网站)[知道其登录用户cookie]
  • 您客户的浏览器(当他登录时)[知道他的cookies]
  • 攻击者网站[不知道登录用户的cookie]
  • CSRF攻击取决于两个事实

  • 浏览器会随每个请求自动发送cookie
  • 我们依靠cookie来识别登录用户(例如:
    setcookie(“sessionID”、“0123456789ABCDEF”、time()+3600”);
  • 如果攻击者可以通过远程或其他方式使登录用户请求此

    <img src="http://mysite.com/vote/30" />
    
    例如,通过将链接放在攻击者网站上或通过电子邮件发送,登录的客户端浏览器将随此请求一起发送识别cookie(sessionID),这将使受害者网站认为其登录的用户确实想要投票

    但是,如果受害者的网站更聪明,并使用额外的GET或POST参数(而不是cookies)验证其登录用户的请求,那么攻击者现在就有问题了,因为GET和POST参数不是由浏览器自动发送的,他必须猜测

    // http://victim.website/vote/30
    
    攻击者不知道
    csrfSecret
    参数,该参数是受害者网站与其客户端之间的秘密(就像会话令牌一样),因此攻击者无法构建他想要伪造请求的URL

    同样,如果投票是通过POST请求完成的,攻击者将无法在其网站(或第三方网站)上制作表单,因为他不知道受害者网站与其用户之间的秘密

    // http://victim.website/vote/30?csrfSecret=0123456789ABCDEF
    
    
    
    你说得对,伪造GET和POST请求一样容易。虽然我不同意有必要拥有过期的代币。如果攻击者能够获得您的会话数据,那么您的麻烦将比一些额外的投票更大。但是您建议的修复仍然有效,因为密钥只是在Cookie和请求数据(保存在Cookie中或绑定到用户会话密钥)中有一个令牌/随机值。谢谢你们的建议。我将更改所有链接以拥有此令牌。我不得不承认,这是一种省钱的方法。但是我不打算实施令牌过期,我同意MygGaN的观点。你们中的任何一个哈