2012-04-13 32 views
5

Tôi khá mới đối với bảo mật web. Tôi đã tự hỏi những gì sẽ là cách chính xác để sử dụng thẻ trên yêu cầu ajax và các hình thức mà không cần gửi các nút (tức là cập nhật trạng thái) để bảo vệ CSRF một lần nữa. Ai đó có thể chỉ cho tôi một mẫu mã? Tôi biết làm thế nào để làm điều đó đúng cho các hình thức với một nút gửi. Cũng trong thư mục ajax của tôi, tôi có một htaccess như sau:bảo vệ chống lại CSRF trên các yêu cầu và biểu mẫu ajax mà không cần gửi các nút

SetEnvIfNoCase X-Requested-With XMLHttpRequest ajax 
Order Deny,Allow 
Deny from all 
Allow from env=ajax 

Có phải đó là an ninh đủ cho các yêu cầu ajax, hoặc nên tôi cũng thực hiện an ninh thẻ cho các yêu cầu ajax?

Trả lời

8

Tất cả những gì bạn cần làm là tạo bí mật (mã thông báo) khi trang tải. Đặt nó trên trang và trong phiên. Thông thường tôi đặt nó dưới dạng một trường ẩn nếu có thể, hoặc nếu nó là một phần của trang rất lớn, tôi sẽ đặt nó vào một thuộc tính giá trị trên một phần tử liên quan như div gói toàn bộ trang. Những người khác sẽ thêm một thẻ script với một biến được đặt vào bí mật.

Sau đó, bất cứ khi nào bạn thực hiện cuộc gọi AJAX hoặc gửi biểu mẫu, bạn sẽ bao gồm một trường cho bí mật. (Câu trả lời của Cheekysoft đi vào chi tiết hơn về cách làm điều này với JS thô, nó có thể được thực hiện gần giống với jQuery hoặc bất kỳ khung công tác nào khác mà bạn có thể đang sử dụng.) Kết hợp nó với giá trị phiên ở phía sau để đảm bảo chúng vẫn giống nhau (đến từ cùng một nguồn), và bạn tốt.

Nếu bạn muốn thêm bảo mật, hãy tạo lại bí mật trên mỗi yêu cầu và trả lại bí mật mới cùng với dữ liệu được yêu cầu. Yêu cầu ajax của bạn thay thế trường hoặc thuộc tính giá trị ẩn đó bằng giá trị mới. Điều này không thực sự hoạt động tốt nếu bạn đang thực hiện nhiều yêu cầu hoặc yêu cầu đồng thời. Thực sự, tạo ra mỗi lần toàn bộ trang được tải là đủ nếu bạn đang làm điều này qua HTTPS, mà bạn nên có.

Nếu bạn không thực hiện điều này qua HTTPS, thì thực sự không quan trọng, ai đó đang ngồi trong quán cà phê internet/starbucks chỉ có thể ăn cắp phiên và tải lại trang.

Nếu bạn định làm điều này rất nhiều, bạn nên kiểm tra jQuery và various plugins để giúp bảo vệ CSRF cho bạn. Also, my way isn't the only way.

+1

Cảm ơn đã phản ứng. Nếu tôi gửi tiêu đề yêu cầu theo một trong các liên kết của bạn: 'var csrf_token = ''; $ ("body"). Bind ("ajaxSend", chức năng (elm, xhr, s) { \t nếu (s.type == "POST") { xhr.setRequestHeader ('X-CSRF-Token' , csrf_token); } }); ' Làm cách nào để kiểm tra cạnh ajax? tôi có phải thử lại mã thông báo bằng cách sử dụng yêu cầu đăng không? – Anonymous

+0

@Anonymous nó sẽ phụ thuộc vào ngôn ngữ của bạn lựa chọn. Điều đó trông giống như PHP, vì vậy tôi sẽ kiểm tra một cái gì đó như [getallheaders] (http://php.net/manual/en/function.getallheaders.php) – DampeS8N

+0

Tôi đã tìm ra cách kiểm tra: 'if ($ _ SERVER ['HTTP_X_CSRF_TOKEN'] == $ _SESSION ['ajaxtoken_value']) {' cảm ơn. vấn đề duy nhất là yêu cầu trên http. làm cách nào để thay đổi cài đặt của tôi để yêu cầu được thực hiện qua https? – Anonymous

2

Nếu XHR của bạn là yêu cầu GET, hãy bao gồm mã thông báo làm tham số URL và có tập lệnh PHP đã đọc nó từ $_GET[]. Nếu XHR của bạn là POST, hãy bật mã thông báo vào dữ liệu POST và yêu cầu tập lệnh PHP đọc nó từ $_POST[].

GET yêu cầu

var token = getElementById('myHiddenField').value; 
var xhr = new XMLHttpRequest(); 
xhr.open('GET', 'server.php?token=' + token); 
xhr.send(null); 

POST yêu cầu

var token = getElementById('myHiddenField').value; 
var xhr = new XMLHttpRequest(); 
xhr.open('POST', 'server.php', true); 
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 
xhr.onreadystatechange = function() { 
    if (xhreq.readystate != 4) { return; } 
    // do client side stuff here 
}; 
xhr.send('token=' + token); 
+0

Bạn cũng nên bao gồm một số ghi chú về thời gian và địa điểm tạo mã thông báo. Và làm thế nào để đảm bảo bạn đang kiểm tra chống lại cùng một trên cả hai đầu. – DampeS8N

+0

@ DampeS8N Hãy thoải mái chỉnh sửa điều đó để hoàn thành, nhưng OP đã nói rằng anh ấy cảm thấy thoải mái với các thẻ CSRF trong các bài đăng biểu mẫu. – Cheekysoft

+0

Cảm ơn bạn đã phản hồi. Nếu tôi gửi nó làm tiêu đề yêu cầu: var csrf_token = ''; $ ("body"). bind ("ajaxSend", hàm (elm, xhr, s) {if (s.type == "POST") {xhr.setRequestHeader ('X-CSRF-Mã thông báo', csrf_token);} }); Làm thế nào tôi sẽ kiểm tra về phía ajax? tôi có phải thử lại mã thông báo bằng cách sử dụng yêu cầu đăng không? – Anonymous

Các vấn đề liên quan