Xác thực biểu mẫu PHP

Bài này và bài tiếp theo sẽ giải thích cách sử dụng PHP để xác thực dữ liệu biểu mẫu.

Xác thực biểu mẫu PHP

Lưu ý:Khi xử lý biểu mẫu PHP, hãy chú ý đến tính an toàn!

Những trang này sẽ trình bày cách xử lý an toàn biểu mẫu PHP. Việc xác thực dữ liệu biểu mẫu HTML là rất quan trọng để phòng ngừa hacker và thư rác!

Biểu mẫu HTML mà chúng ta sẽ sử dụng sau này chứa nhiều loại trường nhập liệu: trường văn bản bắt buộc và tùy chọn, nút chọn một và nút gửi:

Biểu mẫu trên sử dụng quy tắc xác thực sau:

Trường Quy tắc xác thực
Name Bắt buộc. Phải chứa chữ cái và khoảng trống.
E-mail Bắt buộc. Phải chứa địa chỉ email hợp lệ (bao gồm @ và .).
Website Tùy chọn. Nếu được chọn, thì phải chứa URL hợp lệ.
Comment Tùy chọn. Trường nhập nhiều dòng (hộp văn bản).
Gender Bắt buộc. Bạn phải chọn một mục.

Trước tiên chúng ta xem mã HTML thuần của biểu mẫu này:

Trường văn bản

name, email và website là các yếu tố nhập liệu văn bản, trường comment là hộp văn bản. Mã HTML của nó như sau:

Name: <input type="text" name="name">
E-mail: <input type="text" name="email">
Website: <input type="text" name="website">
Comment: <textarea name="comment" rows="5" cols="40"></textarea>

Nút chọn một

Trường gender là nút chọn một, mã HTML của nó như sau:

Gender:
<input type="radio" name="gender" value="female">Female
<input type="radio" name="gender" value="male">Male

Các yếu tố biểu mẫu

Mã HTML của biểu mẫu như sau:

<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>

Khi gửi biểu mẫu này, dữ liệu biểu mẫu sẽ được gửi qua phương thức method="post".

Biến $_SERVER["PHP_SELF"] là gì?

$_SERVER["PHP_SELF"] là một biến toàn cục, nó trả về tên tệp của đoạn mã hiện tại đang được thực thi.

Vì vậy, $_SERVER["PHP_SELF"] sẽ gửi dữ liệu biểu mẫu đến trang web hiện tại, thay vì chuyển hướng đến trang khác. Như vậy, người dùng có thể nhận được thông tin cảnh báo lỗi trên trang biểu mẫu.

Hàm htmlspecialchars() là gì?

Hàm htmlspecialchars() chuyển đổi các ký tự đặc biệt thành các thể hiện HTML. Điều này có nghĩa là các ký tự HTML như < và > sẽ được thay thế bằng < và >. Điều này giúp ngăn chặn kẻ tấn công lợi dụng mã HTML hoặc JavaScript (tấn công XSS) trong biểu mẫu.

Lưu ý quan trọng về bảo mật biểu mẫu PHP

Biến $_SERVER["PHP_SELF"] có thể bị kẻ tấn công lợi dụng!

Nếu trang của bạn sử dụng PHP_SELF, người dùng có thể nhập dấu gạch dưới và thực thi XSS.

Lưu ý:XSS (Cross-site scripting) là một loại lỗ hổng bảo mật máy tính, phổ biến trong các ứng dụng web. XSS cho phép kẻ tấn công chèn mã脚本 khách vào trang web mà người dùng khác đang duyệt.

Giả sử trang của chúng ta có tên là "test_form.php" chứa biểu mẫu sau:

<form method="post" action="<?php echo $_SERVER["PHP_SELF"];?>">

Bây giờ, nếu người dùng truy cập vào URL bình thường trong thanh địa chỉ: "http://www.example.com/test_form.php", mã trên sẽ được chuyển đổi thành:

<form method="post" action="test_form.php">

Đến nay, mọi thứ đều bình thường.

Nhưng, nếu người dùng nhập URL sau vào thanh địa chỉ:

http://www.example.com/test_form.php/%22%3E%3Cscript%3Ealert('hacked')%3C/script%3E

