> For the complete documentation index, see [llms.txt](https://jtz.gitbook.io/web-security/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jtz.gitbook.io/web-security/web-shen-tou-ce-shi/shen-fen-yan-zheng.md).

# 身份验证

## 介绍

身份验证和会话管理构成了当前 WEB 应用程序的核心组件

* 身份验证： 密码、电子邮件、验证码
* 会话管理： cookie、session

## 原因

* 身份验证机制很薄弱，因为无法充分防止暴力攻击
* 实现中的逻辑缺陷或者编码，允许攻击者完全绕过身份验证机制

## 影响

一旦攻击者绕过身份验证机制进入另一个用户账户，他们就可以访问受感染账户的所有数据和功能，如果攻击者可以获取管理员的账号，就可以完全控制整个应用程序

## 攻击

### 1. 暴力攻击

`攻击者使用自动化工具猜测用户的账户和密码`

在攻击者成功破坏帐户之前，暴力攻击很可能会涉及许多失败的猜测。从逻辑上讲，蛮力保护围绕着尝试使过程自动化并减慢攻击者尝试登录的速度变得尽可能棘手。防止暴力攻击的两种最常见的方法是：

* 如果远程用户登录尝试失败次数过多，则锁定他们尝试访问的帐户
* 如果远程用户连续快速登录尝试次数过多，则阻止他们的 IP 地址

这两种方法都提供不同程度的保护，但都不是无懈可击的，尤其是在使用有缺陷的逻辑实施时。

> 例如，有时您可能会发现，如果您多次登录失败，您的 IP 会被封禁。在某些实现中，如果 IP 所有者成功登录，则失败尝试次数的计数器会重置。`这意味着攻击者只需每隔几次尝试就必须登录到自己的帐户，以防止达到此限制。`

### 2. 用户名枚举

> 观察网站的行为变化，以确定给定的用户名是否有效

* 状态代码： 在暴力攻击期间，对于绝大数的猜测，返回的 HTTP 状态码可以是相同的
* 错误消息： 有时候用户名错误、密码错误返回消息不同
* 响应时间： 如果用户名有效，网站就会检测密码是否正确，这个步骤可能会延长响应时间
* 利用注册功能： 网站会阻止同名用户的注册

### 3. 账户锁定

网站试图防止暴力破解的一种方法是在满足某些可疑条件（通常是一定数量的失败登录尝试）时锁定帐户。与正常的登录错误一样，来自服务器的指示帐户已锁定的响应也可以帮助攻击者枚举用户名。

锁定帐户提供了一定程度的保护，防止对特定帐户进行有针对性的暴力破解。但是，这种方法无法充分防止暴力攻击，在这种攻击中，攻击者只是试图访问他们可以访问的任何随机帐户。

例如，可以使用以下方法来绕过这种保护：

1. 建立可能有效的候选用户名列表。这可以通过用户名枚举或简单地基于常用用户名列表来实现。
2. 确定您认为至少有一个用户可能拥有的一小部分密码。至关重要的是，您选择的密码数量不得超过允许的登录尝试次数。例如，如果您计算出密码尝试次数限制为 3 次，则您最多需要选择 3 次密码猜测。
3. 使用诸如 Burp Intruder 之类的工具，尝试使用每个候选用户名尝试每个选定的密码。这样，您可以在不触发帐户锁定的情况下尝试暴力破解每个帐户。您只需要一个用户使用三个密码之一即可破坏帐户。

### 4. 用户限速

网站试图防止暴力攻击的另一种方法是通过用户速率限制。在这种情况下，短时间内发出过多的登录请求会导致您的 IP 地址被阻止。通常，IP 只能通过以下方式之一解封：

* 经过一定时间后自动
* 由管理员手动
* 成功完成验证码后由用户手动操作

由于该限制基于从用户 IP 地址发送的 HTTP 请求的速率，因此如果您能弄清楚如何通过单个请求猜测多个密码，有时也可以绕过这种防御

### 5. HTTP 基本认证

虽然相当古老，但它相对简单且易于实现，这意味着您有时可能会看到使用 HTTP 基本身份验证。在 HTTP 基本身份验证中，客户端从服务器接收身份验证令牌，该令牌是通过连接用户名和密码并以 Base64 编码构成的。此令牌由浏览器存储和管理，浏览器会自动将其添加到`Authorization`每个后续请求的标头中，如下所示：

```javascript
Authorization: Basic base64(username:password)
```

由于多种原因，这通常不被认为是一种安全的身份验证方法。首先，它涉及在每次请求时重复发送用户的登录凭据。除非该网站还实施 HSTS，否则用户凭据很容易在中间人攻击中被捕获。

### 6. 双因素身份验证令牌

> 验证码通常由用户从某种物理设备上读取。许多高安全性网站现在为此目的为用户提供专用设备，例如您可能用来访问网上银行或工作笔记本电脑的 RSA 令牌或键盘设备。除了专为安全而打造，这些专用设备还具有直接生成验证码的优势。出于同样的原因，网站使用专用的移动应用程序（例如 Google Authenticator）也很常见。
>
> 另一方面，一些网站将验证码以短信的形式发送到用户的手机上。虽然这在技术上仍在验证“你拥有的东西”这一因素，但它很容易被滥用。首先，代码是通过 SMS 传输的，而不是由设备本身生成的。这会造成代码被拦截的可能性。还存在 SIM 交换的风险，攻击者借此以欺诈方式获得带有受害者电话号码的 SIM 卡。然后，攻击者将收到发送给受害者的所有 SMS 消息，包括包含他们的验证码的消息

#### 1. 绕过双因素身份验证

如果先提示用户输入密码，然后在单独的页面提示输入验证码，用户在输入验证码之前实际上处于“已登录”状态。在这种情况下，值得测试一下，看看您是否可以在完成第一个身份验证步骤后直接跳转到“仅登录”页面。有时，您会发现网站在加载页面之前实际上并没有检查您是否完成了第二步。

#### 2. 有缺陷的双因素验证逻辑

有时双因素身份验证的逻辑缺陷意味着在用户完成初始登录步骤后，网站无法充分验证同一用户是否正在完成第二步。

例如，用户在第一步中使用其正常凭据登录，如下所示：

```http
POST /login-steps/first HTTP/1.1
Host: vulnerable-website.com

username=carlos&password=qwerty
```

然后，在进入登录过程的第二步之前，他们会被分配一个与其帐户相关的 cookie：

```http
HTTP/1.1 200 OK
Set-Cookie: account=carlos

GET /login-steps/second HTTP/1.1
Cookie: account=carlos
```

提交验证码时，请求使用此 cookie 来确定用户试图访问哪个帐户：

```http
POST /login-steps/second HTTP/1.1
Host: vulnerable-website.com
Cookie: account=carlos

verification-code=123456
```

在这种情况下，攻击者可以使用自己的凭据登录，然后`account`在提交验证码时将 cookie 的值更改为任意用户名。

```http
POST /login-steps/second HTTP/1.1
Host: vulnerable-website.com
Cookie: account=victim-user

verification-code=123456
```

如果攻击者随后能够暴力破解验证码，这是非常危险的，因为这将允许他们完全根据用户名登录任意用户的帐户。他们甚至不需要知道用户的密码。

#### 3. 暴力破解验证码

与密码一样，网站需要采取措施防止 2FA 验证码被暴力破解。这一点尤其重要，因为代码通常是一个简单的 4 或 6 位数字。如果没有足够的暴力保护，破解这样的代码是微不足道的。

一些网站试图通过在用户输入一定数量的错误验证码时自动将用户注销来防止这种情况发生。这在实践中是无效的，因为高级攻击者甚至可以通过为 Burp Intruder[创建宏](https://portswigger.net/burp/documentation/desktop/settings/sessions#macros)来自动执行此多步骤过程。[Turbo Intruder](https://portswigger.net/bappstore/9abaa233088242e8be252cd4ff534988)扩展也可用于此目的 。

## 防御

* 默认执行强密码策略
* 设置密码错误次数
* 双因素身份验证机制
