Ok, có hai vấn đề riêng biệt nhưng có liên quan và mỗi vấn đề được xử lý khác nhau.
Phiên cố định
Đây là nơi kẻ tấn công đặt rõ ràng định danh phiên của phiên cho người dùng. Thông thường trong PHP nó được thực hiện bằng cách cung cấp cho họ một url như thế http://www.example.com/index...?session_name=sessionid
. Một khi kẻ tấn công cung cấp url cho khách hàng, cuộc tấn công cũng giống như một cuộc tấn công chiếm quyền điều khiển phiên.
Có một số cách để ngăn chặn phiên cố định (thực hiện tất cả chúng):
Đặt session.use_trans_sid = 0
trong php.ini
tập tin của bạn . Điều này sẽ bảo PHP không bao gồm mã định danh trong URL và không đọc URL cho mã định danh.
Đặt session.use_only_cookies = 1
trong php.ini
tập tin của bạn . Điều này sẽ nói với PHP không bao giờ sử dụng URL với các định danh phiên.
Tạo lại ID phiên bất cứ khi nào trạng thái của phiên thay đổi. Điều đó có nghĩa là bất kỳ điều nào sau đây:
- Xác thực người dùng
- Lưu trữ thông tin nhạy cảm trong phiên
- Thay đổi bất cứ điều gì về phiên
- Vân vân...
Chiếm quyền điều khiển phiên
Đây là nơi kẻ tấn công nắm giữ mã định danh phiên và có thể gửi yêu cầu như thể chúng là người dùng đó. Điều đó có nghĩa là vì kẻ tấn công có mã định danh, tất cả chúng đều không thể phân biệt được với người dùng hợp lệ đối với máy chủ.
Bạn không thể trực tiếp ngăn chặn chiếm quyền điều khiển phiên. Tuy nhiên, bạn có thể đặt các bước để làm cho nó rất khó sử dụng.
Sử dụng một định danh băm phiên mạnh: session.hash_function
in php.ini
. Nếu PHP <5.3, hãy đặt nó thành session.hash_function = 1
SHA1. Nếu PHP> = 5.3, đặt nó thành session.hash_function = sha256
hoặc session.hash_function = sha512
.
Gửi một băm mạnh: session.hash_bits_per_character
trong php.ini
. Đặt cái này thành session.hash_bits_per_character = 5
. Mặc dù điều này không làm cho việc bẻ khóa trở nên khó khăn hơn , nhưng nó sẽ tạo ra sự khác biệt khi kẻ tấn công cố gắng đoán định danh phiên. ID sẽ ngắn hơn, nhưng sử dụng nhiều ký tự hơn.
Đặt một entropy bổ sung với session.entropy_file
và session.entropy_length
trong php.ini
tệp của bạn . session.entropy_file = /dev/urandom
Ví dụ, đặt trước và sau thành số byte sẽ được đọc từ tệp entropy session.entropy_length = 256
.
Thay đổi tên của phiên từ PHPSESSID mặc định. Điều này được thực hiện bằng cách gọi session_name()
với tên định danh của riêng bạn làm tham số đầu tiên trước khi gọi session_start
.
Nếu bạn thực sự hoang tưởng, bạn cũng có thể xoay tên phiên, nhưng hãy cẩn thận rằng tất cả các phiên sẽ tự động bị vô hiệu nếu bạn thay đổi điều này (ví dụ: nếu bạn làm cho nó phụ thuộc vào thời gian). Nhưng tùy thuộc vào trường hợp sử dụng của bạn, nó có thể là một tùy chọn ...
Xoay định danh phiên của bạn thường xuyên. Tôi sẽ không làm điều này mỗi yêu cầu (trừ khi bạn thực sự cần mức bảo mật đó), nhưng trong một khoảng thời gian ngẫu nhiên. Bạn muốn thay đổi điều này thường xuyên vì nếu kẻ tấn công chiếm quyền điều khiển phiên bạn không muốn chúng có thể sử dụng nó quá lâu.
Bao gồm các tác nhân người dùng từ$_SERVER['HTTP_USER_AGENT']
trong phiên. Về cơ bản, khi phiên bắt đầu, lưu trữ nó trong một cái gì đó như $_SESSION['user_agent']
. Sau đó, trên mỗi yêu cầu tiếp theo kiểm tra xem nó phù hợp. Lưu ý rằng điều này có thể được làm giả để nó không đáng tin cậy 100%, nhưng tốt hơn là không.
Bao gồm địa chỉ IP của người dùng từ$_SERVER['REMOTE_ADDR']
trong phiên. Về cơ bản, khi phiên bắt đầu, lưu trữ nó trong một cái gì đó như $_SESSION['remote_ip']
. Điều này có thể có vấn đề từ một số ISP sử dụng nhiều địa chỉ IP cho người dùng của họ (chẳng hạn như AOL được sử dụng để làm). Nhưng nếu bạn sử dụng nó, nó sẽ an toàn hơn nhiều. Cách duy nhất để kẻ tấn công giả mạo địa chỉ IP là thỏa hiệp mạng tại một số điểm giữa người dùng thật và bạn. Và nếu họ thỏa hiệp mạng, họ có thể làm điều tồi tệ hơn nhiều so với một vụ không tặc (như các cuộc tấn công MITM, v.v.).
Bao gồm mã thông báo trong phiên và về phía trình duyệt mà bạn tăng và so sánh thường xuyên. Về cơ bản, đối với mỗi yêu cầu làm $_SESSION['counter']++
ở phía máy chủ. Cũng làm một cái gì đó trong JS ở phía trình duyệt để làm tương tự (sử dụng bộ nhớ cục bộ). Sau đó, khi bạn gửi yêu cầu, chỉ cần lấy một mã thông báo và xác minh rằng số lần mở đó là giống nhau trên máy chủ. Bằng cách này, bạn sẽ có thể phát hiện phiên bị tấn công do kẻ tấn công sẽ không có bộ đếm chính xác hoặc nếu chúng có 2 hệ thống truyền cùng một số lượng và có thể nói một hệ thống bị giả mạo. Điều này sẽ không hoạt động cho tất cả các ứng dụng, nhưng là một cách để khắc phục vấn đề.
Một lưu ý về hai
Sự khác biệt giữa Cố định phiên và Tấn công chỉ là về cách định danh phiên bị xâm phạm. Trong bản sửa lỗi, mã định danh được đặt thành giá trị mà kẻ tấn công biết trước. Trong Hijacking, nó được đoán hoặc đánh cắp từ người dùng. Mặt khác, hiệu ứng của cả hai là như nhau một khi định danh bị xâm phạm.
Tái tạo ID phiên
Bất cứ khi nào bạn tạo lại định danh phiên bằng cách sử dụng session_regenerate_id
phiên cũ sẽ bị xóa. Điều này xảy ra trong suốt với trình xử lý phiên cốt lõi. Tuy nhiên, một số trình xử lý phiên tùy chỉnh sử dụngsession_set_save_handler()
không làm điều này và được mở để tấn công vào các định danh phiên cũ. Đảm bảo rằng nếu bạn đang sử dụng trình xử lý phiên tùy chỉnh, bạn sẽ theo dõi mã định danh mà bạn mở và nếu nó không giống với mã bạn lưu mà bạn xóa rõ ràng (hoặc thay đổi) mã định danh trên cái cũ.
Sử dụng trình xử lý phiên mặc định, bạn vẫn ổn chỉ bằng cách gọi session_regenerate_id(true)
. Điều đó sẽ loại bỏ thông tin phiên cũ cho bạn. ID cũ không còn hiệu lực và sẽ khiến một phiên mới được tạo nếu kẻ tấn công (hoặc bất kỳ ai khác cho vấn đề đó) cố gắng sử dụng nó. Hãy cẩn thận với trình xử lý phiên tùy chỉnh mặc dù ....
Phá hủy một phiên
Nếu bạn định hủy phiên (ví dụ khi đăng xuất), hãy đảm bảo bạn hủy triệt để phiên. Điều này bao gồm việc bỏ đặt cookie. Sử dụng session_destroy
:
function destroySession() {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
session_destroy();
}