Bảo mật trong PHP
Khi viết mã PHP, điều rất quan trọng là phải ghi nhớ các lỗ hổng bảo mật sau đây để tránh viết mã không an toàn.
Các loại lỗ hổng
Đây là những lỗ hổng phổ biến mà bạn sẽ gặp phải khi viết mã PHP. Chúng ta sẽ thảo luận sâu hơn về một số vấn đề bên dưới.
- Cross Site Request Forgery Một lỗ hổng trong ứng dụng do lập trình viên không kiểm tra xem yêu cầu được gửi từ đâu – cuộc tấn công này được gửi đến người dùng cấp đặc quyền cao để có quyền truy cập cấp cao hơn vào ứng dụng.
- Cross Site Scripting Một lỗ hổng trong ứng dụng do lập trình viên không làm sạch đầu vào trước khi xuất đầu vào cho trình duyệt (ví dụ: nhận xét trên blog). Nó thường được sử dụng để chạy javascript độc hại trong trình duyệt để thực hiện các cuộc tấn công như đánh cắp cookie phiên trong số các hành động độc hại khác để giành được các đặc quyền cấp cao hơn trong ứng dụng.
- Bao gồm tệp cục bộ Một lỗ hổng trong ứng dụng do lập trình viên yêu cầu đầu vào tệp do người dùng cung cấp và không vệ sinh đầu vào trước khi truy cập tệp được yêu cầu. Điều này dẫn đến một tệp được đưa vào nơi không nên có.
- Bao gồm tệp từ xa Một lỗ hổng trong ứng dụng do lập trình viên yêu cầu đầu vào tệp do người dùng cung cấp và không vệ sinh đầu vào trước khi truy cập tệp được yêu cầu. Điều này dẫn đến việc một tệp được lấy từ một máy chủ từ xa và được đưa vào nơi không nên có.
- Đánh cắp phiên Một lỗ hổng gây ra bởi kẻ tấn công giành được quyền truy cập vào mã định danh phiên của người dùng và có thể sử dụng tài khoản của người dùng khác mạo danh họ. Điều này thường được sử dụng để có quyền truy cập vào tài khoản của người dùng quản trị.
- Session Identifier Acquirement Session Identifier Acquirement là một lỗ hổng gây ra bởi kẻ tấn công có thể đoán mã định danh phiên của người dùng hoặc khai thác lỗ hổng trong chính ứng dụng hoặc trình duyệt của người dùng để lấy mã định danh phiên.
- SQL Injection Một lỗ hổng trong ứng dụng do lập trình viên không làm sạch đầu vào trước khi đưa nó vào một truy vấn vào cơ sở dữ liệu. Điều này dẫn đến kẻ tấn công có quyền đọc đầy đủ và thường xuyên hơn là không ghi quyền truy cập vào cơ sở dữ liệu. Với kiểu truy cập này, kẻ tấn công có thể làm những việc rất tồi tệ.
Bây giờ hãy xem xét một số lỗ hổng phổ biến chi tiết hơn.
Cướp phiên
Cướp phiên là một lỗ hổng do kẻ tấn công giành được quyền truy cập vào mã định danh phiên của người dùng và có thể sử dụng tài khoản của người dùng khác mạo danh họ. Điều này thường được sử dụng để có quyền truy cập vào tài khoản của người dùng quản trị.
Bảo vệ chống lại các cuộc tấn công chiếm quyền điều khiển phiên trong PHP
Để chống lại các cuộc tấn công chiếm quyền điều khiển phiên, bạn cần kiểm tra thông tin vị trí và trình duyệt của người dùng hiện tại với thông tin được lưu trữ về phiên. Dưới đây là một triển khai ví dụ có thể giúp giảm thiểu tác động của cuộc tấn công chiếm quyền điều khiển phiên. Nó kiểm tra Địa chỉ IP, Tác nhân người dùng và nếu Phiên hết hạn sẽ xóa một phiên trước khi phiên được tiếp tục.
<?php
session_start();
// Does IP Address match?
if ($_SERVER['REMOTE_ADDR'] != $_SESSION['ipaddress'])
{
session_unset();
session_destroy();
}
// Does user agent match?
if ($_SERVER['HTTP_USER_AGENT'] != $_SESSION['useragent'])
{
session_unset();
session_destroy();
}
// Is the last access over an hour ago?
if (time() > ($_SESSION['lastaccess'] + 3600))
{
session_unset();
session_destroy();
}
else
{
$_SESSION['lastaccess'] = time();
}
Tập lệnh chéo trang
Cross Site Scripting là một loại lỗ hổng trong ứng dụng web do lập trình viên không làm sạch đầu vào trước khi xuất đầu vào cho trình duyệt web (ví dụ: nhận xét trên blog). Nó thường được sử dụng để chạy javascript độc hại trong trình duyệt web để thực hiện các cuộc tấn công như đánh cắp cookie phiên trong số các hành động độc hại khác để giành được các đặc quyền cấp cao hơn trong ứng dụng web.
Ví dụ Tấn công Cross Site Scripting
Một blog cho phép người dùng tạo kiểu cho các nhận xét của họ bằng các thẻ HTML, tuy nhiên, tập lệnh cung cấp năng lượng cho blog không bị loại bỏ <script>
thẻ cho phép bất kỳ người dùng nào chạy javascript trên trang. Kẻ tấn công có thể lợi dụng điều này để chạy javascript độc hại trong trình duyệt. Chúng có thể lây nhiễm phần mềm độc hại cho người dùng, đánh cắp cookie phiên, v.v.
<script>
alert('Cross Site Scripting!');
</script>
Bảo vệ trang web của bạn khỏi các cuộc tấn công cross-site scripting trong PHP
Trong PHP có hai chức năng chính, htmlspecialchars()
và strip_tags()
được tích hợp sẵn để bảo vệ bạn khỏi các cuộc tấn công tập lệnh chéo trang.
Các htmlspecialchars($string)
sẽ ngăn một chuỗi HTML hiển thị dưới dạng HTML và hiển thị nó dưới dạng văn bản thuần túy cho trình duyệt web. ví dụ mã htmlspecialchars()
<?php
$usercomment = "<string>alert('Cross Site Scripting!');</script>";
echo htmlspecialchars($usercomment);
Cách tiếp cận khác là strip_tags($string, $allowedtags)
chức năng loại bỏ tất cả các thẻ HTML ngoại trừ các thẻ HTML mà bạn đã đưa vào danh sách cho phép. Điều quan trọng cần lưu ý là với strip_tags()
chức năng này, bạn phải cẩn thận hơn, chức năng này không ngăn người dùng đưa javascript làm liên kết, bạn sẽ phải tự vệ sinh chức năng đó.
ví dụ mã strip_tags()
<?php
$usercomment = "<string>alert('Cross Site Scripting!');</script>";
$allowedtags = "<p><a><h1><h2><h3>";
echo strip_tags($usercomment, $allowedtags);
Đặt Tiêu đề bảo vệ X-XSS:
Trong PHP bạn có thể gửi X-XSS-Protection
Tiêu đề sẽ yêu cầu trình duyệt kiểm tra cuộc tấn công Cross Site Scripting được phản ánh và chặn tải trang. Điều này không ngăn chặn tất cả các cuộc tấn công cross-site scripting chỉ phản ánh những cuộc tấn công và nên được sử dụng kết hợp với các phương pháp khác.
<?php
header("X-XSS-Protection: 1; mode=block");
Viết chức năng vệ sinh của riêng bạn Một tùy chọn khác, nếu bạn muốn kiểm soát nhiều hơn cách hoạt động của quá trình dọn dẹp, là viết chức năng Vệ sinh HTML của riêng bạn, điều này không được khuyến nghị cho Người mới bắt đầu sử dụng PHP vì một lỗi sẽ khiến trang web của bạn dễ bị tấn công.
Bảo vệ trang web của bạn khỏi các cuộc tấn công tập lệnh chéo trang bằng Chính sách bảo mật nội dung
Một cách tiếp cận hiệu quả để ngăn chặn các cuộc tấn công kịch bản chéo trang, có thể yêu cầu nhiều điều chỉnh đối với cơ sở mã và thiết kế ứng dụng web của bạn, là sử dụng chính sách bảo mật nội dung.
Cách phổ biến nhất để đặt Chính sách bảo mật nội dung là đặt chính sách đó trực tiếp trong Tiêu đề HTTP. Điều này có thể được thực hiện bởi máy chủ web bằng cách chỉnh sửa cấu hình của nó hoặc bằng cách gửi nó qua PHP.
Ví dụ về Chính sách bảo mật nội dung được đặt trong Tiêu đề HTTP
<?php
header("content-security-policy: default-src 'self'; img-src https://*; child-src 'none';");
Đặt Chính sách bảo mật nội dung làm thẻ Meta
Bạn có thể bao gồm Chính sách bảo mật nội dung của mình trong HTML của trang và đặt trên cơ sở từng trang. Phương pháp này yêu cầu bạn phải đặt trên mọi trang nếu không bạn sẽ mất lợi ích của chính sách.
Ví dụ về Chính sách bảo mật nội dung được đặt trong Thẻ meta HTML
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-s
tiêm SQL
SQL injection là một lỗ hổng trong ứng dụng do lập trình viên không làm sạch đầu vào trước khi đưa nó vào một truy vấn vào cơ sở dữ liệu. Điều này dẫn đến kẻ tấn công có quyền đọc đầy đủ và thường xuyên hơn là không ghi quyền truy cập vào cơ sở dữ liệu. Với kiểu truy cập này, kẻ tấn công có thể làm những việc rất tồi tệ.
Ví dụ tấn công SQL injection
Tập lệnh PHP bên dưới chạy Câu lệnh SQL để nhận email của người dùng theo ID. Tuy nhiên, đầu vào không được làm sạch khiến nó dễ bị SQL Injection
<?php
$input = $_GET['id'];
$dbserver = "localhost";
$dbuser = "camper";
$dbpass = "supersecretcampsitepassword";
$dbname = "freecodecamp";
$conn = new mysqli($dbserver, $dbuser, $dbpass, $dbname);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT email FROM users WHERE id =" . $input;
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
echo $row["email"];
}
} else {
echo "no results";
}
$conn->close();
SELECT email FROM users WHERE id = `$input`;
Vì vậy, với phần trên, đầu vào không được truyền kiểu (Tức là truyền đầu vào bằng (int) nên chỉ cho phép một số) cũng như không thoát cho phép ai đó thực hiện một cuộc tấn công SQL Injection – ví dụ: URL getemailbyuserid.php?id=1'; My Query Here-- -
sẽ cho phép bạn chạy các truy vấn SQL tùy ý mà không tốn nhiều công sức.
Bảo vệ trang web của bạn khỏi các cuộc tấn công sql injection trong PHP
Có một số cách tiếp cận để bảo vệ trang web của bạn khỏi các cuộc tấn công SQL Injection. Các cách tiếp cận này là Danh sách trắng, Truyền kiểu và Thoát khỏi ký tự
Danh sách trắng: Phương pháp lập danh sách trắng được sử dụng trong trường hợp chỉ có một vài đầu vào được mong đợi. Bạn có thể liệt kê từng đầu vào dự kiến trong PHP Switch và sau đó có một giá trị mặc định cho đầu vào không hợp lệ. Bạn không phải lo lắng về vấn đề truyền kiểu hoặc bỏ qua thoát ký tự nhưng đầu vào được phép cực kỳ hạn chế. Nó vẫn là một tùy chọn, xem ví dụ bên dưới.
<?php
switch ($input) {
case "1":
//db query 1
break;
case "2":
//db query 2
break;
default:
// invalid input return error
}
Loại đúc: Phương pháp truyền kiểu thường được sử dụng cho một ứng dụng sử dụng đầu vào số. Chỉ cần truyền đầu vào với (int) $input
và chỉ một giá trị số sẽ được cho phép.
Thoát khỏi nhân vật: Cách tiếp cận thoát khỏi ký tự sẽ thoát khỏi các ký tự như dấu ngoặc kép và dấu gạch chéo do người dùng cung cấp để ngăn chặn cuộc tấn công. Nếu bạn đang sử dụng Máy chủ MySQL và thư viện MySQLi để truy cập cơ sở dữ liệu của mình, mysqli_real_escape_string($conn, $string)
hàm sẽ nhận hai đối số, kết nối MySQLi và chuỗi và sẽ thoát khỏi đầu vào của người dùng một cách chính xác để chặn một cuộc tấn công sql injection. Chức năng chính xác mà bạn sử dụng tùy thuộc vào loại cơ sở dữ liệu và thư viện php bạn đang sử dụng, hãy kiểm tra tài liệu của thư viện php để biết thêm thông tin về cách thoát đầu vào của người dùng.