2009-12-23 25 views
43

Tôi sử dụng back-end PHP của mình để phát hiện yêu cầu AJAX bằng cách kiểm tra giá trị trong $_SERVER['HTTP_X_REQUESTED_WITH'].Phát hiện Ajax bằng PHP và đảm bảo yêu cầu là từ trang web của riêng tôi

Điều này mang lại cho tôi một phát hiện đáng tin cậy, đảm bảo yêu cầu được thực hiện bằng cách sử dụng các kỹ thuật AJAX.

Làm cách nào để đảm bảo yêu cầu đến từ miền của riêng tôi chứ không phải tên miền/rô-bốt bên ngoài?

www.example.com/ajax?true có thể cho phép mọi người thực hiện cuộc gọi AJAX và cắt thông tin.

Tôi có thể tạo phiên cho mọi người vào trang web của tôi bình thường và sau đó cho phép cuộc gọi AJAX .. nhưng điều đó cũng có thể bị giả mạo.

Hiện nó có quan trọng không?

Trả lời

31

Cho phép bạn điều khiển

  • tạo access token cửa hàng
  • trong phiên đối chiếu sau này

Trong Xem bạn

  • khai báo thẻ truy cập như biến JS
  • gửi mã thông báo với mỗi yêu cầu

Quay trở lại điều khiển của bạn

  • Validate HTTP_X_REQUESTED_WITH
  • Validate thẻ

Kiểm tra các bảo mật này guidelines from OpenAjax.
Ngoài ra, hãy đọc bài viết trên codinghorror.com Annie được liên kết.

+3

+1 Vì yêu cầu AJAX dựa trên trình duyệt gửi cookie với mỗi yêu cầu - tất cả những gì bạn cần là thêm kiểm tra mã thông báo trên mỗi trang. – Xeoncross

+7

Điều đó sẽ không ngăn một rô-bốt nhấn trực tiếp vào API. Nó có thể nhận được một mã thông báo truy cập giống như ứng dụng JavaScript của bạn. – Quentin

0

Kiểm tra $_SERVER['HTTP_REFERER']. Điều này sẽ làm việc trong nhiều trường hợp, nhưng không nên nhầm lẫn với một giải pháp hoàn toàn an toàn.

+1

Điều này sẽ cung cấp cho bạn những gì bạn cần, nhưng không đáng tin cậy, vì trình duyệt có thể đặt bất kỳ thứ gì nó thích trong này. Rất dễ giả mạo, vì vậy giá trị không thể thực sự đáng tin cậy. Về cơ bản, bạn không thể đảm bảo rằng yêu cầu đến từ bất kỳ đâu, ngay cả khi bạn phát hành mã thông báo cho trang và yêu cầu ajax của bạn chuyển mã thông báo lại cho bạn. Thực sự, bạn phải tự hỏi mình, có quan trọng không? –

+0

@ Jonathan Sampson - Tôi có thể nắm bắt yêu cầu trong một cái gì đó như BurpSuite và thay đổi HTTP_REFERER ... vì vậy tôi không nghĩ đó là giải pháp. Tôi cũng có thể làm điều đó trong một kịch bản w/curl. –

23

Bạn có thể kiểm tra HTTP_REFERRER, nhưng không phải tất cả trình duyệt đều đặt nó. Cách tốt nhất là viết trình bao bọc cho các cuộc gọi ajax của bạn ở phía JavaScript gửi một phần của document.cookie trở lại máy chủ - chỉ miền của bạn mới có quyền truy cập vào cookie. Bạn có thể so sánh cookie trong tiêu đề yêu cầu với cookie trong lời gọi AJAX bằng php.

Để trả lời, "nó có quan trọng không, những ngày này" - CÓ, nó có! Read this.

+2

Tôi không chắc phương pháp này sẽ thực hiện bất cứ điều gì ngoại trừ bảo mật thông qua sự tối tăm. Nó là tầm thường để tạo ra một yêu cầu web, đó là tất cả một yêu cầu Ajax. Nó chỉ là một chút tầm thường để kiểm tra trình bao bọc Javascript và thêm bất cứ điều gì nó sẽ được thêm vào. Tất cả điều này là mô phỏng một mã thông báo phiên. – zombat

+1

Tôi đoán nó có thể giữ cho rô bốt bay, nếu họ không sử dụng Javascript. Nhưng nó không làm cho yêu cầu * an toàn *, mỗi se. – zombat

+0

Phương pháp này yêu cầu quyền truy cập vào cookie phiên. Nếu rô bốt có quyền truy cập vào cookie phiên, thì có, trang web không an toàn. Nhưng bạn cũng có những vấn đề lớn hơn XSRF! – Annie

3

David Walsh có tốt solution

/* decide what the content should be up here .... */ 
$content = get_content(); //generic function; 

/* AJAX check */ 
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') { 
    /* special ajax here */ 
    die($content); 
} 

/* not ajax, do more.... */ 
+1

Điều đó không liên quan gì đến việc bảo mật yêu cầu. – Xeoncross

+0

Bất cứ ai cũng có thể thêm tiêu đề HTTP vào yêu cầu. –

2

Thực sự, cách an toàn nhất để thực hiện việc này là, như bạn đã đề xuất, sử dụng các phiên phía máy chủ, vì chúng không thể được tạo ra như các cookie có thể.

Được cấp, ai đó vẫn có thể chiếm đoạt ID phiên, nhưng nếu bạn cũng lưu trữ địa chỉ IP của người dùng trong phiên của họ và kiểm tra nó trên mỗi yêu cầu, bạn có thể loại bỏ rất nhiều tin tặc. Chỉ có ai đó trên cùng một mạng LAN hoặc proxy mới có thể chiếm đoạt nó.

