PortSwigger - 业务逻辑漏洞

174

支付漏洞 - 负数

商品数量可以设置为负数,但是总价不能为负数。此时添加另一个商品的适当负数量,以将总价降低到低于您的剩余商店积分。

支付漏洞 - 整数溢出

整数溢出通常是由于对整数数据类型的范围进行不当操作或者超过了其表示范围引起的。下面是一些常见的导致整数溢出的原因:

  1. 超过数据类型的表示范围: 每种整数数据类型都有其表示范围,通常由位数决定。例如,32位有符号整数的表示范围是-2,147,483,648 到 2,147,483,647。如果一个操作导致结果超出这个范围,就会发生整数溢出。

  2. 累积错误: 在长时间的计算中,由于一系列的操作导致整数值逐渐增加或减少,最终可能超过了数据类型的表示范围。即使每次操作都在范围内,但它们的累积可能导致溢出。

  3. 缺乏边界检查: 在编程中,如果没有足够的边界检查或错误处理,用户输入或其他外部数据可能包含超出范围的值,从而导致整数溢出。

  4. 算术操作: 算术操作,如加法、减法、乘法等,可能导致整数溢出。例如,两个很大的正数相乘可能得到一个比数据类型最大值还要大的结果。

下面使用 go 语言代码简单演示整数溢出

int8 取值范围为 -128 ~ 127,如果超出范围,会导致溢出

package main

import "fmt"

func main() {
	var a int8 = 15
	var b int8 = 9
	var c int8 = a * b
	fmt.Printf("%d x %d = %d", a, b, c)
}

15 x 9 = -121

在这个例子中,商品价格无法修改,商品数量可控,但是不能为负数

但是我们可以不断增加商品数量,利用整数溢出,将商品价格变为负数

由于总价不能为负数,所以需要配合其它商品下单

支付漏洞 - 工作流程顺序错误

在该例中,正常的支付逻辑是先将商品添加到购物车,进入购物车下单时检验余额,然后支付成功。

然而我们可以直接越过检验余额这个步骤,将确认订单的包发送到 repeater

将皮夹克添加到购物车,不要进入购物车,直接重放 repeater,购买成功

支付漏洞 - 交替使用优惠券

优惠券正常来说只能使用一次,如果重复添加优惠券会提示优惠券已使用。

但是如果交替使用两个不同的优惠券就可能产生逻辑漏洞

支付漏洞 - 无限金钱逻辑漏洞

该例可通过优惠券购买礼品卡,礼品卡可兑换成余额,购买成功后优惠券可重复使用,这样就导致逻辑漏洞

录制宏,加入购物车 - 填入优惠券 - 检查余额 - 下单 - 兑换礼品卡

然后空爆,线程 1

余额蹭蹭蹭往上涨

对异常输入的处理不一致

该例子中,要想访问管理后台,需要邮箱是 @dontwannacry.com 结尾的账号。

我们的邮箱只能显示 @exploit-0a2400e90483d5a884c9f91701a00051.exploit-server.net 和所有子域

此时我们注册时输入一个超长的邮箱账号

登录账号发现邮箱被截断了

因此我们可以通过此漏洞,控制邮箱后缀,确保 @dontwannacry.com 末尾的 m 恰好是字符 255

1very-long-string-very-long-string-very-long-string-very-long-string-very-long-string-very-long-string-very-long-string-very-long-string-very-long-string-very-long-string-very-long-string-very-long-string-very-long-string-very-long-string@dontwannacry.com.exploit-0a2400e90483d5a884c9f91701a00051.exploit-server.net

通过有缺陷的状态机绕过身份验证

正常登录账号

此时让我们选择权限

如果我们丢弃掉这个包,后端存在逻辑缺陷,导致我们的权限默认为administrator

通过加密 Oracle 绕过身份验证(太骚了)

首先正常登录账号,并勾选 Stay logged in

找一篇文章进行评论,输入错误的电子邮件地址

显示错误的邮箱地址

观察数据包发现,notification 的值解密后就是 Invalid email address: 1.com

随后我们将 stay-logged-in 的值替换到 notification 中,进行解密,结果为:

wiener:1705912187781

此时,我们知道了 stay-logged-in 的格式为用户名: 时间戳

那么我们在邮箱处填入 administrator:1705912187781,进行加密

然后解密利用 /post?postId=2 数据包进行解密,发现存在多余的23个字符(Invalid email address: )

删掉 23 个字节

对处理后的 base64 字符串进行 URL 编码后,解密,提示输入长度必须是 16 的倍数,说明其使用基于块的加密算法。

为什么之前在加密时,输入的长度并非 16 的倍数,还能正常解密呢?

这是因为加密算法自动填充到了 64 位,当我们删除 23 个字节时,base64 字符串变为 41 位,就无法解密了

这时,我们不能直接删除 16 位字节,如果这样的话,解密结果就会是

dress: administrator:1705912187781

因此我们需要删除 32 个字节,为了避免 administrator 被删除,我们需要填充 32 - 23 = 9 个字节

然后删除 32 个字节

此时再来解密,就正常了

随后我们将该值替换到 stay-logged-in,删除 session 值,便可以超管身份登录