# 业务逻辑漏洞示例

业务逻辑漏洞相对而言更具体，取决于其发生的特定环境。然而，尽管逻辑缺陷的个体实例差异很大，但它们可以有许多共同的主题。尤其，它们可以根据最初引入漏洞的初始错误进行松散的分组。

在本节中，我们将查看设计和开发团队所犯的一些典型错误示例，并向你展示它们是如何直接导致业务逻辑缺陷的。无论是在开发自己的应用程序，还是在审计现有的应用程序，你都可以从这些示例中吸取教训，并将同样的批判性思维应用到你遇到的其他应用程序上。

逻辑缺陷的例子包括：

* 过度信任客户端控制
* 无法处理非常规输入
* 对用户行为做出有缺陷的假设
* 特定领域的缺陷
* 提供一个加密预言机

## 过度信任客户端控制

一个根本上有缺陷的假设是，用户只会通过提供的Web界面与应用程序进行交互。这样尤其危险，因为它导致了进一步的假设，即客户端验证将阻止用户提供恶意输入。然而，攻击者只需使用诸如Burp Proxy之类的工具，在数据由浏览器发送但在传入服务器端逻辑之前，对其进行篡改。这就有效地使客户端控制失去作用。

仅从表面上接受数据，而不进行适当的完整性检查和服务器端验证，会让攻击者只需付出相对较小的努力就能造成各种破坏。他们能够实现什么取决于功能和它对可控数据的处理情况。在适当的情况下，这种缺陷能对业务相关的功能和网站本身的安全产生毁灭性的后果。

> **LAB**
>
> [过度信任客户端控制](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-excessive-trust-in-client-side-controls)

