คลัง
web

Parameter Discovery

Parameter Discovery คือการหาพารามิเตอร์ที่ซ่อนอยู่ (ไม่ปรากฏใน UI/ลิงก์/form) ซึ่งมักเป็นจุดที่ developer ลืมป้องกัน เช่น debug=true, admin=1, หรือ param ที่นำไปสู่ IDOR/injection/SSRF พารามิเตอร์เหล่านี้ไม่ถูกทดสอบและไม่ถูก validate เพราะไม่มีใครเห็น บทนี้ลงลึกวิธีที่เครื่องมือใช้ตรวจจับ (diff response), เครื่องมือหลัก (arjun, Burp Param Miner, x8, ffuf), การหา param ในทุกตำแหน่ง (query/body/JSON/header/cookie), และการรับมือ false positive/rate limit

Intermediate#parameter#hidden-param#arjun#param-miner#x8#fuzzing#ffuf#web

1. แนวคิด — ทำไม hidden param คือจุดทอง

พารามิเตอร์ที่ไม่โผล่ใน UI มักไม่ถูกทดสอบและไม่ถูกป้องกัน — เป็นจุดทองสำหรับหาช่องโหว่ ตัวอย่างที่เจอบ่อย: debug=1 เปิด verbose error, admin=true ปลดฟีเจอร์, id= ที่ซ่อนนำไป IDOR, url=/next= นำไป SSRF/open-redirect, หรือ param ที่ inject ได้แต่ไม่มีใน form เครื่องมือทำงานโดย ยิง param เดาจาก wordlist แล้วเทียบ response ว่าเปลี่ยนไหม (status/ขนาด/จำนวนคำ/reflection)

ตำแหน่งของ paramตัวอย่างหาอย่างไร
Query string?id=1&debug=1arjun -m GET, ffuf FUZZ=val
POST body (urlencoded)user=a&role=adminarjun -m POST
JSON body{"id":1,"isAdmin":true}arjun -m JSON
HTTP headerX-Forwarded-For, X-Original-URLParam Miner (guess headers)
Cookiedebug=1; role=adminParam Miner, ทดสอบมือ
Cache key / unkeyed inputX-Forwarded-HostParam Miner (cache poisoning)
หลักการ: ยิง param → diff response
baseline size=1200 200 ?debug=x size=4800 (ต่าง!) ?color=x size=1200 (เท่าเดิม) ?id=x reflect debug = param จริง color = ทิ้ง id = param จริง (reflect)
หัวใจคือ diff เทียบ baseline: ยิง param มั่วที่ไม่มีจริงก่อนเพื่อวัดค่ามาตรฐาน (status/size/word/reflection) แล้ว param ไหนทำให้ response ต่างจาก baseline = ตัวจริง

2. เจอ endpoint แล้ว หา param อย่างไร

ลำดับการหา hidden parameter
วัด baseline ของ endpoint
status/size/word ตอนไม่มี param แปลก
endpoint รับ method อะไร?
GETarjun -m GET / ffuf FUZZ=val
POST formarjun -m POST
JSON APIarjun -m JSON
ยิง wordlist param + diff response
arjun/x8 ยิงเป็นชุด (chunk) แล้วเทียบ
หา hidden header/cookie
Burp Param Miner: guess headers/cookies
เจอ param จริงไหม?
เจอทดสอบช่องโหว่ต่อ
ไม่เจอลอง wordlist ใหญ่ขึ้น / method อื่น / ลด chunk
param ทำอะไรได้ → ทดสอบตามชนิด
id/user/fileIDOR / LFI
reflect ใน responseXSS / SSTI / SQLi
url/next/redirectSSRF / open-redirect
debug/admin/testlogic bypass / info leak

3. เครื่องมือและคำสั่ง (ทีละตัว)

arjun — หา hidden parameter (query/POST/JSON)
# GET params (ค่าเริ่มต้น)
arjun -u https://target/endpoint

# POST form / JSON body
arjun -u https://target/api -m POST
arjun -u https://target/api -m JSON

# ใช้ wordlist เอง + ปรับ chunk (จำนวน param ต่อ request) + delay
arjun -u https://target/endpoint -w params.txt -c 250 -d 1 -t 10

# ส่ง header/cookie (ทดสอบ endpoint ที่ต้อง auth) + ผ่าน Burp
arjun -u https://target/endpoint -H "Cookie: session=..." --headers "X-Api: 1"
arjun -u https://target/endpoint --proxy http://127.0.0.1:8080

# ยิงหลาย URL จากไฟล์ แล้ว export
arjun -i urls.txt -oJ arjun.json
arjun ยิง param เป็นชุด (chunk) แล้ว binary-search หาตัวที่ทำให้ response เปลี่ยน — เร็วกว่ายิงทีละตัว
ffuf — หา GET parameter ด้วย diff
# วัด baseline ก่อน (param ที่ไม่มีจริง)
curl -s "https://target/page?nonexistparam_zzz=1" -o /dev/null -w '%{size_download}\n'

