从业者-非常规输入-低级逻辑缺陷
# 实验室:低级逻辑缺陷
# 题目
此实验室未充分验证用户输入。你可以利用其 采购工作流程中的逻辑缺陷,以意外的价格购买商品。要解决实验室问题,请购买一件 “Lightweight l33t leather jacket” 。
你可以使用以下凭据登录到自己的帐户:wiener
:peter
提示
你将需要使用 Burp Intruder(或 Turbo Intruder)来完成本次实验。
为了确保 价格 以可预测的增量上涨,我们建议将攻击配置为 一次只发送一个请求。在 Burp Intruder 中,你可以在 “Resource pool” 配置项当中通过设置 “Maximum concurrent requests” 参数值来执行此操作。
- name: 实验室-从业者
desc: 低级逻辑缺陷 >>
avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
link: https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-low-level
bgColor: '#001350'
textColor: '#4cc1ff'
2
3
4
5
6
# 实操
根据题意,可得实验目标:
- 该实验室的 采购流程 中存在逻辑缺陷,能够以意外的价格购买商品。
- 利用逻辑缺陷,以意外的价格购买一件名为 “Lightweight l33t leather jacket” 的商品。
点击 “Access the lab” 进入实验室。

在首页中可以看到很多商品,其中有我们需要的 “Lightweight l33t leather jacket” 。
点击 “My account” 转到登录页面。

输入题目中提供的用户名和密码,登录相应账户。

登录之后,可以看到我们的账户中拥有 100 元,可以用于购买商品。

# 购买测试1
回到首页,点击商品下方的 “View details” 进入详情页。

启用浏览器代理,点击页面下方的 “Add to cart” 添加一个商品到购物车。

请求数据包中存在三个参数,其中的 quantity 为商品数量。

尝试在 quantity 参数值的前方添加一个-
,使其变为负数,然后放行数据包。

添加失败,无法添加负数量的商品。

# 购买测试2
正常添加一个商品,然后进入购物车页面。
在购物车页面,启用浏览器代理,然后点击商品的 “+” 符号,尝试增加商品数量。

原来的参数值为 1 个。

尝试将其修改为负数,例如 -10 。

添加失败,商品直接被移除。
由此可知,每当商品数量小于 1 的时候,商品就会被移出购物车。

# 购买测试3 - 成功
既然不能以 超低数量 购买商品,那就试试 超高数量 。
在商品详情页,输入一个极大的商品数量 例如 10000 ,然后尝试添加到购物车。
添加失败,每次最多添加 99 个。

尝试在请求数据包里面添加数量,还是不能超过 99 个。
说明 数量添加限制 是在后端进行校验的。


此时商品数量为 100 个,价格为 133700.00 元,没毛病。

接着,将 添加商品数量 的请求数据包转发到 Intruder 模块。
将 quantity 参数值设置为 99(每次增加99个商品数量),然后随意添加一个选区。

设置攻击载荷:
- 载荷类型:Null payloads(空载荷)
- 次数:500

根据题目中的提示,我们需要设置单线程,以防请求过快遗漏重要信息。
转到 “Resource pool” 选项卡,设置 “Maximum concurrent requests” 的值为 1 。
设置好线程数之后,点击右上角的 “Start attack” 开始攻击。

攻击过程中,总价格持续上涨,看起来没啥问题。

随后,攻击次数接近 200 时,我们再次查看总价格。

查看总价格,发现价格的前面多了一个符号-
,总价格变为了负数?!

经过测试,当商品数量为 16061 时,总价格为 21473557.00 元。

当商品数量为 16062 时,总价格变为 -21474778.96 元。
这是为什么?(学过 C语言 的小伙伴应该能想到)

在 C语言 的数据类型中,有符号的整型,也就是int
类型,存储长度一般为 4 字节,它的取值范围是-2147483648 ~ 2147483647
。
将int
类型的取值范围 与 总价格的数值相对比,不能说很像,简直是一模一样。数值长度是一样的,只不过最后两位数变为了小数。
我在此处编写一个 C语言 程序来作个演示,代码如下:
#include <stdio.h>
void main() {
int x = 2147483647;
int y = 2147483647 + 1;
printf("x: %d\n", x);
printf("y: %d\n", y);
}
2
3
4
5
6
7
8
9

使用 gcc 编译,编译的过程中,直接弹了个警告 “整数溢出” 。
随后运行可执行程序,输出的结果为:
x: 2147483647
y: -2147483648
2
当 x + 1 之后超出int
类型的存储范围,导致整数溢出,使原本的正数变为负数。

而实验室的购物程序 应该也是用了类似的数据类型,从而产生溢出漏洞,总价格的取值范围也许是-21474836.48 ~ 21474836.47
。
回到购物车页面,点击 “Place order” 尝试提交订单。

程序返回错误信息,总价格不能小于 0 。

数值溢出,会在取值范围内徘徊,先溢出为负数,溢出到一定数量之后 又变回正数。
回到 Intruder 模块,继续之前的操作,持续增加商品数量。

当商品数量达到 32124 的时候,总价格变回了正数。
但此时的价格为 115.04 元,我们的购买力不足。

将目标商品的数量减少一个,变为 32123 个。
然后添加其他商品,以填补价格的空缺,使价格保持在 1~100 元之间。
如图,此时总价格为 63.39 元,符合条件,点击 “Place order” 提交订单。

购买成功,实验完成。

# 修复建议
支付漏洞3 - 数值溢出 导致 负价格
- 改为使用 无符号的长数值类型 。
- 增加 “商品库存数量” 校验。购物车中的商品数量,不能超过当前商品的库存数量。
A:不好意思这位顾客,我们只剩下 3 件衣服了。
B:我不管!我就要买 93158436 件!