【问题标题】:Why does lock(this) thread.sleep not work with ASP.NET threading?为什么 lock(this) thread.sleep 不适用于 ASP.NET 线程?
【发布时间】:2010-06-25 20:38:47
【问题描述】:

我有一个密码页面,当有人输入错误的密码时,我想简单地阻止暴力攻击

bool isGoodPassword = (password == expected_password);

lock (this)
{
     if (!isGoodPassword)
           Thread.Sleep(2000);
}

我希望这将允许所有正确的密码而不会停止,但如果一个用户输入了错误的密码,另一个来自不同用户的成功密码也将被阻止。但是,锁似乎不是跨 ASP.NET 线程的lock。没有意义。

【问题讨论】:

    标签: c# asp.net multithreading locking


    【解决方案1】:

    好吧,您还没有展示“this”是什么,但是如果您在页面的上下文中......每个请求都会获得自己的页面实例,不是吗?否则他们一开始怎么会有不同的密码?您将拥有多个线程,每个线程都锁定一个单独的对象。

    在许多方面这是一件好事:您不希望真正的用户受到攻击者的影响。另一方面,这意味着攻击者只需要同时进行多次尝试,就可以有效地忽略你挫败他的企图。正如其他答案所述,您可以通过使用单个对象来解决这个问题 - 但请不要。不要忘记 IIS 不会无限地创建新线程:这种方法将允许单个攻击者使您的整个应用程序对 所有 用户无法使用,不仅用于身份验证,而且在整个应用程序中都无法使用。 . 他们甚至不需要有效的密码。

    相反,您可能希望考虑记录未通过身份验证的 IP 地址,并限制您愿意以这种方式处理的请求数量。 (诚​​然,如果某些用户与攻击者使用相同的代理,这可能会给他们带来问题,但可能性较小。)这不会阻止分布式攻击,但这是一个好的开始。

    【讨论】:

    • 感谢乔恩的回答。有人可以通过多种方式 DOS 我的应用程序,而我正在寻找一种快速且便宜的解决方案。没有考虑多个实例并认为您在那里。
    【解决方案2】:

    如果你真的,真的想阻止所有用户访问该页面,如果其中一个用户的密码弄乱了,你总是可以这样做

    bool isGoodPassword = (password == expected_password);
    
    lock (this.GetType())
    {
         if (!isGoodPassword)
              Thread.Sleep(2000);
    }
    

    正如您所写,这只会减慢当前请求的刷新速度,不会阻止多连接攻击。

    此外,比较密码意味着您知道用户密码,这始终是一种不好的做法。更好的方法是保留用户通行证的(加盐)散列,并将其与输入的散列进行比较。 此外,您可能希望采用渐进式延迟(第一个错误 - 1 秒等待时间,第二个错误 - 2 秒,第 3 个 - 4 等等)

    【讨论】:

      【解决方案3】:

      ASP.NET 在单独的线程上运行每个请求。如果要跨请求锁定,可以使用静态对象:

      public class LogOn : Page
      {
          private static object _delaySync = new object();
      
          private void Authenticate()
          {
              lock(_delaySync)
              {
                   if(password != expected_password)
                   {
                       Thread.Sleep(2000);
                   }
              }
      
          }
      }
      

      不过,按 IP 跟踪请求并阻止任何在一定时间内发送一定量的请求可能更有意义。

      【讨论】:

        【解决方案4】:

        我的两分钱:我曾寻找不同的方法。我不认为软件解决方案是防止拒绝攻击的正确位置。最后,这个解决方案将失败。 IIS 将代码处理到到达锁定代码的位置需要时间。锁定代码不会阻止请求。它一次只允许一个人通过。实际上它就像一个队列。

        话虽如此,请尝试使用静态变量。

        private static readonly  object _lock = new object();
        
        ...
        
        lock (_lock)
        {
             if (!isGoodPassword)
                   Thread.Sleep(2000);
        }
        

        【讨论】:

        • 我认为这个问题与我认为您假设的拒绝服务攻击没有任何关系。这与减慢用户快速猜测许多不同密码的速度有关。但是,是的,我们都同意,尝试的解决方案是一种非常糟糕的方法。
        • 这不是捕获拒绝攻击的好地方,但它可能是捕获字典攻击的合理地方。我不认为你想以这种方式捆绑线程。它实际上会使拒绝攻击更容易。
        • 哎呀!我的错,忘记了静态关键字。嗬!感谢您指出。
        • @Jaxidian 你是对的,我一定把暴力攻击翻译成拒绝服务攻击。啊,嗯……
        猜你喜欢
        • 2017-05-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-23
        • 1970-01-01
        • 2017-10-08
        • 1970-01-01
        • 2018-05-05
        相关资源
        最近更新 更多