定义最大密码长度避免拒绝服务攻击(Web长密码拒绝服务漏洞)
Django开源Web应用框架指出过长的密码其实也存在安全问题,容易被黑客利用成为DoS攻击手段之一。过去相当一段时间,我们都强调要用复杂且较长的密码来保护我们的数字资产。大多数网站在保存用户密码时会使用PBKDF2等算法进行加密,以让明文信息得以 哈希值的方式保持于数据库中。然而,这种加密过程会要求服务器执行较为复杂的计算,而密码越长,所消耗的计算时间也就越长。
根据Django的声明指出,一段长达1兆字节的密码若采用PBKDF2算法进行加密,需耗费服务器约一分钟左右的计算时间。此种情况会被黑客所利用——即故意反复发送长度较长,且必定不匹配的密码,则有可能导致服务器宕机,成为典型的DoS攻击案例。
鉴于此,Django在安全更新中特别对密码长度进行了限制为4096个字节。
--------------------------------
没有对明文密码的长度施加任何最大值,这意味着攻击者可以简单地提交任意大且保证失败的密码,迫使运行 服务器执行由此产生的昂贵的哈希计算以尝试检查密码。
例如,在使用 PBKDF2 哈希器时,大小为 1 兆字节的密码将需要大约一分钟的计算时间来检查,“这允许通过重复提交大密码来进行拒绝服务攻击,从而在昂贵的相应哈希计算中占用服务器资源。”
场景一:如果用户名不存在,则不会计算密码哈希,因为用户名不存在。
场景二:如果用户名存在,则计算密码散列并与存储在数据库中的散列进行比较。如果比较的哈希值相同,则授予您访问系统的权限。如果没有,您将被拒绝。
场景三:利用漏洞:用户猜测如果用户名存在并且输入的密码例如是 1000000 A,那么当生成如此长密码的哈希以将其与存储在数据库中的哈希进行比较时,需要更长的时间并且增加时间测量. 因此,如果延迟增加,则用户名存在。
计算密码哈希(带盐的 MD5)的方式会导致在提供非常长的密码时影响 cpu 资源。
拒绝服务如果我们同时使用有效用户名和长密码执行多次登录尝试,则会导致服务器拒绝服务。我们在 Wordpress 7.32、Apache 和 MySQL 默认安装中观察到了两种不同的场景。根据登录尝试的次数和它们之间的时间,我们将有两种不同的情况:
-
DOS 攻击使整个服务器崩溃,因为达到了 RAM 和交换。也达到了CPU。
-
DOS 攻击使数据库崩溃。
--------------------------------
Github 上也有一个 Dumb password Rules 项目,专门收集各个网站和 App 令人抓狂的密码规则,在里面随便找一张都能看到关于密码长度的限制,尤其是**长度。
不少人都觉得限制密码**长度不仅烦人而且没有道理,但如果你问我是不是应该取消这些限制规则,答案是不应该,长度限制是有其背后的逻辑的。有密码**长度其实是件好事,长密码拒绝服务(long password denial of service)这事可是真实存在的,因为服务器端所使用的哈希算法可能会达到长度极限。更重要的是,有了已知的**密码长度能让你可以测试所有的密码字段。显而易见的我们在登陆界面上需要输入它。
登录框可能是在网站上,桌面程序上或者手机应用上。但你知不知道这些密码输入框到底允不允许用户输入(或者粘贴)1000个字符呢?除了登录,注册页面上也需要连续输入两次密码,还有一堆其它的信息,这里面可能有文字,可能有图片——这里的问题是,你的注册表单能处理2000个字符的密码吗?还有密码重置页面,首先用户需要键入旧密码,然后连续两次键入新密码,这有可能就是3000个字符的数据量。在用户和密码存储中间也有我们应该考虑的地方。Web 应用程序的防火墙允许用户发送这么多数据吗?你的应用程序和它使用的框架能接受长密码吗?你的哈希算法是如何处理长字符串的?另外,你页面上的密码输入框允不允许用户输入比登录界面还宽(长)的密码?如果你不测试你的程序看它是否能处理你为其设置的**长度密码,那么你就不能100%确定这个**长度在整个系统中都有效:或者是前端的界面上出了问题,或者它会被防火墙拦截,或者它在后台不能被正确加密…… 可能出现的问题很多,但测试的第一步就是要去定义它的**长度。
现在进行到这一步,我们都了解了定义**长度的意义,但这个长度应该是多少呢?开放式 Web 应用程序安全项目 OWASP 身份验证备忘单 提供了关于正确密码强度控制的建议:
- 强制规定最小密码长度为8以阻止弱密码
- 切勿将**长度定义过低
- 不要截断密码
- 允许出现所有字符(包括 Unicode 和空格)
- 添加密码强度量表
- 不允许使用过于常见或曾被泄露的密码
在设置密码的**长度时,需要牢牢记住建议中的两个要点,一是**长度应该是多少,二是不要截断用户的输入。**长度的数值应该足够高(至少为100),因为任何密码管理工具都不太可能生成这个长度以上的密码。
如果密码的**长度被设置为100个字符,那么每个密码输入框应该至少允许用户输入101个字符,为什么呢:万一用户使用了工具生成200个字符的密码,在键入第101位时你就可以弹出提醒,告诉用户密码已经超过长度。
现在大家就可以去试试,在你正在创建的工程里设置一个**密码长度吧。
- 下一篇:中国互联网域名体系