繁体   English   中英

使用php中的会话防止登录攻击

[英]Prevent attack on login using sessions in php

我正在尝试使用会话来存储登录尝试的数量。 当达到最大登录尝试次数时,我将客户端的IP地址存储在黑名单表中。

我考虑过的一些事情,您可能需要了解:

  • 我正在使用session_regenerate_id(); 在我设置会话值之后。
  • 我不会在会话之外使用任何cookie,因为这不是必需的,而不是2012:p
  • 用户IP被列入黑名单,直到我从黑名单表中删除他的行。
  • SESSION_MAX_ATTEMPTS是已定义的常量,设置为5。
  • index.php?module=login&task=blacklist page只是向用户显示一条被列入黑名单的消息。 此页面没有任何功能。
  • 我正在使用自定义构建php框架,所以我不得不将一些名为method的OOP转换为简化的php代码。

在执行登录查询之前调用以下函数:

private function preventAttack()
{
    $blocked = getData("SELECT count(*) as blocked FROM blacklist WHERE ip = @Value0;", Array( $_SERVER['REMOTE_ADDR'] ));
    if($blocked[0]["blocked"] == "1")
    {
        redirect("index.php?module=login&task=blacklist");
    }
    $old = (int)$this->session->get("login_attempts");
    if(!empty($old))
    {           
        if($old > SESSION_MAX_ATTEMPTS)
        {
            setData("INSERT INTO blacklist SET ip = @Value0;", Array( $_SERVER['REMOTE_ADDR'] ));
            redirect("index.php?module=login&task=blacklist");
        }
        else
        {
            $old++;
            $this->session->set("login_attempts",$old);
        }
    }
    else
    {
        $this->session->set("login_attempts", 0);
    }
}

第一个if语句的工作原理包括两个查询,但我坚持认为存储尝试次数的最佳方法是什么,以及最好的方法是什么? 也许你们可以让我朝着正确的方向前进。

如果您对我的代码有任何疑问,请添加评论。 我知道它有点不可读,因为它来自我的框架,我在发布之前已经翻译了一下。

存储数据库中失败尝试的次数,而不是会话。 注意:您可能需要将每个失败以及时间戳保留在其自己的记录中(并忽略/删除任何早于阈值的内容)。

顺便说一句,回应deceze的评论:

这种方法存在巨大缺陷:会话取决于客户端发送cookie。 真正的攻击者根本不会发回cookie。 ziiiing你必须通过IP来获取一切。

对此的解决方案是,您不接受未在其他地方设置的有效会话cookie附带的登录尝试。

非常感谢,我从你的评论中学到了很多东西。 对于有相同问题的用户,我将解释我所学到的知识以及我如何使用这些知识。

到目前为止我学到了什么:

  1. 真正的攻击者根本不会发回cookie。 因此,在这种情况下使用cookie或会话没有任何意义。
  2. 如果要将攻击者列入黑名单,请使用可以自动为您执行此操作的防火墙。 从您的脚本执行此操作是没有意义的,会话太容易被规避,如果您检查IP地址,您可能会阻止整个办公室或学校使用相同的外部IP。
  3. 无论您做什么:仅将登录尝试数据存储在数据库/ flatfile / etc中的服务器上。 用户或攻击者将无法轻松编辑此数据。
  4. 如果您确实在Web服务器上存储数据以提高性能,请将其存储在文件中,而不是数据库中。

如果我忘记了什么请评论,我将编辑这篇文章。

我检查了我的托管服务提供商,他们已经使用上面提到的防火墙之类的解决方案阻止了很多这些攻击者。 所以我将停止尝试在我的脚本中执行此操作。

我的脚本现在已修复,只有黑名单用户和noob黑客猜测密码:

private function preventAttack()
{
    $blocked = getData("SELECT count(*) as blocked FROM blacklist WHERE ip = @Value0;", Array( $_SERVER['REMOTE_ADDR'] ));
    if($blocked[0]["blocked"] == "1")
    {
        redirect("index.php?module=login&task=blacklist");
    }
    $old = (int)$this->session->get("login_attempts");
    if($old > 0)
    {           
        if(($old + 1) >= SESSION_MAX_ATTEMPTS)
        {
            setData("INSERT INTO blacklist SET ip = @Value0;", Array( $_SERVER['REMOTE_ADDR'] ));
            $this->session->set("login_attempts", 0);
            redirect("index.php?module=login&task=blacklist");
        }
        else
        {
            $old++;
            $this->session->set("login_attempts",$old);
        }
    }
    else
    {
        $this->session->set("login_attempts", 1);
    }
}

由于我不太确定这个平台将获得多少用户,并且我不希望可能的高mysql服务器负载我决定不在数据库中存储登录尝试。 也许在未来,谁知道。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM