我有一个密码页面,当有人输入错误的密码时,我想通过
来挫败蛮力攻击bool isGoodPassword = (password == expected_password);
lock (this)
{
if (!isGoodPassword)
Thread.Sleep(2000);
}
我希望这会允许所有正确的密码而不会停顿,但如果一个用户输入了错误的密码,另一个用户的另一个成功密码也会被阻止。但是,在ASP.NET线程中,锁似乎不是lock
。没有意义。
答案 0 :(得分:16)
好吧,你还没有显示“这个”是什么,但是如果你在页面的上下文中......每个请求都会得到它自己的页面实例,不是吗?否则他们首先会有不同的密码?你将有几个线程,每个线程都锁定一个单独的对象。
在很多方面,这是好的事情:您不希望真正的用户受到攻击者的攻击。另一方面,这意味着攻击者只需要并行进行多次尝试,以便有效地忽略你欺骗他的企图。正如其他答案所述,你可以通过使用单个对象来解决这个问题 - 但请不要。不要忘记IIS不会无限制地创建新线程:这种方法可以让单个攻击者使整个应用程序无法用于所有用户,而不仅仅是用于身份验证,而是整个应用程序。他们甚至不需要有效的密码。
相反,您可能希望考虑记录身份验证失败的IP地址,并限制您愿意以这种方式处理的请求数量。 (不可否认,如果某些用户与攻击者在同一个代理服务器后面,可能会遇到问题,但不太可能。)这不会阻止分布式攻击,但这是一个良好的开端。
答案 1 :(得分:2)
如果你真的,真的想阻止所有用户访问该页面,如果其中一个搞砸了他的密码,你可以随时
bool isGoodPassword = (password == expected_password);
lock (this.GetType())
{
if (!isGoodPassword)
Thread.Sleep(2000);
}
正如你所写的,这只会减慢当前请求的刷新速度,它不会阻止多连接攻击。
另外,比较密码意味着你知道用户密码,这总是一种不好的做法。更好的方法是保留用户传递的(盐渍)哈希值,并将其与输入的哈希值进行比较。 此外,您可能希望使用渐进式延迟(第一个错误 - 1秒等待时间,第二个错误 - 2s,第3 - 4等等)
答案 2 :(得分:2)
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跟踪请求并阻止在一定时间内发送特定音量的任何内容可能更有意义。
答案 3 :(得分:2)
我的两分钱:我想找一个不同的方法。我不相信软件解决方案是防止拒绝攻击的正确位置。最终,此解决方案将失败。 IIS将代码处理到达锁定代码的时间需要一些时间。锁码不会阻止请求。它只允许一次通过。实际上它充当队列。
话虽如此,请尝试使用静态变量。
private static readonly object _lock = new object();
...
lock (_lock)
{
if (!isGoodPassword)
Thread.Sleep(2000);
}