认证
概念
认证 (Authentication) 被定义为“验证系统实体或系统资源具有某个属性值这一声明的过程”。在信息安全 (information security) 领域,认证是确认实体身份的过程,确保他们是其所声称的身份。另一方面,授权 (authorization) 是“授予系统实体访问系统资源的许可”。
Web 应用程序中最普遍的认证方法是登录表单,用户通过输入用户名和密码来证明自己的身份。
认证可能是使用最广泛的安全措施,也是抵御未经授权的访问 (unauthorized access) 的第一道防线。作为 Web 应用程序渗透测试员,我们的目标是验证认证机制是否已安全地实现。本模块将重点介绍针对登录表单的各种利用方法和技术,以绕过认证并获得未经授权的访问。
方法
信息技术系统可以实现不同的认证方法。通常,它们可以分为以下三大类:
- 基于知识的认证
- 基于所有权的认证
- 基于固有特征的认证
知识
基于知识因素的认证依赖于用户所知道的某些信息来证明其身份。用户提供诸如密码、密码短语 (passphrases)、PIN 码或安全问题答案等信息。
所有权
基于所有权因素的认证依赖于用户拥有的某些物品。用户通过展示对物理对象或设备的所有权来证明其身份,例如 ID 卡、安全令牌 (security token) 或装有认证应用程序 (authentication app) 的智能手机。
固有特征
最后,基于固有特征因素的认证依赖于用户是什么或做什么。这包括生物特征因素 (biometric factors),如指纹、面部模式和语音识别,或签名。生物特征认证非常有效,因为生物特征与单个用户固有地绑定在一起。
| 知识 | 所有权 | 固有特征 |
|---|---|---|
| 密码 | ID 卡 身份证 | 指纹 |
| PIN 码 | 安全令牌 | 面部模式 |
| 安全问题答案 | 认证应用程序 | 语音识别 |
单因素认证与多因素认证
单因素认证 (Single-factor authentication) 仅依赖于单一的认证方法。例如,密码认证仅依赖于对密码的了解。因此,它是一种单因素认证方法。
另一方面,多因素认证 (multi-factor authentication, MFA) 涉及多种认证方法。例如,如果一个 Web 应用程序要求输入密码和基于时间的一次性密码 (time-based one-time password, TOTP),那么它就依赖于对密码的了解和对 TOTP 设备的所有权来进行认证。在需要正好两个因素的情况下,MFA 通常被称为双因素认证 (two-factor authentication, 2FA)。
枚举漏洞
用户的枚举
当 Web 应用程序对认证端点的已注册有效输入与无效输入的响应不同时,就会出现用户枚举漏洞 (User enumeration vulnerabilities)。用户枚举漏洞通常发生在依赖用户名的功能中,例如用户登录、注册和密码重置。
Web 开发人员经常忽视用户枚举的攻击向量,认为用户名等信息并非机密。然而,如果用户名是 Web 应用程序中认证所需的主要标识符 (primary identifier),则可以将其视为机密信息。此外,用户倾向于在各种服务(包括 Web 应用程序以及 FTP、RDP 和 SSH)中使用相同的用户名。由于许多 Web 应用程序允许我们识别用户名,因此我们可以枚举出有效的用户名,并将其用于进一步的认证攻击。这通常是可行的,因为 Web 应用程序通常使用用户名或用户的电子邮件地址作为用户的主要标识符。
用户枚举理论
防范用户名枚举攻击可能会对用户体验产生负面影响。一个能够揭示用户名是否存在的 Web 应用程序可以帮助合法用户识别他们是否输错了用户名。但是,这同样适用于试图确定有效用户名的攻击者。即使是像 WordPress 这样知名且成熟的应用程序,默认也允许用户枚举。例如,如果我们尝试使用无效用户名登录 WordPress,会收到以下错误消息:

另一方面,使用有效用户名则会产生不同的错误消息:

通过错误信息枚举用户
为了获取有效用户列表,攻击者通常需要一个用户名字典来进行测试。用户名通常远没有密码复杂。当它们不是电子邮件地址时,很少包含特殊字符。一个常用用户列表可以让攻击者缩小暴力破解攻击 (brute-force attack) 的范围,或对支持人员或用户进行定向攻击(利用开源情报 (OSINT))。此外,一个常用密码可以轻易地对有效账户进行喷洒攻击 (password spraying),这通常会导致账户成功失陷。
让我们利用返回错误消息的这种差异,并使用 SecLists 的字典 xato-net-10-million-usernames.txt 和 ffuf 来枚举有效用户。我们可以使用 -w 参数指定字典,使用 -d 参数指定 POST 数据,并在用户名中使用关键字 FUZZ 来模糊测试有效的用户。最后,我们可以通过移除包含字符串 Unknown user 的响应来筛选掉无效用户:
ffuf -w /opt/useful/seclists/Usernames/xato-net-10-million-usernames.txt -u http://172.17.0.2/index.php -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "username=FUZZ&password=invalid" -fr "Unknown user"
通过侧信道攻击进行用户枚举
虽然 Web 应用程序响应的差异是枚举有效用户名最简单、最明显的方法,但我们或许也可以通过侧信道 (side channels) 来枚举有效用户名。侧信道攻击 (Side-channel attacks) 并不直接针对 Web 应用程序的响应,而是针对可以从响应中获取或推断出的额外信息。侧信道的一个例子是响应时间 (response timing),即 Web 应用程序的响应到达我们这里所需的时间。假设一个 Web 应用程序只对有效的用户名进行数据库查询。在这种情况下,即使响应相同,我们或许也能够测量出响应时间的差异,并以此方式枚举出有效的用户名