参考: The Web Application Hacker’s Handbook
1.Design Flaws in Authentication Mechanisms(1)(身份验证机制中的设计缺陷)
身份验证功能比Web应用程序中通常使用的任何其他安全机制受更多的设计弱点困扰。 即使在应用程序根据用户名和密码对用户进行身份验证的看似简单的标准模型中,该模型的设计缺陷也可能使应用程序很容易受到未经授权的访问。
1.1 Bad Passwords(弱密码)
许多网络应用程序对用户密码的质量没有采取任何控制措施,甚至没有采取任何控制措施。 通常会遇到允许以下密码的应用程序:
- 1.非常短或空白
- 2.常用的字典单词或名称
- 3.和用户名相同
- 4.仍设置为默认值
图6-1显示了弱密码质量规则的示例。 最终用户通常几乎不了解安全问题。 因此,很可能未执行强密码标准的应用程序将包含大量设置了弱密码的用户帐户。 攻击者可以轻松猜测这些帐户,从而授予他(或她)未经授权的应用程序访问权限。
HACK STEPS
尝试发现有关密码质量的任何规则:
- 1.查看网站关于密码规则的任何描述
- 2.如果可以进行自我注册,请尝试使用不同类型的弱密码注册多个帐户,以发现已有的规则。
- 3.如果您控制一个帐户,并且可以更改密码,请尝试将密码更改为各种弱值。
如果仅通过客户端控制来强制实施密码质量规则,那么这本身就不是安全问题,因为普通用户仍将受到保护。 狡猾的攻击者可以为自己分配一个弱密码,通常不会威胁到应用程序的安全。
1.2 Brute-Forcible Login(蛮力登录)
登录功能向攻击者发出了公开邀请,使其可以尝试猜测用户名和密码,从而获得对应用程序的未授权访问。 如果该应用程序允许攻击者使用不同的密码重复尝试登录,直到他猜出正确的密码为止,那么即使是业余攻击者,也要在其浏览器中手动输入一些常用的用户名和密码,它都极易受到攻击。
最近,对高品质站点的攻击使人们可以访问以明文形式或使用蛮力散列存储的数十万个真实密码。 以下是最流行的现实世界密码:
password
- website name
123456
qwerty
abc123
111111
monkey
12345
letmein
管理密码实际上可能比密码策略所允许的弱。 它们可能是在策略生效之前设置的,也可能是通过其他应用程序或界面设置的。
在这种情况下,任何严重的攻击者都将根据冗长的常用值列表,使用自动化技术来尝试猜测密码。 鉴于当今的带宽和处理能力,通过标准的PC和DSL连接,每分钟可以进行数千次登录尝试。 在这种情况下,即使是最可靠的密码也最终会被破坏。
在第14章中详细介绍了以这种方式使用自动化的各种技术和工具。图6-2显示了使用Burp Intruder对单个帐户成功进行密码猜测的攻击。 成功的登录尝试可以通过HTTP响应代码,响应长度和不存在“ login errors”消息的区别来清楚地区分。
在某些应用程序中,采用客户端控件来尝试防止猜测密码的攻击。 例如,应用程序可以设置cookie(例如,failedlogins = 1),并在每次失败尝试后将其递增。 当达到某个阈值时,服务器会在提交的cookie中检测到此阈值,并拒绝处理登录尝试。 这种客户端防御可能会阻止仅使用浏览器发起手动攻击,但是当然可以轻松绕开它,如第5章所述。
当失败的登录计数器保存在当前会话中时,就会发生上述漏洞的变体。 尽管在客户端可能没有任何指示,但是攻击者所需要做的就是获得一个新会话(例如,通过保留其会话cookie),然后他可以继续进行密码猜测攻击。
最后,在某些情况下,应用程序会在适当数量的失败登录后锁定目标帐户。 但是,它使用指示(或允许攻击者推断)所提供的密码是否正确的消息来响应其他登录尝试。 这意味着即使锁定了目标帐户,攻击者也可以完成其猜测密码的攻击。 如果该应用程序在一定的延迟后自动解锁帐户,则攻击者只需等待此事件发生,然后使用发现的密码照常登录。
HACK STEPS
- 1.手动为您控制的帐户提交几次错误的登录尝试,并监视收到的错误消息。
- 2.大约10次失败登录后,如果应用程序未返回有关帐户锁定的消息,请尝试正确登录。 如果成功,则可能没有帐户锁定策略。
- 3.如果该帐户被锁定,请尝试使用其他帐户重复该练习。 这次,如果应用程序发出任何cookie,则将每个cookie仅用于一次登录尝试,并为每个后续的登录尝试获取新的cookie。
- 4.另外,如果该帐户已被锁定,请查看与无效密码相比,提交有效密码是否会导致应用程序行为发生任何差异。 如果是这样,即使帐户被锁定,您也可以继续进行密码猜测攻击。
- 5.如果您不控制任何帐户,请尝试枚举有效的用户名(请参阅下一节),并使用该用户名进行几次错误的登录。 监视有关帐户锁定的任何错误消息。
- 6.要发动暴力攻击,请首先确定应用程序在成功登录和失败登录后的行为有所不同。 您可以使用此事实来区分自动攻击过程中的成功与失败。
- 7.获取枚举或常用用户名列表和常用密码列表。 使用获得的有关密码质量规则的任何信息来定制密码列表,以避免不必要的测试用例。
- 8.使用合适的工具或自定义脚本,使用这些用户名和密码的所有排列来快速生成登录请求。 监视服务器的响应以识别成功的登录尝试。 第14章详细介绍了使用自动化执行自定义攻击的各种技术和工具。
- 9.如果您一次定位多个用户名,通常最好以广度优先而不是深度优先的方式进行这种蛮力攻击。 这涉及遍历密码列表(从最常见的开始),并尝试依次打开每个用户名的每个密码。 这种方法有两个好处。 首先,您可以更快地发现具有通用密码的帐户。 其次,您不太可能触发任何帐户锁定防御措施,因为在使用每个单独帐户的连续尝试之间存在时间延迟。
1.3 Verbose Failure Messages(详细的失败消息)
典型的登录表单要求用户输入两条信息-用户名和密码。 某些应用程序还需要其他一些应用程序,例如出生日期,一个难忘的地方或PIN码。
当登录尝试失败时,您当然可以推断出至少一条信息不正确。 但是,如果应用程序告诉您哪些信息无效,则可以利用此行为来大大降低登录机制的有效性。
在最简单的情况下,登录需要用户名和密码,应用程序可能会通过指示失败的原因是无法识别的用户名或错误的密码来响应失败的登录尝试,如图6-3所示。
在这种情况下,您可以使用自动攻击来遍历大量常用用户名,以枚举有效的用户名。 当然,用户名通常不被视为机密(例如,登录期间不会将其屏蔽)。 但是,为攻击者提供一种简单的方法来识别有效的用户名会增加在足够的时间,技能和精力下攻击者破坏应用程序的可能性。 枚举的用户名列表可以用作各种后续攻击的基础,包括密码猜测,对用户数据或会话的攻击或社交工程。
除了主要的登录功能外,身份验证机制的其他组件中可能会出现用户名枚举。 原则上,可以使用提交实际或潜在用户名的任何功能来实现此目的。 通常可以找到用户名枚举的一种位置是用户注册功能。 如果应用程序允许新用户注册并指定他们自己的用户名,则如果应用程序要防止重复的用户名被注册,则几乎不可能阻止用户名枚举。 有时会找到用户名枚举的其他位置是密码更改和忘记密码功能,如本章稍后所述。
NOTE
许多身份验证机制都隐式或显式公开用户名。 在Web邮件帐户中,用户名通常是电子邮件地址,这是设计上的常识。 许多其他站点在应用程序内公开用户名,而没有考虑它授予攻击者的好处,或者以可以预测的方式生成用户名(例如,user1842,user1843等)。
在更复杂的登录机制中,当应用程序要求用户提交几条信息或经历多个阶段时,冗长的故障消息或其他区分符可以使攻击者依次针对登录过程的每个阶段,从而增加了以下可能性: 他将获得未经授权的访问。
NOTE
此漏洞可能会以比此处说明的更微妙的方式出现。 即使响应有效和无效用户名返回的错误消息在表面上是相似的,它们之间也可能存在细微差别,可用于枚举有效用户名。 例如,如果应用程序中的多个代码路径返回“相同”失败消息,则消息的每个实例之间可能存在较小的印刷差异。 在某些情况下,应用程序的响应可能在屏幕上是相同的,但是包含隐藏在HTML源代码中的细微差别,例如注释或布局差别。 如果没有明显的枚举用户名的方法,则应该对应用程序对有效和无效用户名的响应进行仔细比较。
您可以使用Burp Suite中的Comparer工具来自动分析并突出显示两个应用程序响应之间的差异,如图6-4所示。 这可以帮助您快速确定用户名的有效性是否导致应用程序响应中的任何系统差异。
HACK STEPS
- 1.如果您已经知道一个有效的用户名(例如,您控制的帐户),请使用该用户名和错误的密码提交一个登录名,并使用随机用户名提交另一个登录名。
- 2.记录服务器对每次登录尝试的响应的每个细节,包括状态代码,任何重定向,屏幕上显示的信息以及HTML页面源中隐藏的任何差异。 使用拦截代理来维护往返于服务器的所有流量的完整历史记录。
- 3.尝试发现服务器对两次登录尝试的响应中任何明显或细微的差异。
- 4.如果失败,请在可提交用户名的应用程序中的所有位置重复该操作(例如,自注册,更改密码和忘记密码)。
- 5.如果在服务器对有效和无效用户名的响应中检测到差异,请获取常用用户名列表。 使用自定义脚本或自动工具快速提交每个用户名,并过滤表示该用户名有效的响应(请参见第14章)。
- 6.在开始枚举之前,请验证应用程序是否在一定次数的失败登录尝试后执行任何帐户锁定(请参阅上一节)。如果是这样,则考虑到这一事实来设计枚举攻击是可取的。例如,如果应用程序仅授予您使用任何给定帐户的三个失败登录尝试,则冒着“浪费”通过自动枚举发现的每个用户名之一的风险。因此,进行枚举攻击时,请勿在每次登录尝试时提交牵强的密码。而是提交一个通用密码(例如password1)或用户名本身作为密码。如果密码质量规则很弱,那么您在枚举过程中尝试执行的某些登录尝试很有可能会成功,并且一次点击就会同时显示用户名和密码。要将密码字段设置为与用户名相同,可以在Burp Intruder中使用“ battering ram”攻击模式在登录请求中的多个位置插入相同的有效负载。
即使应用程序对包含有效和无效用户名的登录尝试的响应在每个内在方面都是相同的,仍然有可能根据应用程序响应登录请求所花费的时间来枚举用户名。应用程序通常会根据登录请求中是否包含有效的用户名对后端请求执行非常不同的后端处理,例如,提交有效的用户名后,应用程序可能会从后端数据库检索用户详细信息,然后对后端数据库执行各种处理这些详细信息(例如,检查帐户是否已过期),然后在密码错误的情况下返回通用消息之前,先验证密码(可能涉及资源密集型哈希算法)。当仅使用浏览器时,两个响应之间的时间差异可能太微妙而无法检测到,但是自动工具可能能够区分它们。即使此练习的结果包含很大比例的误报,与拥有10,000个用户名(其中约0.5%有效)的列表相比,拥有100个用户名(约占50%有效)的列表还是更好。 。有关如何检测和利用这种类型的时序差异从应用程序中提取信息的详细说明,请参见第15章。
TIP
除了登录功能本身之外,还可以使用其他信息来源来获取有效的用户名。 查看在应用程序映射期间发现的所有源代码注释(请参见第4章),以识别任何明显的用户名。 组织中开发人员或其他人员的任何电子邮件地址都可以是有效的用户名,可以是完整的用户名,也可以是用户特定的前缀。 任何可访问的日志记录功能都可能泄露用户名。
Chapter 6 Attacking Authentication(1) - Authentication Technologies
Chapter 6 Attacking Authentication(2) - Design Flaws in Authentication Mechanisms(2)