Hướng dẫn dùng sanitize input trong PHP
Việc bảo mật phù hợp là rất quan trọng để giữ cho website hoặc theme hoặc plugin người dùng được an toàn. Một phần của việc đó có nghĩa là xác nhận và chuẩn hóa dữ liệu phù hợp. Trong bài viết này, chúng ta sẽ xem lý do tại sao việc này lại quan trọng, những gì cần phải làm và WordPress đề xuất những hàm trợ giúp nào. Show
Nội dung chính
Nội dung chính
Nội dung chính
Vì dường như có nhiều cách hiểu khác nhau về ý nghĩa của các thuật ngữ 'validation'(xác nhận), 'escaping' và 'sanitization', trước tiên tôi sẽ làm rõ ý của tôi trong bài viết này:
Vì sao sanitization quan trọng?Khi dữ liệu được xem xét trong một số tình huống(giả sử trong tài liệu HTML) - dữ liệu đó có thể bị hiểu sai là code cho môi trường đó(ví dụ code HTML). Nếu dữ liệu đó chứa code độc hại, sau đó sử dụng dữ liệu đó mà không sanitization nó, có nghĩa là code đó sẽ được thực thi. Code thậm chí không nhất thiết phải có hại để gây ra các hiệu ứng không mong muốn. Công việc sanitization là đảm bảo rằng bất kỳ code nào trong dữ liệu không được thông dịch thành code - nếu không, bạn có thể nhận kết quả như trường học của Bobby Tables. Một ví dụ có vẻ vô hại là một trường tìm kiếm có sẵn với cụm từ được tìm kiếm, sử dụng unescaped Điều này tạo ra một lỗ hổng có thể cho phép javascript được chèn vào, ví dụ như lừa ai đó truy cập Làm thế nào code độc này(hoặc nói cách khác) có thể tìm được đường vào website của bạn không phải là mối quan tâm ở đây - quan trọng hơn là ngăn nó thực thi. Chúng tôi cũng không đưa ra các giả định về bản chất của code không mong muốn này hoặc ý định của nó - có thể nó chỉ đơn giản là lỗi phía người dùng. Điều này đưa tôi đến quy tắc số 1 ... Quy tắc số 1: Không tin aiĐó là một câu châm ngôn phổ biến được sử dụng liên quan đến sanitization dữ liệu và đó là một câu châm ngôn hay. Ý tưởng là bạn không nên cho rằng bất kỳ dữ liệu nào được người dùng nhập vào đều an toàn. Bạn cũng không nên cho rằng dữ liệu bạn đã truy xuất từ cơ sở dữ liệu là an toàn - ngay cả khi bạn đã khiến cho nó 'an toàn' trước khi chèn nó vào đó. Trong thực tế, liệu dữ liệu có thể được coi là "an toàn" khi không trong tình huống cụ thể thì xem như vô nghĩa. Đôi khi cùng một dữ liệu có thể được sử dụng trong nhiều tình huống trên cùng một trang. Ví dụ, title có thể chứa dấu ngoặc đơn hoặc dấu ngoặc kép một cách an toàn nếu ở bên trong thẻ header - nhưng sẽ gây ra sự cố nếu được sử dụng(unescaped) bên trong thuộc tính title của link tag. Vì vậy, thật vô nghĩa khi làm 'an toàn' dữ liệu lúc thêm nó vào cơ sở dữ liệu, vì thường không thể làm cho dữ liệu an toàn cho tất cả các tình huống cùng lúc. (Tất nhiên dữ liệu cần được đảm bảo an toàn khi thêm vào cơ sở dữ liệu - nhưng chúng ta sẽ nói đến sau). Ngay cả khi bạn chỉ có ý định sử dụng dữ liệu đó trong một tình huống cụ thể, như trong một form, việc sanitization dữ liệu khi ghi vào cơ sở dữ liệu là vô nghĩa vì theo Quy tắc số 1, bạn không thể tin rằng nó vẫn còn an toàn khi bạn lấy nó ra lại. Quy tắc số 2: Validate dữ liệu vào, escape dữ liệu xuất raĐây là câu châm ngôn về thủ tục bắt đầu khi nào bạn nên xác thực dữ liệu và khi nào bạn sanitization nó. Nói một cách đơn giản - xác thực dữ liệu của bạn(kiểm tra xem nó cần phải ra sao - và nó "hợp lệ") ngay khi bạn nhận được dữ liệu từ người dùng. Khi bạn đến để sử dụng dữ liệu này, ví dụ như khi bạn xuất nó, bạn cần escape(hoặc sanitization) dữ liệu đó. Hình thức sanitization này xảy ra như thế nào, hoàn toàn phụ thuộc vào tình huống sử dụng của bạn. Lời khuyên tốt nhất là thực hiện điều này 'muộn': escape dữ liệu của bạn ngay trước khi bạn sử dụng hoặc hiển thị nó. Bằng cách này, bạn có thể tự tin rằng dữ liệu của mình đã được sanitization đúng cách và bạn không cần phải nhớ xem liệu dữ liệu đã được kiểm tra trước đó. Quy tắc số 3: Tin tưởng WordPressBạn có thể nghĩ "Ok, xác nhận trước khi ghi vào cơ sở dữ liệu và sanitization khi sử dụng nó. Nhưng tôi không cần đảm bảo dữ liệu an toàn để ghi vào cơ sở dữ liệu? ". Cơ bản là có. Khi thêm dữ liệu vào cơ sở dữ liệu hoặc đơn giản là sử dụng dữ liệu nhập vào để tương tác với cơ sở dữ liệu, bạn sẽ cần phải escape dữ liệu trong trường hợp có chứa bất kỳ lệnh SQL nào. Nhưng điều này đưa tôi đến Quy tắc số 3, một quy tắc đối mặt với Quy tắc số 1: Tin tưởng WordPress. Trong một bài viết trước đó, tôi đã
lấy dữ liệu đầu vào của người dùng(được gửi từ một form tìm kiếm bằng AJAX) và sử dụng nó trực tiếp với $posts = get_posts( array( 's'=>$_REQUEST['term'] ) ); Một độc giả quan sát nhận thấy rằng tôi đã không thực hiện bất kỳ sanitization nào - và họ đã đúng. Nhưng tôi đã không cần. Khi bạn sử dụng các hàm cấp cao như Xác nhận dữ liệuKhi bạn nhận được dữ liệu do người dùng nhập vào, quan trọng là phải xác thực nó. (Các thiết lập API, đã trình bày trong loạt bài này, cho phép bạn chỉ định hàm callback để thực hiện điều này chính xác). Dữ liệu không hợp lệ được tự động sửa hoặc quá trình bị hủy bỏ và người dùng được đưa trở lại form để thử lại(hy vọng với thông báo lỗi thích hợp). Mối quan tâm ở đây không phải là an toàn mà là tính hợp lệ - nếu bạn làm đúng, WordPress sẽ xử lý việc thêm dữ liệu vào cơ sở dữ liệu một cách an toàn. "Valid"(hợp lệ) nghĩa là gì tùy thuộc vào bạn - có thể nghĩa là địa chỉ email hợp lệ, số nguyên dương, văn bản có độ dài giới hạn hoặc một trong các array có tùy chọn chỉ định. Tuy nhiên, mục đích của bạn là xác định tính hợp lệ, WordPress cung cấp rất nhiều hàm hữu ích. NumberKhi mong đợi dữ liệu number, có thể kiểm tra xem dữ liệu 'là một kiểu number', ví dụ Nếu bạn cần muốn con số được thêm vào các số 0 đứng đầu, WordPress cung cấp hàm
Ví dụ: echo zeroise(70,4); // Prints 0070 Để kiểm tra tính hợp lệ của email, WordPress có hàm $email = is_email('[email protected]^ample.com'); // $email is set to false. $email = is_email(''); // $email is set to ''. HTMLThường có thể bạn chỉ muốn cho phép một số tag của HTML trong dữ liệu của mình - ví dụ như trong các bình luận được đăng trên website của bạn. WordPress cung cấp một nhóm các hàm có dạng
$content = "Click here to visit wptuts+ "; echo wp_kses( $content, array( 'strong' => array(), 'a' => array('href') ) ); // Prints the HTML "Click here to visit wptuts+ ": Click here to visit wptuts+ Tất nhiên, việc chỉ định các tag được dùng và từng attribute(thuộc tính) được dùng sẽ là một nhiệm vụ Vì vậy, WordPress cung cấp các hàm khác cho phép bạn sử dụng
Các hàm trên rất hữu ích trong việc đảm bảo rằng HTML từ người dùng chỉ chứa các thành phần an toàn. Khi chúng tôi thực hiện xong,
chúng tôi cũng muốn đảm bảo rằng tag mở có tag đóng tương ứng. Đối với điều này, chúng ta có thể sử dụng
// Content with missing closing tag $content = "Click here to visit wptuts+"; echo balanceTags($content,true), // Prints the HTML "Click here to visit wptuts+ " Filename(tên file)Nếu bạn muốn tạo một file trong một trong các thư mục của website của mình, bạn sẽ muốn đảm bảo tên file là hợp lệ và chính thức. Bạn cũng muốn đảm bảo rằng tên file là duy nhất trong thư mục đó. Đối với điều này WordPress cung cấp:
Dữ liệu từ các text fieldKhi nhận dữ liệu được nhập vào text field, có thể bạn sẽ muốn loại bỏ các space, tab và line break(ngắt dòng), cũng như lược bỏ tag bất kỳ. Trường hợp này WordPress có KeysWordPress cũng có Sanitization cho dữ liệuTrong khi đó việc xác nhận có liên quan đến việc đảm bảo dữ liệu là hợp lệ - sanitization dữ liệu là về việc làm cho nó an toàn. Mặc dù một số hàm xác thực được đề cập ở trên có thể hữu ích trong việc đảm bảo dữ liệu an toàn - nói chung là không đủ. Ngay cả dữ liệu 'hợp lệ' cũng có thể không an toàn trong các tình huống nhất định. Quy tắc số 4: Việc giữ cho dữ liệu an toàn chủ yếu là về tính huốngNói đơn giản bạn không thể hỏi "Làm thế nào để tôi khiến dữ liệu này an toàn?". Thay vào đó, bạn nên hỏi, "Làm sao để tôi làm cho dữ liệu này an toàn khi sử dụng nó trong X". Để minh họa luận điểm này, giả sử bạn có một widget với textarea, đây là nơi bạn sẽ cho người dùng nhập vào HTML. Giả sử họ nhập: Hello World Code này là hoàn toàn hợp lệ và an toàn, HTML - tuy nhiên khi bạn nhấp save, chúng tôi thấy rằng văn bản đã nhảy ra khỏi textarea. Code HTML không phải giá trị an toàn cho textarea. Điều an toàn để sử dụng trong một tình huống, không hẳn sẽ an toàn trong một tình huống khác. Bất cứ khi nào bạn sử dụng hoặc hiển thị dữ liệu, bạn phải ghi nhớ những hình thức sanitization cần phải được thực hiện để làm cho việc sử dụng dữ liệu đó an toàn. Đây là lý do tại sao WordPress thường cung cấp một số hàm cho cùng nội dung, ví dụ:
Tất cả đều thực hiện việc sanitization cần thiết cho một tình huống cụ thể - và nếu bạn đang sử dụng chúng, bạn nên chắc chắn đã sử dụng đúng. Tuy nhiên, đôi khi, chúng tôi sẽ cần thực hiện sanitization riêng của mình - thường vì chúng tôi có dữ liệu nhập bổ sung ngoài title của post, permalink, content, v.v. WordPress xử lý cho việc đó. Escape HTMLKhi in các biến ra trang, chúng ta cần lưu ý về cách trình duyệt sẽ biên dịch chúng. Hãy xem xét ví dụ sau: Giả sử
Hình thức injection này(cũng được trình bày trong ví dụ của form tìm kiếm) được gọi là Cross-site scripting và ví dụ đơn giản này cho thấy mức độ nghiêm trọng. Injected script về cơ bản có thể kiểm
soát trình duyệt và 'nhân danh' người dùng hoặc đánh cắp cookie của người dùng. Điều này trở thành một vấn đề thậm chí nghiêm trọng hơn nếu người dùng có đăng nhập. Để ngăn các biến được in ra trong HTML được hiểu là HTML, WordPress cung cấp hàm Escape các thuộc tínhBây giờ hãy xem xét ví dụ sau: Vì Trong ví dụ này, chúng ta nên có: Cả
Tên các Class HTMLĐối với tên class, WordPress cung cấp
Escape các URLBây giờ chúng ta hãy xem xét một thực hành phổ biến khác, in các biến thành thuộc tính Link Text Rõ ràng nó dễ bị tấn công bằng hình thức tấn công đã minh họa trong việc escape HTML và các thuộc tính. Nhưng điều gì sẽ xảy ra nếu $url = 'javascript:alert(\'Injected javascript\')' Khi nhấp vào liên kết, hàm alert sẽ bị loại bỏ. Hàm này không chứa HTML hoặc bất kỳ trích dẫn nào cho phép nó vượt
ra khỏi thuộc tính href - vì vậy ở đây
Những gì esc_url_raw thực hiện gần giống với esc_url, nhưng nó không thay các thế ký hiệu và dấu ngoặc đơn (mà bạn không muốn, khi sử dụng URL thành URL, thay vì hiển thị URL). Trong ví dụ này, chúng tôi đang hiển thị URL, vì vậy chúng tôi
sử dụng Link Text Mặc dù đa số các trường hợp là không cần thiết trong, nhưng cả hai hàm đều nhận một array tùy chọn để chỉ định giao thức nào (như Escape JavaScriptĐôi khi, bạn sẽ muốn in các biến javascript lên một trang (thường ở head): Trong thực tế, nếu bạn đang làm điều này, gần như chắc chắn bạn sẽ sử dụng Tuy nhiên, để làm cho ví dụ trên an toàn, bạn có thể sử dụng hàm Escape TextareaKhi hiển thị nội dung trong textarea, text <b>bold</b>' ?>
text bold Thay vì cũng encode Đối với điều này, WordPress cung cấp text <b>bold</b>' ?> AntispambotHiển thị địa chỉ e-mail trên website của bạn khiến các email này dễ bị lấy đi. Một phương pháp đơn giản là ngụy trang địa chỉ email. WordPress cung cấp
$email = ""; $email = sanitize_email($email); echo ''.antispambot($email).' '; Các chuỗi truy vấnNếu bạn muốn thêm (hoặc xóa) các biến khỏi string truy vấn (điều này rất hữu ích nếu bạn
muốn cho phép người dùng chọn thứ tự cho các bài đăng của mình), cách an toàn và dễ nhất là sử dụng
// If we are at www.example.com/wp-admin/edit.php?post_type=book $query_params = array ('page' => 'my-bage'); $url = add_query_arg( $query_params ); // Would set $url to be: // www.example.com/wp-admin/edit.php?post_type=book&page=my-page Validation & SanitizationNhư đã đề cập trước đây, việc sanitize không có ý nghĩa gì nếu không có tình huống cụ thể - vì vậy việc sanitization dữ liệu khi ghi vào cơ sở dữ liệu là vô nghĩa. Thông thường, dù sao bạn cũng cần lưu trữ dữ liệu ở định dạng thô và trong tất cả trường hợp - Quy tắc số 1 chỉ ra chúng ta phải luôn sanitization dữ liệu xuất ra. Việc xác thực dữ liệu, mặt khác, nên được thực hiện ngay khi nhận được và trước khi được ghi vào cơ sở dữ liệu. Ý tưởng là dữ liệu 'không hợp lệ' nên được tự động sửa hoặc được gắn cờ với dữ liệu và chỉ nên cung cấp dữ liệu hợp lệ cho cơ sở dữ liệu. Có nghĩa là - bạn cũng có thể muốn thực hiện xác nhận khi dữ liệu cũng được hiển thị. Đôi khi trên thực tế, 'validation' cũng sẽ đảm bảo dữ liệu an toàn. Nhưng ưu tiên ở đây là sự an toàn và bạn nên tránh việc xác thực quá mức cho mỗi lần tải trang (ví dụ, các
hàm Escape cơ sở dữ liệuKhi sử dụng các hàm như Chúng ta hãy xem xét lệnh ' SELECT * WHERE age='$age' AND firstname = '$firstname' Chúng tôi đã không escape khỏi các biến này, vì vậy các lệnh có tiềm năng hơn có thể được chèn vào. Mượn ví dụ của xkcd ở bên trên: $age = 14; $firstname = "Robert'; DROP TABLE Students;"; $sql = "SELECT * WHERE age='$age' AND firstname = '$firstname';"; $results = $wpdb->query Sẽ chạy như các lệnh: SELECT * WHERE age='14' AND firstname = 'Robert'; DROP TABLE Students;'; Và xóa toàn bộ bảng Students của chúng tôi. Để ngăn điều này, chúng ta có thể sử dụng phương thức
Trong ví dụ này: $age = 14; $firstname = "Robert'; DROP TABLE Students;"; $sql = $wpdb->prepare('SELECT * WHERE age=%d AND firstname = %s;',array($age,$firstname)); $results = $wpdb->get_results($sql); Truy vấn SQL đã escape (
Chèn và cập nhật dữ liệuĐể thêm mới hoặc cập nhật dữ liệu, WordPress giúp mọi việc dễ dàng hơn bằng cách cung cấp các phương thức Phương thức
$age = 14; $firstname = "Robert'; DROP TABLE Students;"; $wpdb->insert( 'Students', array( 'firstname' => $firstname, 'age' => $age ), array( '%s', '%d' ) ); Phương thức
// Update Robert'; DROP TABLE Students; to Bobby $oldname = "Robert'; DROP TABLE Students;"; $newname = "Bobby"; $wpdb->update( 'Students', array( 'firstname' => $newname ), array( 'firstname' => $oldname ), array( '%s' ), array( '%s' ) ); Cả hai phương thức Các câu lệnh LIKEVì phương thức $age=14; $firstname = "Robert'; DROP TABLE Students;"; SELECT * WHERE age=$age (firstname LIKE '%$firstname%'); Sẽ thực hiện an toàn với: $age=14; $firstname = "Robert'; DROP TABLE Students;"; SELECT * WHERE age=$age AND (firstname LIKE '%$firstname%'); $query = $wpdb->prepare('SELECT * WHERE age=%d AND (firstname LIKE %s);', array($age, '%'.like_escape($firstname).'%') ); Tóm tắtĐây không phải danh sách đầy đủ các hàm có sẵn để validate và sanitize, nhưng nó sẽ bao gồm phần lớn các trường hợp sử dụng. Rất nhiều hàm(và các hàm khác) này có thể được tìm thấy trong Bạn thấy bài viết này hữu ích không? Bạn có thêm đề xuất nào về các thực tiễn tốt nhất để validate và sanitizie dữ liệu trong WordPress không? Hãy cho chúng tôi biết trong các bình luận dưới đây. |