Cross-Site Request Forgery (CSRF)
- Về cơ bản, CSRF lừa trình duyệt của người dùng gửi một yêu cầu giả mạo đến một trang web đáng tin cậy, cùng với thông tin đăng nhập phiên hiện tại của người dùng (ví dụ: cookie phiên). Nếu người dùng có phiên hoạt động trên trang web đó, máy chủ sẽ chấp nhận yêu cầu giả mạo là hợp lệ và thực hiện hành động. Kẻ tấn công có thể thực hiện các hành động quan trọng trong phạm vi quyền của nạn nhân, chẳng hạn như thay đổi mật khẩu, cập nhật địa chỉ email, chuyển tiền hoặc mua sản phẩm.
- CSRF hoạt động như thế nào?
- Để một cuộc tấn công CSRF thành công, ba điều kiện chính phải được đáp ứng:
- Hành động liên quan: Phải có một hành động trong ứng dụng mà kẻ tấn công muốn thực hiện (ví dụ: thay đổi mật khẩu của nạn nhân). Hành động này chỉ được bảo vệ bằng cookie phiên, không có cơ chế nào khác (như mã thông báo CSRF) để xác minh tính xác thực của yêu cầu.
- Phiên: Nạn nhân phải có phiên hoạt động trong ứng dụng mục tiêu.
- Mồi nhử: Kẻ tấn công phải lừa trình duyệt của nạn nhân gửi một yêu cầu giả mạo đến máy chủ mục tiêu.
- Ví dụ
- Nạn nhân đăng nhập vào ứng dụng ngân hàng của họ tại
https://techcom-bank.com. Trình duyệt của họ đã có va lưu trữ cookie phiên cho trang web này. - Kẻ tấn công tạo một yêu cầu chuyển tiền giả mạo, chẳng hạn như một URL như
https://techcom-bank.com/transfer?to=attacker&amount=1000. - Kẻ tấn công nhúng một cơ chế để kích hoạt yêu cầu này trên trang web mà chúng kiểm soát (
https://attacker-site.com). Đây có thể là một thẻ <img> ẩn, một liên kết hoặc một biểu mẫu tự động gửi. - Mã HTML trên
attacker-site.com
<img src="https://techcom-bank.com/transfer?to=attacker&amount=1000" width="0" height="0" border="0">
- Nạn nhân truy cập
https://attacker-site.comtrong khi phiên giao dịch ngân hàng của họ vẫn đang hoạt động. - Trình duyệt của nạn nhân tự động gửi yêu cầu GET đến URL trong thuộc tính src của thẻ <img>. Trình duyệt tự động bao gồm cookie phiên của techcom-bank.com trong yêu cầu này.
- Máy chủ techcom-bank.com nhận được yêu cầu với cookie phiên hợp lệ, coi đó là hợp lệ và chuyển 1000 đơn vị tiền tệ vào tài khoản của kẻ tấn công. Nạn nhân không hề biết về giao dịch này.
Đây chỉ là 1 ví dụ cụ thể cho bạn hiểu , các nền tảng ngân hàng hiện nay đều thường dung thêm 1 token do sever sinh ra để làm xác thực rằng request này được giử đi từ trang hợp lệ ,không phải csrf nên không thể thành công đâu 😘🕵️
- CSRF token = một giá trị ngẫu nhiên, khó đoán, do server sinh và dùng như “bằng chứng” rằng yêu cầu thay đổi trạng thái thực sự xuất phát từ trang/phiên hợp lệ. Attacker có thể khiến trình duyệt gửi request, nhưng không thể biết token đó (vì SOP), nên không thể làm request hợp lệ — server sẽ từ chối.
1) Token là gì & vì sao cần
Là gì: chuỗi ngẫu nhiên (CSPRNG) như a1b2c3... gắn với session hoặc per-request.
Mục đích: cung cấp yếu tố thứ hai bên cạnh cookie. Cookie cho biết “người dùng có phiên”, token cho biết “request này bắt nguồn từ UI/JS của site, không phải site khác”.
Vì sao hiệu quả: attacker có thể ép browser gửi cookie, nhưng không thể đọc token nằm trong DOM/response của target (SOP), nên không thể gắn token hợp lệ vào request giả mạo.
2) Sinh token — an toàn như nào
Cách sinh chuẩn: dùng CSPRNG, độ entropy đủ (>=128 bit).
- PHP:
bin2hex(random_bytes(32)) - Node:
crypto.randomBytes(32).toString('hex')
Không dùng: mt_rand, uniqid, hoặc values dự đoán (userId + timestamp đơn giản).
3) Lưu token — lựa chọn
-
Synchronizer token (khuyến nghị): lưu token trong
$_SESSIONhoặc session store (Redis). So sánh token request vs token lưu.- Per-session (1 token/phiên) — dễ nhất.
- Per-request / single-use — an toàn hơn chống replay, phức tạp hơn (phải xoá token sau dùng).
-
Double-submit cookie (stateless): server set cookie
XSRF-TOKENreadable JS; client đọc cookie và gửi lại trong headerX-XSRF-TOKEN. Server so sánh cookie vs header. (Không cần lưu server-side, nhưng token phải readable → rủi ro XSS.)
4) Truyền token xuống client — cách thực hiện
- Form HTML truyền thống: chèn
<input type="hidden" name="csrf_token" value="...">. - SPA/AJAX: chèn vào
<meta name="csrf-token" content="...">hoặc trả JSON khi render, rồi client thêm headerX-CSRF-Tokencho mọi AJAX. - Không đặt token trong URL (query string) — dễ leak qua logs/Referer.
5) Trình duyệt có tự gửi token không?
- Không, trừ khi token là cookie — và cookie thì trình duyệt tự gửi trong header
Cookie:theo rules domain/path/SameSite. - Nếu token ở DOM (hidden input/meta) thì chỉ khi trang hiện tại submit form hoặc JS đọc và thêm token thì token mới được gửi. Attacker-page không có token đó trong DOM → không thể gửi token.
- Nếu token là cookie (double-submit), trình duyệt tự gửi cookie, nhưng server vẫn cần client gửi token ở header/body để so sánh (tránh chỉ dựa vào cookie).
6) Server validate token — phải làm gì
- Lấy token từ request:
POST bodyhoặcX-CSRF-Tokenheader. - Lấy token từ store (session/redis) hoặc cookie (double-submit).
- So sánh bằng
constant-time compare(hash_equalsPHP,crypto.timingSafeEqualNode). - Nếu khớp → xử lý; nếu không → trả
403và log. - Với single-use token: xoá token sau dùng.
7) Các biến thể thực tế
- Synchronizer token (server-side store) — an toàn, phổ biến.
- Double-submit cookie — stateless, tiện SPA, nhưng token phải readable JS so XSS dễ leak.
- JWT as CSRF token — có thể sign token, verify signature server-side; tương tự synchronizer nhưng stateless; vẫn phải cẩn thận với XSS/leak.
8) Khi token bị phá — các bypass & nguyên nhân
Token sẽ bị vô hiệu nếu tồn tại lỗi khác:
- XSS trên target: attacker chạy script trong origin target → đọc token từ DOM → gửi request hợp lệ. Vì vậy fix XSS trước.
- CORS cấu hình sai: nếu server cho phép attacker origin đọc responses and credentials, attacker có thể AJAX lấy token.
- Token leak (URL, logs, Referer): nếu token nằm trong query string hoặc được leak, attacker có thể lấy.
- Token predictable: attacker dò đoán token nếu RNG yếu.
Quá trình sinh và gửi CSRF_Key từ sever sang client
1. Server sinh token (khi nào)
Khi user mở trang chứa form hoặc đăng nhập → server gọi CSPRNG để sinh token.
Ví dụ: ngay khi session được tạo, hoặc mỗi khi render trang form (tùy bạn muốn per-session hay per-request).
2. Server lưu token ở đâu
- Per-session (thường dùng): lưu
$_SESSION['csrf_token'](PHP) hoặcreq.session.csrfToken(Express). Đây là kiểu phổ biến. - Per-request / single-use: lưu vào session như một danh sách token hợp lệ hoặc push vào Redis với TTL; xoá token khi dùng.
- Stateless double-submit: server không lưu; server set cookie
XSRF-TOKEN=…cho client; client phải echo lại giá trị cookie này trong header. Server so sánh cookie vs header.
3. Server gửi token xuống client (cách truyền)
-
HTML form: chèn ví dụ:
<input type="hidden" name="csrf_token" value="TOKEN">Khi user submit form từ trang đó, browser gửi token trong body.
-
SPA / AJAX: chèn ví dụ:
<meta name="csrf-token" content="TOKEN">hoặc trả token trong response JSON; client JS đọc và thêm header
X-CSRF-Tokenvào mọi request. -
Double-submit cookie: server trả header ví dụ:
Set-Cookie: XSRF-TOKEN=TOKEN; Path=/; Secure; SameSite=LaxClient JS đọc
document.cookieđể lấy token và gắn header.
⚠️ Lưu ý: không đặt token trong URL (query string) — dễ bị leak qua logs hoặc Referer header.
4. Client gửi token cùng request
-
Nếu form submit → token được gửi tự động trong body.
-
Nếu AJAX → client code thêm header ví dụ:
'X-CSRF-Token': token -
Nếu double-submit → browser tự gửi cookie, và JS phải gửi header hoặc body copy token để server so sánh.
5. Server xác thực token (verify)
- Server lấy token từ request (body param hoặc header).
- Server lấy token đã lưu (session store) hoặc cookie (double-submit).
- So sánh bằng constant-time compare (ví dụ
hash_equalstrong PHP,crypto.timingSafeEqualtrong Node) để tránh timing attacks. - Nếu khớp → xử lý request; nếu không → trả
403 Forbiddenvà ghi log.
6. Sau khi verify
- Nếu dùng single-use token: xoá token khỏi store để ngăn replay attack.
- Nếu per-session: có thể rotate token sau login hoặc định kỳ để tăng an toàn.
Tool
Những công cụ này hỗ trợ phát hiện khả năng tồn tại CSRF và các lỗ hổng bảo mật web khác bằng cách quét ứng dụng web.
| Công cụ | Mô tả | Giấy phép | Địa chỉ |
|---|---|---|---|
| Burp Suite | Công cụ tiêu chuẩn ngành cho kiểm thử bảo mật web: proxy, scanner, các công cụ pentest. Phiên bản Professional có scanner tự động phát hiện CSRF và tính năng sinh PoC CSRF. | Thương mại / Có bản miễn phí | Link |
| OWASP ZAP | Trình quét bảo mật web mã nguồn mở phổ biến. Cung cấp quét tự động và công cụ kiểm thử thủ công, có thể phát hiện CSRF. | Mã nguồn mở | Link |
| XSRF-Scanner | Công cụ Python chuyên để tìm lỗ hổng CSRF. | Mã nguồn mở (MIT) | Link |
| Acunetix | Máy quét lỗ hổng web toàn diện. Phát hiện nhiều loại lỗ hổng, bao gồm CSRF, với độ chính xác cao. | Thương mại | Link |
Công cụ tự động sinh PoC (Proof-of-Concept) . Những công cụ/website này giúp nhanh chóng tạo mã HTML PoC cho tấn công CSRF từ một HTTP request đã bắt được — tiện để demo khả năng khai thác.
| Tài nguyên | Mô tả | Địa chỉ |
|---|---|---|
| security.love CSRF PoC | Trình sinh PoC nhanh, hỗ trợ nhiều phương thức và kiểu mã hóa. | security.love/CSRF-PoC-Genorator |
| Hacktify CSRF PoC Generator | Tạo ngay mã PoC HTML bằng cách dán request HTTP. | hacktify.in/csrf |
| Nakano Security CSRF PoC | Công cụ trực tuyến khác để nhanh chóng sinh form PoC. | tools.nakanosec.com/csrf |
Danh sách payload và tham khảo . Những nguồn này cung cấp ý tưởng payload và thông tin kỹ thuật cho CSRF và các lỗ hổng web khác.
| Tài nguyên | Mô tả |
|---|---|
| PayloadAllTheThings | Một trong những kho payload toàn diện dành cho pentester — chứa danh sách payload và kỹ thuật khai thác cho nhiều loại lỗ hổng, bao gồm CSRF. (Trên GitHub) |
| OWASP CSRF Cheatsheet | Tài liệu tham khảo của OWASP trình bày các phương pháp phòng chống CSRF chi tiết. |