(这本质上是一个与语言无关的问题,但在我的情况下,我使用的是ASP.NET 3.5)
我正在使用标准的ASP.NET 登录控件,并希望实现以下失败的登录尝试限制逻辑.
处理OnLoginError
事件并在会话中维护失败的登录尝试次数
当此计数达到[某个可配置值]时,阻止来自原始IP地址或该用户/那些用户进行1小时的进一步登录尝试
这听起来像是一种明智的做法吗?我错过了一种可以绕过这种检查的明显方法吗?
注意:ASP.NET Session使用cookie与用户的浏览器相关联
这适用于仅在英国和印度使用的管理站点
Jeff Atwood提到了另一种方法:不是在多次尝试后锁定帐户,而是增加时间,直到允许另一次登录尝试:
1st failed login no delay 2nd failed login 2 sec delay 3rd failed login 4 sec delay 4th failed login 8 sec delay 5th failed login 16 sec delay
这将降低这种保护措施可能被滥用于拒绝服务攻击的风险.
见http://www.codinghorror.com/blog/archives/001206.html
您要做的最后一件事是将所有不成功的登录尝试存储在数据库中,这种方法运行良好,但也会使DDOS攻击使数据库服务器崩溃变得非常简单.
您可能正在使用Web服务器,memcached或类似服务器上的某种类型的服务器端缓存.这些是用于跟踪IP地址和/或用户名失败尝试的完美系统.如果超过登录尝试失败的特定阈值,则可以决定停用数据库中的帐户,但是您将保存对您不需要的失败登录计数器的持久存储的大量读写操作.坚持.
如果你试图阻止人们进行暴力破解身份验证,像Gumbo建议的限制系统可能效果最好.它会使暴力攻击对攻击者不感兴趣,同时在正常情况下甚至在攻击发生时最大限度地减少对合法用户的影响.我建议只计算在memcached或类似的IP中不成功的尝试,如果你曾经成为极度分布式暴力攻击的目标,你总是可以选择开始跟踪每个用户名的尝试,假设攻击者是实际上经常尝试相同的用户名.只要尝试不是非常分散,就像仍然来自可数量的IP地址一样,初始的by-IP代码应该让攻击者足够好.
防止来自IP地址数量有限的国家/地区访问者问题的关键是不要使您的阈值过于严格; 如果你在几秒钟内没有收到多次尝试,你可能没有太多担心重新.脚本强暴.如果您更关心尝试手动解开其他用户密码的人,则可以通过用户名为后续失败的登录尝试设置更宽的边界.
另一个建议是,不回答您的问题,但有些相关,是为您的最终用户强制实施一定级别的密码安全性.我不会过分需要一个混合大小写,至少x个字符,非字典等等密码,因为你还不想在他们还没有注册的时候给人们带来太大的麻烦,但是简单地阻止人们使用他们的用户名作为他们的密码应该有很长的路要走,以保护你的服务和用户免受最不成熟的 - 猜他们为什么称他们为暴力;) - 攻击.
接受的答案会在连续登录尝试中插入越来越多的延迟,这可能会在ASP.NET中执行得非常糟糕,具体取决于它的实现方式.ASP.NET使用线程池来处理请求.一旦此线程池耗尽,传入的请求将排队,直到线程可用.
如果使用Thread.Sleep(n)插入延迟,则将在延迟期间绑定ASP.NET线程池线程.该线程将不再可用于执行其他请求.在这种情况下,简单的DOS风格攻击将是继续提交您的登录表单.最终,每个可用于执行请求的线程都将处于休眠状态(并且会增加一段时间).
我能想到正确实现这种延迟机制的唯一方法是使用异步HTTP处理程序.请参阅演练:创建异步HTTP处理程序.实施可能需要:
在BeginProcessRequest期间尝试身份验证并确定失败时的延迟
返回一个IAsyncResult,暴露将在延迟后触发的WaitHandle
确保在EndProcessRequest中触发了WaitHandle(或阻止它直到它)
这可能会影响您的真正用户.对于前者 在像新加坡这样的国家,ISP的数量有限,而且家庭用户可以使用较少的IP.
或者,您可能会在x尝试阻止脚本小子之后插入验证码.