บทที่ 9 · Part 2 — Identity & Web Security

Web Security Model

HTTP, origin, Same-Origin Policy, cookie, CORS, browser credentials, trusted proxy headers และ TLS termination ที่กำหนด security boundary ของเว็บ

เว็บหนึ่งอาจตั้ง Access-Control-Allow-Origin: * แล้วเชื่อว่า API เปิดเฉพาะ public data แต่ endpoint เดียวกันใช้ cookie session และ response มีข้อมูลบัญชี หรือ application อาจเชื่อ X-Forwarded-Host จาก Internet แล้วสร้าง recovery link ไปยัง domain ของ attacker

การป้องกัน Web ต้องเริ่มจากความเข้าใจว่า browser แนบ credential เมื่อไร, script อ่านข้อมูล ข้าม origin ได้หรือไม่ และ proxy ใดเป็นผู้กำหนดข้อมูลที่ application เชื่อ

Learning Outcomes

  • อธิบาย HTTP request path, origin และ Same-Origin Policy ได้
  • แยก CORS ออกจาก Authentication/Authorization ได้
  • เข้าใจ cookie credential และเหตุผลที่เกิด CSRF ได้
  • กำหนด trusted proxy chain สำหรับ Host, scheme และ client IP ได้
  • วิเคราะห์ TLS termination และ hop ภายในเป็น trust boundaries แยกกันได้

1 Request ผ่านหลาย Trust Boundaries

TLS จาก browser อาจสิ้นสุดที่ CDN หรือ load balancer ไม่ใช่ application ทุก hop ต้องตอบว่า:

  • endpoint ใด authenticate peer
  • header ใดถูกสร้าง/ล้างโดย proxy
  • plaintext ปรากฏและถูก log ที่ใด
  • route จาก edge ถึง origin ถูกจำกัดอย่างไร
  • application รู้ external scheme/host/client IP จากแหล่งใด

คำว่า “ใช้ HTTPS” จึงต้องระบุ endpoints ไม่ใช่ถือว่าทุกลูกศรได้รับการป้องกันเหมือนกัน

Origin คือ Security Boundary ของ Browser

origin โดยทั่วไปประกอบด้วย tuple:

scheme + host + port
URLเทียบกับ https://app.example.com
https://app.example.com/profilesame origin
http://app.example.comdifferent scheme
https://api.example.comdifferent host
https://app.example.com:8443different port

path ไม่ได้สร้าง origin ใหม่ หน้า /public และ /admin ใน origin เดียวกันจึงแชร์ browser security boundary หลายอย่าง การ host untrusted content ใต้ origin เดียวกับ admin portal เป็น design risk

Same-Origin Policy ทำอะไร

Same-Origin Policy (SOP) จำกัด script จาก origin หนึ่งในการอ่าน/เข้าถึง resource ของอีก origin แต่ไม่ได้ห้าม cross-origin request ทุกชนิด เช่น form, image หรือ navigation ยังส่ง request ได้

ผลสำคัญ:

  • attacker site อาจทำให้ browser ส่ง request พร้อม cookie ได้
  • SOP อาจกัน script attacker อ่าน response
  • server ยังต้องทำ CSRF protection และ authorization
  • endpoint ที่มี side effect ห้ามพึ่ง “อีก site อ่าน response ไม่ได้”

SOP เป็น browser control ไม่ป้องกัน server-to-server client, mobile app, curl หรือ bot

browser เลือก cookie จาก domain/path/secure/samesite rules แล้วแนบไปกับ request application code ไม่ต้องอ่าน cookie ก่อนส่ง นี่เป็นทั้งข้อดีของ HttpOnly session และต้นเหตุ CSRF

POST /transfers HTTP/1.1
Host: app.example.com
Cookie: __Host-session=<opaque>
Origin: https://app.example.com
Content-Type: application/json

server ต้องตรวจ authorization และ CSRF ตาม credential transport SameSite ช่วยลด cross-site sending แต่ไม่ครอบคลุมทุก navigation/integration และไม่แทน anti-CSRF token/origin validation

CORS คือ Permission ให้ Browser อ่าน Response

Cross-Origin Resource Sharing (CORS) เป็น protocol ที่ server ใช้บอก browser ว่า origin ใดอ่าน response และใช้ method/header/credentials ใดได้ ไม่ใช่ firewall หรือ server-side authorization

Simple และ Preflighted Requests

request บางชนิดถูกส่งได้ทันที ส่วน request ที่มี method/header/content type บางแบบจะมี preflight:

OPTIONS /accounts/acc_01 HTTP/1.1
Origin: https://app.example.com
Access-Control-Request-Method: PATCH
Access-Control-Request-Headers: authorization, content-type

response ที่อนุญาตแบบเจาะจง:

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: PATCH
Access-Control-Allow-Headers: authorization, content-type
Access-Control-Allow-Credentials: true
Vary: Origin

preflight ไม่ใช่ authorization attacker ที่ไม่ใช่ browser เรียก PATCH ตรงได้เสมอ

CORS Failure ที่พบบ่อย

  • reflect Origin ใดก็ได้กลับไปพร้อม credentials
  • allow suffix แบบ endsWith("example.com") จน evil-example.com ผ่าน
  • เชื่อ null origin โดยไม่เข้าใจ sandbox/file context
  • allow origin ที่ถูก third party takeover
  • ลืม Vary: Origin เมื่อ cache response แตกต่างตาม origin
  • เปิด method/header กว้างและคิดว่า CORS จำกัด API client ทุกชนิด