# fuzz ชื่อ param — filter ขนาด baseline ออก
ffuf -u "https://target/page?FUZZ=test" \
  -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt \
  -fs <baseline_size> -c

# fuzz ค่าใน param ที่รู้ (หา value ที่ปลดล็อก เช่น id ที่มีจริง)
ffuf -u "https://target/page?id=FUZZ" -w ids.txt -mc 200 -fs <notfound_size>

# POST body param
ffuf -u https://target/api -X POST -d 'FUZZ=test' \
  -H 'Content-Type: application/x-www-form-urlencoded' -w params.txt -fs <baseline>
ffuf ไม่ทำ chunk เอง = ยิงทีละ param ช้ากว่า arjun แต่คุมได้ละเอียด (regex/header/method)
x8 — param discovery แม่นยำ (Rust)
# หา query param
x8 -u "https://target/page" -w params.txt

# หลาย method + body type พร้อมกัน
x8 -u "https://target/api" -X GET POST -w params.txt --body-type json

# ยิงหลาย URL + verbose
x8 -u "https://target/a" "https://target/b" -w params.txt -v 1
x8 ตรวจ reflection + diff ได้ละเอียด จัดการ header/body หลายชนิด เหมาะกับ API สมัยใหม่
  • Burp Param Miner (extension) — 'Guess GET/POST params', 'Guess headers', 'Guess cookies' + ตรวจ unkeyed input สำหรับ cache poisoning
  • wordlist param: Discovery/Web-Content/burp-parameter-names.txt, raft-*-words.txt, และ Assetnote parameters_top_1M.txt
  • ลองทุกตำแหน่ง: query, POST body, JSON, header (X-Forwarded-For/-Host, X-Original-URL, X-Rewrite-URL), cookie
  • ผสมกับ endpoint ที่ได้จาก JS mining (katana/linkfinder) — param มักฝังในโค้ด client อยู่แล้ว

4. CTF & Pentest Walkthrough

  1. 1CTF: หน้าโปรไฟล์ไม่มีอะไร → arjun เจอ param ?debug=1 → เปิด verbose แสดง flag ใน error
  2. 2CTF: API /user คืน profile ตัวเอง → arjun -m JSON เจอ field "admin" → ส่ง {"admin":true} ปลดสิทธิ์
  3. 3Pentest: endpoint /export → ffuf เจอ ?file= (ไม่มีใน UI) → path traversal อ่าน /etc/passwd (ต่อ LFI)
  4. 4Pentest: /fetch → arjun เจอ ?url= → ยิง http://169.254.169.254/ ได้ metadata (SSRF)
  5. 5Pentest: Param Miner guess headers เจอ X-Forwarded-Host สะท้อนใน response + cached → cache poisoning
เจอ param แล้วอย่าหยุด — จัดชนิดแล้วส่งต่อทันที: id/user→IDOR, file/path→LFI, url/next→SSRF/redirect, ค่าที่ reflect→XSS/SSTI/SQLi

5. ข้อผิดพลาดที่พบบ่อย & Troubleshooting

อาการสาเหตุทางแก้
เจอ param ปลอมเต็มไปหมดresponse มี timestamp/token/CSRF สุ่มทุกครั้งarjun --stable, ลด chunk, filter dynamic part
ไม่เจอ param ที่ควรมีchunk ใหญ่จน diff กลบกันลด -c (chunk), ยิงทีละน้อย, เปลี่ยน wordlist
โดน rate limit / 429ยิงเร็วเกินเพิ่ม -d delay, ลด -t threads, ผ่าน proxy pool
method ผิดเลยไม่เจอendpoint รับแค่ POST/JSONลองครบ -m GET/POST/JSON
param จริงแต่ผลไม่ต่างdiff วัดแค่ size — param เปลี่ยน logic เงียบๆทดสอบมือ, ดู reflection/behavior, ลอง value ที่มีความหมาย
WAF บล็อก param บางชื่อชื่อ param ตรง signatureencode, เปลี่ยนตำแหน่ง (body/header), ลดความถี่
false positive จาก response ที่มีค่าสุ่ม (nonce/timestamp) เป็นปัญหาคลาสสิก — ตรวจ baseline ซ้ำ 2-3 ครั้งเพื่อดูว่าขนาด/เนื้อหานิ่งไหมก่อนเชื่อผลลัพธ์

6. Quick Reference

  • hidden param = จุดที่มักลืมป้องกัน → จุดทอง
  • หลักการ: ยิง param + diff เทียบ baseline (status/size/word/reflect)
  • arjun -u URL (เพิ่ม -m POST/-m JSON ตาม endpoint)
  • ffuf -u 'URL?FUZZ=test' -w params -fs baseline
  • x8 = แม่นยำ หลาย method/body; Burp Param Miner = header/cookie/cache
  • wordlist: burp-parameter-names.txt, Assetnote parameters_top_1M
  • ลองครบ: query / body / JSON / header / cookie
  • false positive จาก nonce → ตรวจ baseline ซ้ำ, arjun --stable
  • เจอ param → จัดชนิด: id→IDOR, file→LFI, url→SSRF, reflect→XSS/SSTI/SQLi

