CSRF Attack คืออะไร? วิธีป้องกัน Cross-Site Request Forgery อย่างถูกต้อง

CSRF Attack คืออะไร?

CSRF (Cross-Site Request Forgery) คือการโจมตีที่หลอกให้ Browser ของผู้ใช้ส่ง Request อันตรายไปยังเว็บไซต์ที่ผู้ใช้เข้าใจระบบอยู่แล้ว โดยแน่บว่าทำโดยไม่ได้ตั้งใจ เช่น หากผู้ใช้ Login อยู่บนธนาคารออนไลน์ แล้วคลิกลิงค์ภายนอก ลิงค์นั้นอาจเป็นการโอนเงินไปยังบัญชีของผู้โจมตีโดยอัตโนมัติ

ขั้นตอน CSRF Attack ทำงานอย่างไร?

  1. ผู้ใช้ Login เข้าสู่ภายงของ bank.com แล้ว Session Cookie ถูกบันทึกไว้ใน Browser
  2. ผู้อ่านเว็บอีแปบเช่น evil.com ที่มี Form/Link ที่ชีไป bank.com
  3. เมื่อ Browser ส่ง Request ไป bank.com จะแนบ Cookie ของ bank.com ไปด้วยตอนคันหา
  4. bank.com ตรวจสอบ Cookie แล้วดำเนินการตามคำสั่ง เพราะคิดว่าเป็นผู้ใช้จริง

ความแตกต่างภายภาค CSRF และ XSS

คุณสมบัติ CSRF XSS
เป้าหมาย Server-side Action Client-side Browser
ต้องการ เหยื่อเข้าสู่ภายมาแล้ว ในเว็บมีช่องโหว๋
วิธีโจมตี Request Forgery Script Injection
ผลลัพธ์ การกระทำที่ไม่ได้ตั้งใจ ขโมยข้อมูล

วิธีป้องกัน CSRF Attack

1. ใช้ CSRF Token

CSRF Token เป็นค่า Random ที่เซิร์เวอร์สร้างและแนบไปกับ Form เมื่อ Server รับ Form Submit จะตรวจสอบว่า Token ถูกต้องหรือไม่ เนื่องจากเว็บปลอมไม่รู้ค่า Token นี้ จึงส่ง Token ที่ถูกต้องไปไม่ได้:

<!-- HTML Form พร้อม CSRF Token -->
<form method="POST" action="/transfer">
  <input type="hidden" name="csrf_token" value="{{ csrf_token }}">
  <input type="text" name="amount">
  <button type="submit">โอนเงิน</button>
</form>

# ป้องกันใน Laravel
use Illuminate\Support\Facades\Route;
Route::post('/transfer', function() {
    // Laravel ตรวจ CSRF Token อัตโนมัติ
});

2. ตั้งค่า SameSite Cookie Attribute

SameSite Attribute บอก Browser ว่าจะส่ง Cookie ในเงื่องหมองบ้าง:

# SameSite=Strict: ไม่ส่ง Cookie เบือกับ Cross-Site Request
Set-Cookie: session=abc123; SameSite=Strict; HttpOnly; Secure

# SameSite=Lax: ส่งเฉพาะเมื่อ Click Link (GET เท่านั้น)
Set-Cookie: session=abc123; SameSite=Lax; HttpOnly; Secure

# SameSite=None: ส่ง Cookie ทุกกรณี (ต้องใช้คู่กับ Secure)
Set-Cookie: session=abc123; SameSite=None; Secure

3. ตรวจสอบ Origin/Referer Header

เซิร์เวอร์ควรตรวจสอบว่า Request มาจาก Origin ที่เชื่อถือได้หรือไม่ หาก Referer หรือ Origin Header ไม่ตรงกันกับ Domain ของเว็บไซต์ ให้ปฏิเสธ Request นั้น

4. ใช้ Double Submit Cookie Pattern

ส่งค่า CSRF Token ทั้งใน Cookie และใน Request Body เพื่อให้ Server เปรียบเทียบว่าตรงกันหรือไม่ เหมาะสำหรับการเชื่อมต่องแบบ Stateless

5. ใช้ Custom Request Headers

เพิ่ม Header พิเศษ เช่น X-Requested-With: XMLHttpRequest ในคำขอ news API เนื่องจาก Browser จะไม่สามารถส่ง Custom Header พร้อม Cross-Site Request ได้เนื่องจากข้อจำกัด CORS

CSRF Token ใน Framework ยอดนิยม

Framework การป้องกัน CSRF
Laravel (PHP) อัตโนมัติด้วย VerifyCsrfToken Middleware
Django (Python) {% csrf_token %} ใน Template และ CsrfViewMiddleware
Spring (Java) เปิดใช้งานในตัวแล้วใน Spring Security
Rails (Ruby) protect_from_forgery พร้อมใช้แบบ Default
Express.js (Node) ติดตั้ง csurf middleware

สรุป

CSRF เป็นการโจมตีที่อาศัยกับความไว้เชื่อ Browser ที่ส่ง Cookie อัตโนมัติ การป้องกันที่ดีที่สุดคือการใช้ CSRF Token ร่วมกับ SameSite Cookie Attribute ที่เป็น Strict หรือ Lax Framework สมัยใหม่ส่วนใหม่หรือมีการป้องกันในตัวแล้ว แต่ควรเข้าใจหลักการให้เตังกตัดสินเชือมต่อง