ใช้ exact allowlist ที่มี owner/lifecycle และแยก public unauthenticated API ออกจาก credentialed API

CORS ไม่ให้สิทธิ์ Business Resource

แม้ origin ถูก allow และ token valid endpoint ยังต้องตรวจ subject-action-resource ตาม Authorization

แยก Site จาก Origin

cookie SameSite ใช้แนวคิด site ซึ่งอิง registrable domain + scheme ไม่เหมือน origin ทุกกรณี subdomain ต่างกันอาจ cross-origin แต่ same-site ได้ ดังนั้น XSS/subdomain takeover แห่งหนึ่งอาจ มีผลต่อ cookie/CSRF assumption ของอีก subdomain

อย่าวาง user-generated site, legacy app และ privileged portal ใต้ parent domain เดียวโดยไม่ วิเคราะห์ cookie domain, CORS, CSP และ takeover lifecycle

อย่าเชื่อ Proxy Headers จาก Client

header เหล่านี้เชื่อได้เฉพาะเมื่อ request มาจาก proxy ที่กำหนดและ proxy ล้างค่าจาก client ก่อน:

  • Forwarded, X-Forwarded-For
  • X-Forwarded-Proto
  • X-Forwarded-Host
  • vendor-specific client IP / TLS identity headers

application ต้องกำหนด trusted proxy hops ไม่ใช้ค่าซ้าย/ขวาสุดแบบเดาสุ่ม

Host Header Injection

ถ้า recovery link สร้างจาก Host ที่ client ควบคุม:

POST /forgot-password HTTP/1.1
Host: attacker.example

email อาจมี link ไปยัง attacker domain พร้อม recovery token ใช้ canonical external base URL จาก trusted configuration และ allowlist host ที่ edge/application แทนการประกอบ security link จาก request header โดยตรง

HTTPS ต้อง Validate Identity

TLS ให้ confidentiality/integrity ของ channel และ server authentication เมื่อ client ตรวจ certificate chain, validity และ hostname ถูกต้อง การปิด verification ทำให้ encryption ไม่มี peer authenticity และเปิด MITM

เพิ่มเติมสำหรับเว็บ:

  • redirect HTTP → HTTPS แต่ sensitive cookie ต้องไม่ถูกส่งผ่าน HTTP ตั้งแต่แรก
  • ใช้ HSTS หลังประเมิน subdomain/rollout/recovery
  • หลีกเลี่ยง mixed content ที่ HTTPS page โหลด active HTTP resource
  • cookie ใช้ Secure
  • origin server จำกัดให้รับจาก edge ที่กำหนด ไม่เปิด bypass path โดยไม่ตั้งใจ

TLS ไม่ป้องกัน XSS, CSRF, broken authorization หรือ plaintext ที่ log หลัง termination

Cache และ Response Boundary

response ที่มีข้อมูลเฉพาะ user ต้องตั้ง cache policy ให้ตรง architecture Shared CDN/proxy cache อาจรั่วข้อมูลข้าม session ถ้า cache key ไม่รวม authorization context หรือ origin

ระวัง:

  • cache authenticated response โดย path อย่างเดียว
  • response ขาด Cache-Control ที่เหมาะสม
  • Vary ไม่ตรง header ที่เปลี่ยน content
  • error/debug response ถูก cache
  • signed URL ถูกเก็บใน analytics/referrer

อย่าแก้ด้วย no-store ทุก response โดยไม่พิจารณา performance แต่กำหนด data class และ cache owner

Browser Security Headers เป็น Defense in Depth

header สำคัญจะลงรายละเอียดในบท Browser Security แต่ mental model คือ:

Header/PolicyBoundary ที่ช่วย
Content-Security-Policyจำกัด source/execution และ framing ตาม directive
frame-ancestorsจำกัดการ embed/clickjacking
X-Content-Type-Optionsลด MIME sniffing
Referrer-Policyจำกัดข้อมูล URL ที่ส่งออก
Permissions-Policyจำกัด browser capabilities
HSTSบังคับ HTTPS สำหรับ host หลัง browser รับ policy

header ไม่แทน safe rendering, authorization หรือ secure architecture และค่าที่กว้างเกินอาจไม่มีผลจริง

Review Checklist

  • ระบุ origin/site ของ frontend, API, admin และ untrusted content
  • ทุก TLS termination/hop มี peer, header และ logging boundary ชัด
  • cookie domain/path/secure/samesite จำกัดตาม architecture
  • CSRF ไม่พึ่ง SOP หรือ SameSite เพียงชั้นเดียว
  • CORS ใช้ exact origin allowlist และไม่ถูกใช้แทน authorization
  • credentialed response มี Vary: Origin/cache policy ที่ถูกต้อง
  • proxy ล้าง forwarded headers และ application กำหนด trusted hops
  • security link ใช้ canonical configured origin ไม่เชื่อ Host header
  • origin bypass และ mixed-content path ถูกปิด
  • authenticated/sensitive response ไม่รั่วผ่าน shared cache

สรุป

Web security เกิดจาก boundary หลายชั้น: browser origin/site, cookie, CORS, TLS endpoint, reverse proxy และ application authorization SOP จำกัดการอ่านข้าม origin แต่ไม่หยุด request และ CORS เป็น browser read permission ไม่ใช่ access control ของ API

Further Reading