> **LAB**
>
> [2FA逻辑存在缺陷](https://portswigger.net/web-security/authentication/multi-factor/lab-2fa-broken-logic)

## 无法处理非常规输入

应用程序逻辑的一个目的是将用户的输入限制为符合业务规则的值。例如，应用程序可能被设计为接受某种数据类型的任意值，但逻辑决定了从业务的角度来看，这个值是否可以接受。许多应用程序在其逻辑中加入了数值限制。可能包括为管理库存、应用预算限制、触发供应链阶段等而设计的限制。

我们以在线商店为例。在订购产品时，用户通常会指定他们想要订购的数量。虽然理论上任何整数都是有效的输入，但业务逻辑可能会阻止用户订购超过现有库存的数量。

要实现这样的规则，开发人员需要预见所有可能的情况，并将处理这些情况的方法纳入到应用程序逻辑中。换句话说，他们需要告诉应用程序是否应该允许一个给定的输入，以及在各种条件下应该如何反应。如果没有明确的逻辑来处理给定的情况，可能会导致意外的和潜在的可利用行为。

例如，一个数值数据类型可能接受负值。根据相关的功能，业务逻辑允许这样做可能没有意义。然而，如果应用程序不进行充分的服务器端验证并拒绝此输入，攻击者可能能够传入一个负值并引发不必要的行为。

考虑在两个银行账户之间转账。这个功能肯定会在完成转账之前检查发送方是否有足够的资金：

```php
$transferAmount = $_POST['amount'];
$currentBalance = $user->getBalance();

if ($transferAmount <= $currentBalance) {
    // Complete the transfer
} else {
    // Block the transfer: insufficient funds
}
```

但是，如果逻辑没有充分防范用户在`amount`参数中提供一个负值，攻击者可能会利用这一点，绕过余额检查，并在“错误”的方向上转账。如果攻击者向受害者的账户发送了-1000美元，可能导致他们从受害者那里收到1000美元。逻辑将始终评估-1000小于当前余额并批准转账。

像这种简单的逻辑缺陷，如果出现在正确的功能中，可能会造成毁灭性的后果。它们在开发和测试期间也很容易被忽视，尤其是考虑到这样的输入可能被Web界面上的客户端控制所阻止。

在审计应用程序时，你应该使用Burp Proxy和Repeater等工具来尝试提交非常规的值。特别是，尝试输入合法用户不太可能输入的范围。包括异常高或异常低的数值输入，以及基于文本字段的异常长的字符串。你甚至可以尝试意想不到的数据类型。通过观察应用程序的反应，你应该尝试回答以下问题：

* 数据是否有任何限制？
* 当你达到这些限制时会发生什么？
* 是否对你的输入进行了任何转换或规范化处理？

这可能会暴露出薄弱的输入验证，允许你能以不寻常的方式操纵应用程序。请记住，如果你在目标网站上找到一个无法安全处理非常规输入的表单，那么其他表单很可能也存在同样的问题。

> **LAB**
>
> [高级逻辑漏洞](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-high-level)

> **LAB**
>
> [低级逻辑缺陷](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-low-level)

> **LAB**
>
> [对特殊输入的处理不一致](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-inconsistent-handling-of-exceptional-input)

## 对用户行为做出有缺陷的假设

逻辑漏洞最常见的根源之一就是对用户行为做出有缺陷的假设。这可能会导致一系列问题，开发人员可能没有考虑到违反这些假设的潜在危险场景。在这一部分中，我们将提供一些应避免的常见假设的警示性例子，并演示它们如何导致危险的逻辑缺陷。

### 可信用户并不总是可信的

应用程序可能因为实现了看似健壮的措施来执行业务规则而显得安全。不幸的是，有些应用程序犯了一个错误的假设，即一旦用户通过了这些严格的控制后，那么他们和他们的数据就可以无限期地被信任。这可能会导致从那时起，相同的控制措施被相对宽松地执行。

如果业务规则和安全措施没有在整个应用程序中得到一致地应用，将会导致潜在的被攻击者利用的危险漏洞。

> **LAB**
>
> [不一致的安全控制](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-inconsistent-security-controls)

### 用户不会总是提供必须的输入

一个误解是，用户总是会为必填输入字段提供值。浏览器可能会阻止普通用户在没有必填输入的情况下提交表单，但是我们知道，攻击者可以在传输过程中篡改参数。甚至可以扩展到完全删除参数。

当多个功能在同一服务器端脚本中实现时，这是一个特殊的问题。在这种情况下，特定参数的存在与否可能决定哪部分代码被执行。删除参数值可能会允许攻击者访问本应无法访问的代码路径。

在探测逻辑缺陷时，你应该尝试轮流删除每一个参数，并观察这对响应有什么影响。你应该确保：

* 每次只删除一个参数，以确保达到所有相关的代码路径。
* 尝试删除参数的名称以及值。服务器通常会以不同的方式处理这两种情况。
* 遵循多阶段流程，直到完成。有时，在一个步骤中篡改参数会影响到工作流程中的另一个步骤。

如上适用于URL和`POST`参数，但也别忘了检查Cookies。这个简单的过程可以揭示一些奇特的应用程序行为，可能是可利用的。

> **LAB**
>
> [双重使用端点的弱隔离](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-weak-isolation-on-dual-use-endpoint)

> **LAB**
>
> [密码重置逻辑存在缺陷](https://portswigger.net/web-security/authentication/other-mechanisms/lab-password-reset-broken-logic)

### 用户不会总是遵循预定的顺序

许多交易都依赖于由一系列步骤组成的预定义工作流程。Web界面通常会引导用户通过这个过程，每次他们完成当前的一步，就带他们到下一步。然而，攻击者不一定会遵循这个预定的顺序。没有考虑到这种可能性，就会导致危险的缺陷，而这些缺陷可能相对容易被利用。

例如，许多实现双因素认证（2FA）的网站要求用户在一个页面上登录，然后在另一个页面上输入验证码。假设用户总是按照这个过程完成，因此不去验证他们是否确实这样做了，这可能会让攻击者完全绕过2FA步骤。

> **LAB**
>
> [2FA简单绕过](https://portswigger.net/web-security/authentication/multi-factor/lab-2fa-simple-bypass)

对事件的顺序进行假设，即使在相同的工作流程或功能中，也会导致各种各样的问题。使用像Burp Proxy和Repeater这样的工具，一旦攻击者看到一个请求，他们就可以随意重放它，并使用强制浏览在任何顺序下与服务器进行任何交互。这使他们能够在应用程序处于非预期的状态时完成不同的操作。

为了识别这种类型的缺陷，你应该使用强制浏览以非预期的顺序提交请求。例如，你可能会跳过某些步骤，多次访问一个步骤，返回到早期的步骤等等。注意观察如何访问不同的步骤。虽然通常你只是向一个特定的URL提交一个`GET`或`POST`请求，但有时你可以通过向同一个URL提交不同的参数集来访问不同的步骤。和所有的逻辑缺陷一样，试着确定开发人员做出了什么假设以及攻击面在哪里。然后你就可以寻找违反这些假设的方法。

注意，这种测试通常会引发异常，因为预期的变量有空值或未初始化的值。在部分定义或不一致的状态下到达一个位置，也有可能导致应用程序产生错误。在这种情况下，一定要密切关注你遇到的任何错误信息或调试信息。这些可能是信息泄露的宝贵来源，可以帮助你微调你的攻击并了解后端行为的关键细节。

> **LAB**
>
> [工作流程验证不足](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-insufficient-workflow-validation)

> **LAB**
>
> [通过有缺陷的状态机绕过认证](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-authentication-bypass-via-flawed-state-machine)

## 特定领域的缺陷

在许多情况下，你会遇到特定于业务领域或网站用途的逻辑缺陷。

在线商店的折扣功能是寻找逻辑缺陷时的一个典型的攻击面。对于攻击者来说，这可能是一个潜在的金矿，各种基本的逻辑缺陷都可能出现在折扣应用的方式中。

例如，考虑一个在线商店，为超过1000美元的订单提供10%的折扣。如果业务逻辑未能检查在应用折扣后订单是否被修改，这可能会遭受到滥用。在这种情况下，攻击者只需将商品添加到他们的购物车，直到他们达到1000美元的门槛，然后在下单前移除他们不想要的商品。即使他们的订单已经不满足预期的条件，他们仍会得到折扣。

当基于用户行为确定的标准来调整价格或其他敏感值时，你应该特别注意这种情况。试图理解应用程序使用什么算法来进行的这些调整，以及在什么时候进行这些调整。通常涉及操纵应用程序，使其处于应用的调整与开发人员原本预期的标准不符的状态。

为了识别这些漏洞，你需要仔细思考攻击者可能有什么目的，并尝试使用提供的功能找到实现这一目的的不同方法。可能需要一定程度的特定领域知识，以了解在特定情况下什么可能是有利的。以一个简单的例子来说，你需要了解社交媒体才能了解强制大量用户关注你的好处。

如果没有这些领域的知识，可能会因为你根本没有意识到其潜在的连锁反应，而忽视危险的行为。同样，你可能很难将这些点联系起来，注意到两个功能如何以有害的方式结合起来。为了简单起见，本专题使用的例子都是特定于所有用户都已经熟悉的领域，即一个在线商店。然而，无论你是在寻找漏洞赏金，渗透测试，甚至只是一个试图写出更安全代码的开发者，在某些时候可能会遇到来自不太熟悉的领域的应用程序。在这种情况下，你应该尽可能多地阅读文档，并在可能的情况下与该领域的专家进行交流，以获取他们的见解。听起来可能很费力，但领域越是晦涩难懂，其他测试人员越是有可能错过大量漏洞。

> **LAB**
>
> [存在缺陷的业务规则执行](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-flawed-enforcement-of-business-rules)

> **LAB**
>
> [无限金钱的逻辑缺陷](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-infinite-money)

## 提供一个加密预言机

当用户可控的输入被加密，然后生成的密文以某种方式提供给用户时，就会出现危险情况。这种输入有时被称为“加密预言机”。攻击者可以利用此输入，使用正确的算法和非对称密钥对任意数据进行加密。

当应用程序中存在其他用户可控的输入，并且这些输入期望使用相同的算法加密数据时，情况就变得危险起来。在这种情况下，攻击者可以使用加密预言机生成有效的加密输入，然后将其传入到其他敏感功能中。

如果网站上还有另一个提供反向功能的用户可控输入，问题可能会变得更加复杂。这将使攻击者能够解密其他数据以确定预期的结构。为他们创建恶意数据节省了一部分工作，但并不一定是成功利用的必要条件。

加密预言机的严重性取决于与预言机使用相同算法的功能。

> **LAB**
>
> [通过加密预言机绕过认证](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-authentication-bypass-via-encryption-oracle)