Bất kỳ phương pháp nào khác được đề cập - cookie, javascript, http referer - phụ thuộc vào dữ liệu phía máy khách, không an toàn và luôn bị nghi là giả mạo, giả mạo, bị tấn công và xây dựng độc hại.

+0

Đồng ý và một người có thể thay đổi cách tạo phiên để họ sẽ an toàn hơn. – Quamis

6

Về câu hỏi cuối cùng của bạn: "Liệu nó có quan trọng không, trong những ngày này?" Đây là trường hợp theo câu hỏi. Nếu yêu cầu ajax đang làm điều gì đó không yêu cầu bảo mật (ví dụ: tải báo giá cổ phiếu mới nhất) thì điều đó thực sự không quan trọng IMHO. Nếu yêu cầu đang tải thông tin cần được bảo mật (ví dụ: trả lại thông tin nhận dạng hoặc thực hiện điều gì đó trên máy chủ) thì bạn nên xử lý thông tin như vậy.

Cá nhân tôi không sử dụng biến máy chủ để biết khi nào đó là yêu cầu ajax. Thay vào đó, tôi chỉ thêm thông số truy vấn vào cuộc gọi ajax (ví dụ: http://domain.com/?ajax=true). Nếu tôi cần bảo mật cuộc gọi ajax thì tôi sẽ sử dụng các phương thức tương tự như bảo mật yêu cầu trang thông thường (sử dụng cả máy khách và máy chủ). Như Lucas Oman đã chỉ ra, bất cứ điều gì ở phía khách hàng đều có thể bị giả mạo. Điểm mấu chốt không tin tưởng bất kỳ yêu cầu nào ngay cả khi bạn cho rằng nó đến từ trang web hoặc cơ sở dữ liệu của bạn. Luôn luôn làm theo câu thần chú "đầu vào bộ lọc - đầu ra thoát".

+1

Vâng, vâng, vâng. Jim đang nói chuyện. Nghe anh ấy. – Quentin

+0

Đây là câu trả lời hay nhất. Bạn không bao giờ có thể chắc chắn nguồn của một yêu cầu đến trang web của bạn. Ngay cả khi yêu cầu được xác thực, người dùng có thể đang sử dụng bot và thông tin xác thực hợp lệ hoặc thậm chí chỉ cần kéo cookie của họ ra khỏi trình duyệt. – frostymarvelous

1

Sử dụng POST phiên đảm bảo các yêu cầu:

Bên trong trang web (ví dụ index.php) chúng ta cần phải lưu trữ các sessionid

<?php 
// Create Session 
$session = session_id(); 
if(empty($session)) session_start(); 
?> 
<head> 
... 
<script type="text/javascript"> 
    sid = '<?php echo session_id(); ?>'; 
</script> 
<script type="text/javascript" src="ajaxrequest.js"></script> 
... 
</head> 

Các yêu cầu ajax (ajaxrequest.js)

/* simple getAjax function 
* @param $url  request url 
* @param $param  parameter (dont use ?) 
* @param callback function on success 
*/ 
var spinnerid = '#spinner'; // Spinner as long ajax requests running 
$(document).ajaxStart(function() { $(spinnerid).show(); }); 
$(document).ajaxStop(function() { $(spinnerid).hide(); }); 
function getAjax(url, param, callback) { 
    var data = null; 
    url += "?sid=" + sid + "&" + param; 
    $.ajax({ 
     url: url, 
     method: "POST", // uncomment to use GET, POST is secured by session 
     cache: false, 
     async: true, 
     success : function(data){ 
     callback(data); 
    }, 
} 

getAjax('http://domain.com/', 'data=foo', function(data) { 
// do stuf with data 
var jsonobj = eval("(" + data + ")"); 
var data = jsonobj[0][ 'data' ]; 
}); 

Phía php có trách nhiệm:

if(isset($_GET['sid'])) $client_sid = $_GET['sid']; 

if(session_id() == null) session_start(); 

if(session_id() != $client_sid) { 
    // noID or wrongID, redirect to mainindex 
    ignore_user_abort(true); 
    header("HTTP/1.1 403 Forbidden"); 
    header("Connection: close", true); 
    exit; 
} else { 

    // get data 
    if(isset($_GET['data'])) { 
     $data = $_GET['data']; 
    } else if(isset($_POST['data'])) { 
     $data = $_POST['data']; 
    } else { 
     $data = null; 
    } 

    // do stuff with data 

    // return data as json 
    $resp[0]['data'] = $data; 
    print_r(json_encode($resp)); 
} 
+0

Tôi sẽ không sử dụng ID phiên vì lý do bảo mật. Bạn nên tạo một mã thông báo ngẫu nhiên cho mọi yêu cầu, được lưu trong phiên của bạn. Đọc này: https://docs.phalconphp.com/en/latest/reference/security.html#cross-site-request-forgery-csrf-protection – Yossi

+0

Trong khi điều này sẽ làm việc vì ajax đang đăng dữ liệu (không sử dụng get) , bất kỳ ai cũng có thể thấy các giá trị bằng cách chỉ xem javascript. sau đó họ có thể sao chép dữ liệu, tạo biểu mẫu của riêng họ và đăng nó lên cùng một vị trí. Một kiểm tra trên $ _SERVER ['HTTP_REFERER'] sẽ giúp ngăn chặn điều đó, cũng như kiểm tra xem dữ liệu đã được đăng qua ajax nhưng nó vẫn chưa được bảo mật hoàn toàn. Có cách nào tốt hơn? – james

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