防止许多用户共享IP地址的暴力攻击

时间:2014-07-26 02:15:43

标签: php mysql pdo brute-force

我和我的团队正在编写一个PHP5.5的Web应用程序,其中包含一个数据库(除其他外)具有典型的用户名和passhash查找用户身份验证。

我们正在研究防止超过相对数量的方法,比如8,不正确的登录。这是一个面向大约7000名学生的网络应用程序,当他们在4个校园网络中的一个时,将共享相同的传出IP地址。目前,失败的登录记录在表中作为时间戳和IP地址,以及尝试的用户名(外键)或如果用户名不正确则为NULL。

我们已经考虑过一些方法,但都存在安全漏洞或问题:

  • 存储用户代理字符串:许多计算机在各个学校都是标准化的,并生成相同的用户代理字符串

  • 存储本地/网络IP地址:目前尚无可靠有效的评估方法

  • 为每个用户提供一个唯一的ID并存储在cookie中:可以轻松刷新会话,清除缓存,使用不同的浏览器等。

如果有某种方法可以使用PHP或MySQL可靠地识别小网络地址后面的用户,理想情况下我们会比较该地址最近登录尝试的次数。这样我们就可以锁定(服务器端)只有一个用户。

我想知道有更大用户群的网站有效使用哪些方法。

4 个答案:

答案 0 :(得分:3)

此处的标准方法是tar pit。只是放慢速度,这样就无法对暴力攻击账户进行攻击。

另一种方法是在对特定帐户进行如此多次失败尝试后的验证码。唯一的缺点是如果受害者必须为他们的账户输入验证码,他们就会知道他们会受到攻击。

这假设每个人都有一个强密码。强制使用强(长,非字典)密码。

使用这种方法,很少需要锁定受攻击的帐户,但如果您愿意,可以通知他们。

答案 1 :(得分:1)

最近我读到了一个用于识别用户唯一的画布技巧。我完全不理解这个概念,但它与画布在渲染内容时在每台机器上有非常小的差异这一事实有关。 addthis.com例如用它来识别。不是一个非常温和的解决方案,IMO。

该技术被称为:画布指纹识别

这是一个很好的资源:http://browserleaks.com/canvas

答案 2 :(得分:1)

我想我们会去锁定时间/ CAPTCHA组合。

  • 当用户尝试登录>对于同一帐户,他们将被要求完成内部CAPTCHA及其登录。

  • 如果两次CAPTCHA失败,该帐户将被锁定该IP地址5分钟。 (然后是10,然后是20,等等 - 每次后续尝试)

  • 如果尝试失败8次或以上,则可以通过电子邮件向用户发送包含唯一标识符的链接,该标识符允许用户跳过锁定期和/或重置密码。与忘记密码类似,但他们也可以保留密码。

其他措施

  • 如果超过3个不同的IP地址尝试登录一个帐户而在半小时内没有成功 - 强制CAPTCHA开启下一个小时,或者直到从最初的3个IP地址之一成功登录。

这种方法的好处是真正的用户不会因为蛮力尝试失败而被锁定,特别是如果攻击者位于不同的网络上。

答案 3 :(得分:0)

如果客户足够新,您可以利用webRTC。下面是一个将整个数据包转储到屏幕并在控制台中记录单个IP地址的示例。您可以使用javascript将它们发送到服务器并使用它们来阻止。

<html>
 <head>
  <title>Test</title>
  <script>
     function grepSDP(sdp) {
       var hosts = [];
       sdp.split('\r\n').forEach(function (line) {
           if (~line.indexOf('a=candidate')) {
               var parts = line.split(' '),
                   addr = parts[4],
                   type = parts[7];
               if (type === 'host')
                   console.log(addr);
           } else if (~line.indexOf('c=')) {
               var parts = line.split(' '),
               addr = parts[2];
               console.log(addr);
           }
    });
   }

   var peer = new webkitRTCPeerConnection({'iceServers': [{'url': 'stun:stun.services.mozilla.com'}]});
   peer.createOffer(function(sdp) { peer.setLocalDescription(sdp); }, function(err) { console.error(err); }, {});
   setTimeout(function() {
        grepSDP(peer.localDescription.sdp);
        document.getElementById("localdescription").innerHTML = peer.localDescription.sdp;
       }, 500);
  </script>
 </head>
 <body>
  Local description:
  <div id="localdescription">
 </body>
</html>