🧭 จับมือทำทีละขั้น (มีแค่ Kali) + ถ้าติดไปไหนต่อ

สมมติเจอ endpoint แล้ว (เช่น /api/user หรือ /search) แต่ไม่รู้ว่ามันรับ parameter ซ่อนอะไรบ้าง มีแค่ Kali เปล่าๆ ทำตามนี้ทีละขั้น

  1. 1ติดตั้ง arjun ถ้ายังไม่มี: pipx install arjun (หรือ pip install arjun)
  2. 2วัด baseline ก่อน: curl -s 'https://target/endpoint?nonexistparam_zzz=1' -o /dev/null -w '%{size_download}\n'
  3. 3รัน arjun ตาม method ของ endpoint: arjun -u https://target/endpoint (GET) หรือ arjun -u https://target/api -m JSON
  4. 4ถ้า endpoint ต้อง login ให้ส่ง cookie ไปด้วย: arjun -u https://target/endpoint -H 'Cookie: session=...'
  5. 5ดูผลลัพธ์ arjun ว่าเจอ parameter ไหนที่ทำให้ response เปลี่ยนไปจาก baseline
  6. 6เปิด Burp → ติดตั้ง 'Param Miner' จาก BApp Store แล้วรัน 'Guess headers' และ 'Guess cookies' เพิ่ม (arjun ไม่ครอบคลุมส่วนนี้)
  7. 7ถ้าเจอ param แปลกๆ ให้ทดสอบมือ: ยิงค่าที่มีความหมาย (เช่น debug=true, admin=1) ดูว่า behavior เปลี่ยนไหม
  8. 8ถ้าค่าที่ arjun เจอดูเหมือน false positive (response ต่างเพราะ timestamp/nonce) ให้รันซ้ำ 2-3 ครั้งเพื่อยืนยัน
  9. 9เมื่อเจอ parameter จริง ให้จัดประเภทตามชื่อ/พฤติกรรม แล้วเลือกช่องโหว่ที่ตรงที่สุดไปทดสอบต่อทันที
Decision flow — จับมือทำ Parameter Discovery
วัด baseline (status/size) ด้วย param ที่ไม่มีจริง
รัน arjun ตาม method ของ endpoint (GET/POST/JSON)
arjun เจอ param ที่ทำให้ response ต่างจาก baseline ไหม?
✅ เจอ param จริง→ ยืนยันด้วยการทดสอบมือ
❌ ไม่เจอเลย→ รัน Param Miner หา header/cookie เพิ่ม
Param Miner เจอ header/cookie ที่ unkeyed/สำคัญไหม?
✅ เจอ→ ทดสอบต่อ
❌ ยังไม่เจอเลยหลังลองทั้งคู่→ ลอง wordlist ใหญ่ขึ้น/ลด chunk
ยืนยันซ้ำว่าไม่ใช่ false positive (nonce/timestamp)
✅ ผลนิ่ง ยืนยันเป็น param จริง→ จัดประเภทแล้วทดสอบช่องโหว่
❌ ผลไม่นิ่ง (false positive)→ ตัดทิ้ง กลับไปหา param อื่น
param ทำอะไรได้ → เลือกช่องโหว่ตามชนิด
✅ id/user/file→ IDOR
✅ url/next/redirect→ SSRF
✅ reflect ใน response→ XSS/SQLi
ขั้นตอน/งานเครื่องมือใน Kaliติดตั้งเพิ่ม (ถ้าไม่มี)เครื่องมือออนไลน์
หา hidden parameter อัตโนมัติ (GET/POST/JSON)-pipx install arjun-
หา param แม่นยำ (Rust, หลาย method พร้อมกัน)-cargo install x8 (หรือดาวน์โหลด release)-
หา header/cookie ที่ unkeyedBurp Suite CommunityParam Miner (BApp Store)-
diff response ด้วยมือเร็วๆcurl + wc -c--
fuzz param แบบคุมเองffuf--
encode ค่า param ก่อนยิง--CyberChef
🚑 ถ้าตันสนิท ลองท่าถัดไป: Directory Enumeration — ถ้าหา param บน endpoint นี้ไม่เจอเลย อาจเป็นเพราะยังไม่รู้ endpoint ที่ถูกต้อง ให้กลับไป brute path เพิ่ม; IDOR — ถ้าเจอ param ที่ดูเหมือน object reference (id, uuid); SSRF — ถ้าเจอ param ที่รับ URL/hostname; SQL Injection — ถ้า param ที่เจอ reflect ค่ากลับมาและดูเหมือนต่อ query DB

หัวข้อที่เชื่อมโยง

โน้ตของฉัน

ยังไม่มีโน้ตสำหรับหัวข้อนี้