1.业务逻辑漏洞介绍
业务逻辑漏洞是应用程序设计和实现中的缺陷,允许攻击者引发意外行为。这可能使攻击者能够操纵合法功能来实现恶意目的。这些缺陷通常是由于未能预测到可能出现的异常应用程序状态,从而无法安全地处理它们。
"业务逻辑",只是定义Web应用程序如何操作的一组规则。有时并不与业务直接相关,因此也被称为"逻辑漏洞"
逻辑漏洞通常不会在Web应用的正常使用中暴露,攻击者会尝试以开发人员从未想过的方式与应用程序交互,从而导致行为上的异常。
业务逻辑的主要目的之一是执行在设计应用程序或功能时定义的规则和约束。一般来说,业务规则规定了当给定场景发生时应用程序应该如何反应。这包括防止用户做一些对业务有负面影响或根本没有意义的事情。
业务逻辑中存在的缺陷允许攻击者绕过这些约束。
考虑某个业务流程:
条件1,数据a
条件2,数据b
达成业务。
攻击者可能会尝试异常数据a、b或在没有经过条件1的情况下,直接尝试条件2或达成业务。
逻辑漏洞通常是与应用程序及其特定功能相关的,识别它们需要对业务有一点的理解。因此,漏洞扫描器很难检测出逻辑漏洞,是手工测试的主要目标。
1.1 业务逻辑漏洞产生的原因
当设计和开发团队对用户将如何与应用程序交互做出了错误或不充分的假设时,攻击者就有可能做出偏离预期的用户行为。
逻辑缺陷在过于复杂的系统中尤其常见,处理大型代码库的开发人员可能并不十分了解应用程序的所有领域是如何工作的。处理一个组件的人可能会对另一个组件的工作方式做出错误的假设,结果无意中引入了严重的逻辑缺陷。
为了避免逻辑缺陷,开发人员需要从整体上理解应用程序。这包括了解如何以意想不到的方式组合不同的功能。
1.2 业务逻辑漏洞的影响
业务逻辑漏洞的影响取决于其与什么功能相关。例如,身份认证机制、交易中的逻辑漏洞往往会带来巨大损失。而其他方面的逻辑漏洞可能影响微不足道,但逻辑缺陷仍然可能允许攻击者以某种方式破坏业务。
2.案例
2.1 对客户端过度信任
对前端传递来的数据不执行完整性检查和服务端验证,过于信任用户输入。例如:
-
用户可以直接修改传递参数(价格等)
需要注意的是,与价格相关的参数,不要直接设置0或负数,最好是一个比较小的数值,这样避免被过滤。
-
或是通过某种明文信息来区分用户身份
2.2 失效的异常输入处理
应用程序逻辑的一个目标是将用户输入限制为符合业务规则的值。例如,允许提交某种数据类型的任意值,然后逻辑从业务角度决定该值是否能接受,如库存管理、预算限制、触发供应链阶段等。
一个很容易想到的是支付阶段,尝试负值,可能导致付款后余额变多。
在进行渗透测试时,应该使用Burpsuite Proxy拦截或Repeater尝试提交异常值。包括异常数值、或是非预期的数据类型。通过观察Web应用的响应,尝试回答以下问题:
- 该功能对数据有什么限制?
- 当输入超限值发生了什么?
- 是否对输入进行了某种转义或归一化?
这能会暴露弱输入验证问题。并且如果目标网站上发现一个表单不能安全地处理非常规输入,那么其他表单很可能也会有同样的问题。
- 例如,我们可以输入数值使其溢出
当我们发现数值可以溢出为负数时,不要局限于一个选项,可以和其它选项拼凑使其整体为一个正数值。
2.又或者,即使数量不溢出,价格也可能溢出
可以使用Burp Intruder 的null paylaods,设置循环次数。并使用单线程,防止再次溢出
- 对于字符串数据,我们可以尝试它是否被截断(先校验是否合法,限制字符上限)
例如,邮箱注册,给一个非法的邮箱域名,但是被截断校验,然而发邮件还是发往恶意邮箱。
这样,如果限制了邮箱域名,我们可以尝试 test<填充>@合法域名@非法域名。
这可以通过BurpSuite Intruder的character blocks实现
2.3 对用户行为做出错误假设
逻辑漏洞最常见的根本原因之一是对用户行为做出错误的假设。这可能会导致开发人员没有考虑到违反这些假设的潜在危险场景的各种问题。
2.3.1 用户永远不可信
Web应用可能很安全,但通过身份认证后,就无限制地信任用户,而没有一致地应用安全措施和业务规则,这可能导致潜在的漏洞。
2.3.2 用户不总是提交全部参数
一个误解是用户总是会为强制输入字段提供值。用户可能尝试缺失一些参数值或添加一些参数值(包括确定存在的隐藏参数或随机测试的不存在参数)。
在同一个服务器端脚本中实现多个函数的情况下,这是一个特别的问题。在这种情况下,特定参数的存在与否可能决定执行哪个代码。删除参数值可能允许攻击者访问应该无法访问的代码路径。
因此,在探测逻辑参数时,应该尝试依次删除每个参数,并分析影响:
- 一次只删除一个参数,以确保到达所有相关的代码路径。
- 依次尝试删除参数名称和参数值,服务器通常会以不同的方式处理这两种情况。
- 遵循多阶段流程直至完成 ,有时在一个步骤中篡改参数会对工作流中的另一个步骤产生影响。
- 意思是修改参数后,完整首先剩余流程;
- 观察篡改某个参数导致的连锁反应
这一规则适用于URL和POST提交的参数 ,但同样不要忘记检查cookie。
在最危险的情况,缺失token也能完成功能(服务器只是传递token并没有严格验证)。
- 例如,我们可以在不输入原密码的情况下,修改新密码:
- 或在没有Cookie的情况下,尝试一些功能,此时服务器可能重新发布cookie
2.3.3 用户并不遵循预期的顺序
许多事务依赖于由一系列步骤组成的预定义工作流。网络界面通常会引导用户完成这个过程,每次他们完成当前的工作,就会进入工作流程的下一个步骤。
然而,攻击者有可能跳过其中的流程。例如,2FA网站要求用户在一个网页登录,然后在另一个网页输入验证码,此时,可以跳过其中一个或两个流程。
即使在相同的工作流或功能中,对事件顺序进行假设也可能导致各种各样的问题。攻击者能够通过重放数据包,以非预期顺序与应用程序交互。
- 打破正常流程顺序(如跳过步骤、重复某一步、回退较早的步骤),例如,跳过某一步、重复使用优惠券、在接受验证码页面回退仍然成功等。
这种类型的测试通常会导致异常,因为预期的变量具有空值或未初始化的值。到达处于部分定义或不一致状态的位置也可能导致应用程序报错。在这种情况下,一定要密切关注遇到的任何错误消息或调试信息。这些信息可能是有价值的信息披露来源。
例如:
- 订单支付的中间确认状态可跳过(基准测试查看流程 ),这属于流程验证不足
- 可以尝试跳过步骤(丢弃身份判断页面的请求包),尝试进入一种可能存在的默认状态
2.4 特定业务领域缺陷
在许多情况下,将遇到特定于业务领域或站点目的的逻辑缺陷。
在寻找逻辑缺陷时,在线商店的折扣功能是一个典型的攻击面,因为折扣的应用方式存在各种基本逻辑缺陷。例如:
- 未校验折扣次数(多次叠加折扣券)
- 在达到阈值后,触发折扣。但是在支付前,去掉不想要的商品,折扣仍然使用。
应该特别留意根据用户操作导致的价格变动或其它敏感值变化 ,尝试去理解应用程序使用什么算法进行调整(变动),在什么时候进行变动。
总之,尽量让应用程序处于开发者意料之外的状态。
为了识别这些漏洞,需要仔细考虑潜在的感兴趣的目标,尝试使用不同的方式实现这一目标。这可能需要一些特定领域的知识,才能明白什么情况下,攻击者会受益 。如果没有业务相关知识,可能会忽略危险行为。我们可能会意识不到潜在的后果。
在这种情况下,应该尽可能多地阅读文档,并在可能的情况下与该领域的主题专家交谈,以获得他们的见解。这听起来好像工作量很大,但是领域越模糊,其他测试人员就越有可能遗漏大量的bug。
2.4.1 案例
连续使用折扣被拒绝,但交替使用通过(只是检测不能和上一个相同)
2.4.2 Burpsuite自动化脚本(宏爆破)
假如我们需要顺序执行一些操作,可以用burpsuite宏完成。
- 顺序执行需要做的操作
Settings -> Sessions -> Add
,打开Session Handling rule editor页面Scope -> URL scope -> 选择Include all URLs
Details -> Rule actions -> Add -> Run a macro -> Select macro -> Add
添加一个宏- 依次选择需要执行的请求,然后点击OK
- 选择相应请求,配置会变化的参数
Configure item -> Add ->Parameter name -> OK
- 配置使用该参数的后续请求:
Configure item ->derived from the prior response
Test macro -> Intruder -> Maximum 1单线程
2.5 加密预言
当应用程序中存在用户可控制的输入,这些输入需要使用相同的算法加密数据,并且用户某种方式得知密文时,这就变得很危险。攻击者可以使用此输入使用正确的算法和非对称密钥加密任意数据。(攻击者根据明文、密文推断加密算法)
同时可以构造有效的加密输入,传递给其它敏感函数(如登录接口)
如果站点上有另一个用户可控的输入提供相反的功能,这个问题可能会更加复杂。(正向加密,反向解密)攻击者将能够解密其他数据以识别预期结构,这减少了他们构造恶意数据所需的工作量,但并非成功利用漏洞的必要条件(可以降低漏洞利用的难度,但是正向加密就足够利用漏洞了)。
2.5.1 案例
- 基准测试 ,登录时,关注响应包(服务器操作) ,返回了两个字符串(Set-Cookie),说明是通过这两个参数鉴别身份
- 发现在评论区存在加密缺陷,当邮箱设置错误时候(测试的时候,他想要输入什么,偏不按照格式来,比较数据包差异)
- 每次发送错误邮箱,会根据邮箱生成一个字符串,并且响应包可解密错误邮箱
- 当某一个接口出现漏洞时,其它接口可能也存在相同的漏洞。尝试解密登录验证参数
成功解密: wiener:1750167044973 ;推断是根据时间戳生成验证码 - 尝试加密administrator(成功加密,但是这是包含invalid email
address : 的 ,因此需要删除。但为了保证服务器能接受删除后的字段,添加9个字符使删除后的字段数为16的倍数。)
URL解密->Base64解密->删除32个字节->Base64加密->URL加密
得到我们想要的字符串- GET / 访问登录页面。删除session(让服务器误以为我们是第一次登录),修改登陆验证为字符串。成功以管理员身份登录。
2.6 邮件地址解析差异
一些网站通过解析电子邮件地址来提取域名,并确定邮箱所有者属于哪个组织。即使对于符合RFC的地址也是很复杂的。
电子邮件地址解析方式的差异会破坏这种逻辑。当应用程序的不同部分处理电子邮件地址的方式不同时,就会出现这些差异。
攻击者可以利用差异,使用编码伪装电子邮件的部分内容。即,让初始验证和服务器具有不同的解析逻辑。
电子邮件地址解析不一致的主要影响是未经授权的访问。攻击者可以在受限的域名中使用看似有效的电子邮件地址注册账户。这使他们能够访问应用程序的敏感区域,如管理面板或受限制的用户功能。
利用电子邮件解析不一致绕过访问控制
2.6.1 案例:利用编码解码不一致,绕过注册限制
前提描述:尝试了分隔符截断,但不成功。
-
(基准测试)确认注册限制,网站只允许内部邮箱注册
-
测试编码差异。
- 尝试
[email protected]
,这是 [email protected],其中abc使用Q编码。Q编码是"encoded-word" standard(标准编码词)的一部分。被拒绝 - 尝试
[email protected]
,同样被拒绝,报错消息相同。 - 尝试
=?utf-7?q?&[email protected]
没有报错,这说明UTF-7编码似乎绕过了服务器的验证。可以利用这个编码,让服务器向我们可控的邮箱发送邮件,同时看起来仍然满足域要求。
- 尝试
-
使用UTF-7利用漏洞
- 使用以下邮箱注册账户
=?utf-7?q?attacker&AEA-[YOUR-EXPLOIT-SERVER_ID]&[email protected].
,去掉中括号,即将[YOUR-EXPLOIT-SERVER_ID]替换为可控邮箱 - 在UTF-7编码中,&AEA表示@,&ACA表示空格,?=表示结束符。因此这段代码表示
attacker@[mail]
,后面内容被空格截断。 - 校验代码认为格式通过(是内部邮箱),但是服务解析时,使用了UTF-7解析。依赖解析差异,使邮件发送到攻击者控制的服务器。
- 使用以下邮箱注册账户
3.业务逻辑漏洞的防范
防范业务逻辑漏洞的关键在于:
- 确保开发人员和测试人员了解应用程序所服务的领域
- 避免对用户行为或应用程序其他部分的行为做出隐式假设
需要明确识别对服务端状态的现有假设,并通过逻辑验证这些假设是否成立。这包括确保所有输入值在后续处理前均符合预期范围。
确保开发人员和测试人员能充分理解这些假设,并清楚应用在不同场景下的预期行为。开发团队应该遵循以下实践:
- 为所有事务和工作流程维护清晰的设计文档和数据流,注意每个阶段做出的任何假设。
- 写出尽可能清晰的代码。生成清晰的文档是至关重要的,以确保其他开发人员和测试人员知道所做的假设以及所期望的行为是什么。
- 注意对使用每个组件的其他代码的引用。考虑这些依赖项的潜在危害。
总结
测试一个功能的时候,如果可以传参,首先尝试常规漏洞,如SQLi、命令注入等。然后可以尝试异常值检测逻辑漏洞,包括但不限于:
-
数值类异常
- 特殊值(负值,0,NaN,1.1)
- 极大值(上溢、下溢),不局限于某个传参,例如数量本身不会溢出,但是会导致价格溢出。(32位有符号整数最大值, 2147483647;32位有符号整数最小值,-2147483648)。64位有符号数,Infinity等。
- 边界值(如99,-1)
- 其他格式数字(1,000;1e10;0xFF等)
- 非数字(abc,123abc)
-
字符串异常值
- 超长字符串(如邮箱过长,可能会截断)
- 特殊字符串(""," ","\t","\n","\r\n"等)
- 常规漏洞测试字符
- SQL:
' " ; -- /* */ # \
- XSS:
< > & " '
- 命令注入:
| & ; < > \ %00 %0A(换行) $() 反引号
- 路径遍历:
../ ..\ %2f %2e ~
- SQL:
- 格式错误字符:(无效的UTF-8序列,unicode表情字符等)
-
数据类型混淆
- 字符串、数值、数组、字典、布尔值、二进制值等
-
结构类异常值
- 缺失字段
- 提供额外字段(如,API测试的隐藏参数提交)
- 异常字段(如与保留字段冲突,含特殊字符的字段值)
-
其它异常传参
- 文件上传
- 超大文件(包括直接上传大文件(bp添加额外字段)、zip压缩炸弹)
- 上传绕过
- 重复文件名
- 文件上传
等待,尽可能以非预期的方式传递参数。
- 对于邮件等要求固定后缀的输入。可以尝试分隔符 ,这里的分隔符不局限于
; # @
等,而是要扩展到其它编码集的分隔符。 - 关注一个数值变化对另一个影响,例如,个数不允许溢出,但是总价可以。
- 尽可能以非预期的方式测试功能。如果网站引导往一个方向前进,那么反方向可能就代表着漏洞。