Trong trường hợp này, mã trên sẽ được chuyển đổi thành:

<form method="post" action="test_form.php"/><script>alert('hacked')</script>

Mã này đã thêm một đoạn vở kịch và một lệnh thông báo. Và khi trang này được tải, mã JavaScript sẽ được thực thi (người dùng sẽ thấy một hộp thông báo). Đây chỉ là một ví dụ đơn giản và vô hại về cách biến đổi biến PHP_SELF.

Bạn nên nhận ra Thẻ <script> có thể thêm bất kỳ mã JavaScript nào!Hackers có thể chuyển hướng người dùng đến một tệp nào đó trên máy chủ khác, trong đó chứa mã độc hại có thể thay đổi biến toàn cục hoặc gửi biểu mẫu đến địa chỉ khác để lưu trữ dữ liệu người dùng, v.v.

Làm thế nào để tránh $_SERVER["PHP_SELF"] bị lợi dụng?

Bằng cách sử dụng hàm htmlspecialchars() có thể tránh được việc $_SERVER["PHP_SELF"] bị lợi dụng.

Mã biểu mẫu như sau:

<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">

Hàm htmlspecialchars() chuyển các ký tự đặc biệt thành các thẻ HTML. Bây giờ, nếu người dùng cố gắng sử dụng biến PHP_SELF, nó sẽ dẫn đến đầu ra sau:

<form method="post" action="test_form.php/"><script>alert('hacked')</script>">

Không thể sử dụng, không có hại!

Xác thực dữ liệu biểu mẫu bằng PHP

Việc đầu tiên chúng ta cần làm là truyền tất cả các biến qua hàm htmlspecialchars() của PHP.

Sau khi chúng ta sử dụng hàm htmlspecialchars() nếu người dùng cố gắng gửi nội dung sau trong trường văn bản:

<script>location.href('http://www.hacked.com')</script>

- Mã này sẽ không được thực thi vì nó sẽ được lưu trữ như mã đã được chuyển mã hóa, như sau:

<script>location.href('http://www.hacked.com')</script>

Hiện tại, đoạn mã này an toàn khi hiển thị trên trang web hoặc trong email.

Khi người dùng gửi biểu mẫu này, chúng ta cần làm hai việc sau:

  1. (Bằng cách sử dụng hàm trim() của PHP) Xóa các ký tự không cần thiết trong dữ liệu đầu vào của người dùng (các khoảng trống, tab, dòng mới không cần thiết)
  2. (Bằng cách sử dụng hàm stripslashes() của PHP) Xóa các dấu ngoặc kép ngược (\) trong dữ liệu đầu vào của người dùng

Tiếp theo, chúng ta tạo một hàm kiểm tra (để hiệu quả hơn là không cần viết mã nhiều lần).

Chúng ta đặt tên hàm là test_input()。

Hiện tại, chúng ta có thể kiểm tra mỗi biến $_POST bằng hàm test_input() như sau:

Ví dụ

<?php
// Định nghĩa biến và đặt giá trị là rỗng
$name = $email = $gender = $comment = $website = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
  $name = test_input($_POST["name"]);
  $email = test_input($_POST["email"]);
  $website = test_input($_POST["website"]);
  $comment = test_input($_POST["comment"]);
  $gender = test_input($_POST["gender"]);
}
function test_input($data) {
  $data = trim($data);
  $data = stripslashes($data);
  $data = htmlspecialchars($data);
  return $data;
}
?>

Chạy ví dụ

Lưu ý rằng ở đầu đoạn mã, chúng tôi đã kiểm tra biểu mẫu có sử dụng $_SERVER["REQUEST_METHOD"] để gửi không. Nếu REQUEST_METHOD là POST, biểu mẫu đã được gửi - và nên được kiểm tra. Nếu chưa gửi, thì bỏ qua việc kiểm tra và hiển thị biểu mẫu trống.

Tuy nhiên, trong ví dụ trên, tất cả các trường nhập đều là tùy chọn. Mặc dù người dùng không nhập bất kỳ dữ liệu nào, đoạn mã vẫn hoạt động bình thường.

Bước tiếp theo là tạo các trường nhập bắt buộc và tạo các thông báo lỗi cần thiết.