Cross-Site Request Forgery (CSRF) là một trong những lỗ hổng bảo mật web phổ biến và nguy hiểm nhất hiện nay. Lỗ hổng này cho phép kẻ tấn công gửi các yêu cầu giả mạo từ trình duyệt của nạn nhân đến một trang web mà nạn nhân đã xác thực. CSRF có thể dẫn đến việc thực hiện các hành động không mong muốn trên trang web mục tiêu với quyền hạn của người dùng đã đăng nhập.
CSRF là gì?

CSRF là một loại tấn công mà kẻ tấn công buộc trình duyệt của người dùng thực hiện một hành động không mong muốn trên một ứng dụng web mà người dùng đó đã xác thực. Điều này có thể dẫn đến các hậu quả nghiêm trọng như thay đổi dữ liệu, thực hiện các giao dịch tài chính trái phép, hoặc thậm chí chiếm quyền kiểm soát tài khoản.
Cách thức hoạt động của CSRF
- Người dùng đăng nhập vào một trang web: Người dùng đăng nhập vào một trang web và nhận một cookie xác thực từ trang web đó.
- Người dùng truy cập trang web độc hại: Sau khi đăng nhập, người dùng truy cập một trang web khác do kẻ tấn công kiểm soát.
- Trang web độc hại gửi yêu cầu giả mạo: Trang web độc hại chứa mã JavaScript hoặc HTML có thể gửi yêu cầu HTTP đến trang web đã xác thực sử dụng cookie của người dùng.
- Trang web mục tiêu xử lý yêu cầu: Trang web mục tiêu nhận yêu cầu và xử lý nó như một yêu cầu hợp lệ từ người dùng, dẫn đến các hành động không mong muốn.
Ví dụ về tấn công CSRF
Thực hiện yêu cầu chuyển tiền
Giả sử một trang web ngân hàng cho phép người dùng chuyển tiền bằng cách gửi yêu cầu POST đến /transfer với các tham số amount và account_number. Khi người dùng đã đăng nhập, yêu cầu này sẽ được xử lý dựa trên cookie xác thực của họ.
Một kẻ tấn công có thể tạo một trang web giả mạo với mã sau đây:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CSRF Attack</title>
</head>
<body>
<form action="http://example-bank.com/transfer" method="POST">
<input type="hidden" name="amount" value="1000">
<input type="hidden" name="account_number" value="attacker_account">
<input type="submit" value="Click me!">
</form>
<script>
document.forms[0].submit();
</script>
</body>
</html>
Khi người dùng truy cập trang này, mã JavaScript sẽ tự động gửi yêu cầu POST đến trang web ngân hàng với các tham số được thiết lập bởi kẻ tấn công. Nếu người dùng đã đăng nhập vào trang web ngân hàng, yêu cầu này sẽ được xử lý và số tiền sẽ được chuyển đến tài khoản của kẻ tấn công.
Phương pháp phòng chống CSRF
Sử dụng token CSRF

Một trong những phương pháp phổ biến nhất để ngăn chặn CSRF là sử dụng token CSRF. Đây là các token duy nhất được tạo ra cho mỗi phiên hoặc mỗi yêu cầu và được bao gồm trong các biểu mẫu hoặc URL. Khi trang web nhận được yêu cầu, nó sẽ kiểm tra token để xác định xem yêu cầu có hợp lệ hay không.
Ví dụ, khi người dùng truy cập trang để chuyển tiền, trang web sẽ tạo ra một token CSRF và bao gồm nó trong biểu mẫu:
<form action="/transfer" method="POST">
<input type="hidden" name="csrf_token" value="unique_csrf_token">
<input type="text" name="amount">
<input type="text" name="account_number">
<input type="submit" value="Transfer">
</form>
Khi nhận được yêu cầu POST, trang web sẽ kiểm tra token CSRF:
def transfer(request):
csrf_token = request.POST.get('csrf_token')
if csrf_token != request.session['csrf_token']:
return HttpResponseForbidden("CSRF token is invalid.")
# Process the transfer
Kiểm tra referrer
Một phương pháp khác là kiểm tra header Referrer của yêu cầu để đảm bảo rằng yêu cầu đến từ cùng một trang web. Tuy nhiên, phương pháp này không phải lúc nào cũng đáng tin cậy vì header Referrer có thể bị chặn hoặc thay đổi.
def transfer(request):
if request.META.get('HTTP_REFERER') != 'http://example-bank.com/transfer':
return HttpResponseForbidden("Invalid referrer.")
# Process the transfer
Sử dụng SameSite cookie attribute

SameSite là một thuộc tính của cookie giúp ngăn chặn việc gửi cookie trong các yêu cầu cross-site. Khi thuộc tính này được đặt, trình duyệt sẽ không gửi cookie trong các yêu cầu từ trang web khác, giúp giảm nguy cơ CSRF.
response.set_cookie('sessionid', session_id, samesite='Strict')
Các công cụ và thư viện hỗ trợ phòng chống CSRF
Django

Django, một framework web phổ biến, tích hợp sẵn cơ chế chống CSRF. Khi sử dụng Django, bạn chỉ cần đảm bảo rằng django.middleware.csrf.CsrfViewMiddleware được thêm vào MIDDLEWARE trong settings.py:
MIDDLEWARE = [
...
'django.middleware.csrf.CsrfViewMiddleware',
...
]
Django sẽ tự động thêm token CSRF vào các biểu mẫu và kiểm tra chúng trong các yêu cầu POST.
Spring Security

Spring Security, một thư viện bảo mật cho ứng dụng Java, cũng hỗ trợ chống CSRF. Để kích hoạt CSRF trong Spring Security, bạn chỉ cần cấu hình nó trong tệp cấu hình bảo mật:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
// other configurations
}
}
Thực hành tốt nhất để phòng chống CSRF
- Sử dụng token CSRF: Đảm bảo rằng tất cả các biểu mẫu và yêu cầu trạng thái thay đổi đều bao gồm token CSRF và kiểm tra chúng trên máy chủ.
- Kiểm tra referrer: Sử dụng kiểm tra referrer như một lớp bảo mật bổ sung.
- Cấu hình SameSite cookie attribute: Thiết lập thuộc tính SameSite cho cookie xác thực để giảm nguy cơ tấn công CSRF.
- Giới hạn phương thức HTTP: Sử dụng phương thức HTTP GET cho các yêu cầu chỉ đọc và phương thức POST, PUT, DELETE cho các yêu cầu trạng thái thay đổi.
- Sử dụng các công cụ và thư viện hỗ trợ: Sử dụng các framework và thư viện có tích hợp sẵn cơ chế chống CSRF để giảm thiểu rủi ro và đảm bảo tính bảo mật.
Kết luận
CSRF là một lỗ hổng bảo mật nghiêm trọng có thể dẫn đến những hậu quả nghiêm trọng cho các ứng dụng web. Hiểu rõ cách thức hoạt động của CSRF và áp dụng các biện pháp phòng chống thích hợp là rất quan trọng để bảo vệ ứng dụng khỏi các cuộc tấn công này. Bằng cách sử dụng các token CSRF, kiểm tra referrer, cấu hình SameSite cookie attribute, và tuân thủ các thực hành tốt nhất, bạn có thể giảm thiểu nguy cơ bị tấn công CSRF và bảo vệ thông tin và tài sản của người dùng.


