2012-05-10 17 views
6

Có cách nào để đảm bảo dữ liệu $_POST mã của tôi nhận được đến từ biểu mẫu của tôi chứ không phải ảnh hưởng bên ngoài. Về cơ bản, tôi không muốn ai đó có thể giả mạo một $_POST đến một trang phổ biến có sẵn như tạo tài khoản. Trang tạo tài khoản có thể truy cập được bởi bất kỳ người dùng nào, nhưng tôi muốn đảm bảo chỉ dữ liệu được gửi bởi biểu mẫu account_creation của tôi là những gì được xử lý.

Điều duy nhất tôi có thể nghĩ đến là bắt đầu một $_SESSION và sau đó cung cấp session_id cho biểu mẫu bằng cách sử dụng thông tin nhập ẩn. Khi $ _POST giá trị của đầu vào bị ẩn sau đó sẽ được đối sánh với session_id hiện tại.

Nếu có phương pháp nào tốt hơn để đạt được kết quả này? Nếu có tôi mong muốn được nghe nó.

Trả lời

7

Bạn không thể đảm bảo rằng dữ liệu đến từ một hình thức . Yêu cầu POST chỉ là yêu cầu POST, nó có thể được tạo theo bất kỳ cách nào. Biểu mẫu HTML chỉ là một những cách rất thân thiện với người dùng. Máy chủ của bạn cần xác thực xem liệu dữ liệu nhận được qua yêu cầu POST có hợp lệ hay không và có nên hành động hay không.

Có nói rằng, có những thứ có thể giúp bạn hạn chế và xác thực dữ liệu đang được gửi. Trước hết, yêu cầu người dùng phải đăng nhập bằng cookie (phiên). Điều đó giúp loại bỏ các yêu cầu ngẫu nhiên của người dùng ẩn danh. Thứ hai, bạn có thể nhúng mã thông báo dưới dạng trường ẩn vào biểu mẫu mà bạn cũng lưu vào phiên của người dùng. Yêu cầu POST cần chứa mã thông báo đó để hợp lệ. Mã thông báo chỉ đơn giản là một chuỗi giả ngẫu nhiên.
Bạn có thể cải thiện điều này bằng cách chuẩn bị băm của các trường biểu mẫu mà bạn mong đợi người dùng gửi. Nếu giá trị biểu mẫu phải là chỉ đọc, bạn có thể đưa giá trị vào giá trị băm. Ví dụ.:

$rand = md5(mt_rand()); 
$hash = sha1('lastname:firstname:email:' . $rand); 

$_SESSION['rand'] = $rand; 
$_SESSION['hash'] = $hash; 

// on form submit: 

$keys = array_keys($_POST); 
$checkHash = sha1(join(':', $keys) . ':' . $_SESSION['rand']); 
if ($checkHash != $_SESSION['hash']) { 
    die('Form submission failed token validation'); 
} 

Đó chỉ là một ví dụ nhanh, có thể bạn sẽ muốn sắp xếp các phím theo thứ tự abc để đảm bảo bạn sẽ nhận được cùng bảng băm vv Nó minh chứng cho khái niệm của người sử dụng cần phải có một thẻ duy nhất cho mỗi yêu cầu mặc dù ngăn cản ủ với các biểu mẫu và gửi nhiều hoặc ít dữ liệu hơn mong muốn.

Điều này vẫn không có nghĩa là người dùng thực sự đã sử dụng biểu mẫu của bạn để gửi dữ liệu.

1

Tốt hơn một chút là thêm xác thực bổ sung như user_agent, user_ip và một số $ _SERVER vars khác - đó là hai tôi sử dụng.

Vì vậy, hãy tạo ID duy nhất (hoặc ID phiên) như bạn mô tả, nhưng thêm xác nhận thêm một chút mà tác nhân và ip cũng khớp. Không đánh lừa bằng chứng, nhưng thêm một lớp bảo mật nhỏ.

Chỉnh sửa: Tôi nên thêm rằng bạn không gửi lại tác nhân người dùng; giữ cho phía máy chủ đó và âm thầm xác thực đối với id phiên được trả lại.

Ngoài ra, nếu việc gửi xác thực không thành công, không bao giờ tiết lộ rằng ngược lại với người dùng là tại sao - theo cách đó, việc gian lận không biết cách theo dõi chúng. Bạn cũng có thể thêm "5 thương tích và bạn ra ngoài" theo dõi, nhưng bạn cần phải loại đăng nhập cho điều đó.

1

Sử dụng ID phiên chắc chắn là một cách để thực hiện. Nhưng có nhiều tùy chọn khác (nếu không phải tất cả) trong số đó liên quan đến việc thêm một số dữ liệu dưới dạng một trường ẩn.

  1. Sử dụng CAPCHA. Điều đó sẽ luôn là duy nhất cho mỗi lần tải trang và do đó bắt buộc phải sử dụng biểu mẫu của bạn.
  2. Tạo dữ liệu ngẫu nhiên và lưu trữ dữ liệu đó trong DB (hoặc chỉ biến số $_SESSION) và kiểm tra sau khi biểu mẫu được gửi.

Tùy chọn một là tùy chọn tôi đề xuất cho biểu mẫu tạo người dùng khi nó kéo gấp đôi nhiệm vụ. Nó dừng tự động gửi biểu mẫu của riêng bạn, trong khi đảm bảo rằng dữ liệu $_POST đến từ biểu mẫu của riêng bạn.

0

Đây là mẫu hình tiêu chuẩn để ngăn XSRF. Về cơ bản nó là tương tự như những gì bạn đã đề cập. Máy chủ tạo một mã thông báo ngẫu nhiên khi biểu mẫu được hiển thị cho người dùng. Nó được gắn với cookie của trình duyệt cho người dùng. Khi gửi biểu mẫu, nó sẽ được gửi trở lại máy chủ. Máy chủ sau đó so sánh mã thông báo với những gì đã được phát hành và hành động biểu mẫu chỉ được thực hiện sau khi khớp thành công.

0

Có rất nhiều đề cập tốt về việc đặt một giá trị duy nhất trong biểu mẫu và khớp với giá trị được lưu trữ trong phiên phía máy chủ. Làm điều đó, nhưng cũng nghĩ về điều sẽ xảy ra khi người dùng sử dụng nút quay lại và có thể cố gắng gửi biểu mẫu hai lần hoặc họ mở cửa sổ trình duyệt thứ hai (cùng một phiên!) Hoặc họ sử dụng nhiều biểu mẫu trên trang web của bạn.

Không tạo lỗi điên bằng cách không nghĩ đến hệ thống của bạn.

+0

Cảm ơn vì điều này tôi đã không nghĩ về những tác động khác của hành động này có thể có. Mặc dù tôi nghĩ rằng những vấn đề này có thể được ngăn chặn bằng cách sử dụng một cái gì đó như thế này 'if (! Isset ($ _ SESSION ['hash'])) {create hash} else {use existing hash}'. –

2
$ref = $_SERVER['HTTP_REFERER']; 
if($ref !== 'some site path/index.php') 
{ 
    die("Access Denied!"); 
} 

Điều này sẽ ngăn hầu hết mọi người đăng dữ liệu lên cơ sở dữ liệu của bạn từ ảnh hưởng bên ngoài.

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