Sửa lỗi / hack phiên PHP


145

Tôi đang cố gắng để hiểu thêm về Sửa lỗi & chiếm quyền điều khiển phiên PHP và cách ngăn chặn các sự cố này. Tôi đã đọc hai bài viết sau trên trang web của Chris Shiflett:

Tuy nhiên, tôi không chắc là tôi hiểu chính xác mọi thứ.

Để giúp ngăn chặn việc sửa phiên là đủ để gọi session_regenerate_id (true); Sau khi đăng nhập thành công? Tôi nghĩ rằng tôi hiểu điều đó một cách chính xác.

Anh ta cũng nói về việc sử dụng mã thông báo được chuyển qua các url thông qua $ _GET để ngăn chặn việc chiếm quyền điều khiển phiên. Làm thế nào điều này sẽ được thực hiện chính xác? Tôi đoán khi ai đó đăng nhập vào bạn tạo mã thông báo của họ và lưu trữ nó trong một biến phiên, thì trên mỗi trang bạn sẽ so sánh biến phiên đó với giá trị của biến $ _GET?

Mã thông báo này chỉ cần được thay đổi một lần mỗi phiên hoặc trên mỗi lần tải trang?

Ngoài ra, đây có phải là cách tốt để ngăn chặn không tặc mà không phải vượt qua một giá trị trong các url? điều này sẽ dễ dàng hơn rất nhiều


Có lẽ bạn có thể thêm liên kết đến các trang nơi bạn đã tìm thấy các đề xuất này.
Gumbo

Câu trả lời:


219

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 = 0trong php.initậ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 = 1trong php.initậ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_functionin php.ini. Nếu PHP <5.3, hãy đặt nó thành session.hash_function = 1SHA1. Nếu PHP> = 5.3, đặt nó thành session.hash_function = sha256hoặc session.hash_function = sha512.

  • Gửi một băm mạnh: session.hash_bits_per_charactertrong 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_filesession.entropy_lengthtrong php.initệp của bạn . session.entropy_file = /dev/urandomVí 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_idphiê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();
}

4
Sử dụng 5 thay vì 4 bit cho mỗi ký tự sẽ không làm thay đổi cường độ mạnh mẽ của bất kỳ cách nào Nhưng mặc dù điểm của bạn được khuyến khích nói chung, họ thiếu một số chi tiết quan trọng. Ví dụ: những gì xảy ra với phiên có liên quan đến ID phiên cũ hoặc cách xử lý phiên có ID phiên cũ sau khi phiên không hợp lệ.
Gumbo

2
@battal: Không, đó là điểm chính. session_regenerate_idkhông làm mất hiệu lực phiên vẫn được liên kết với ID cũ; chỉ khi tham số xóa_old_session được đặt thành đúng thì phiên sẽ bị hủy. Nhưng nếu kẻ tấn công bắt đầu tái tạo ID này thì sao?
Gumbo

6
Tôi không đồng ý với việc tạo lại phiên mỗi khi bạn thay đổi biến phiên, chỉ nên thực hiện khi đăng nhập / đăng xuất. Ngoài ra, việc kiểm tra tác nhân người dùng là vô nghĩa và việc kiểm tra REMOTE_ADDR là vấn đề. Một điều tôi muốn thêm là session.entropy_file = /dev/urandom. Thế hệ entropy nội bộ của PHP được chứng minh là cực kỳ yếu và nhóm entropy được cung cấp bởi / dev / Random hoặc / dev / uranom là thứ tốt nhất bạn có thể có trên máy chủ web mà không cần rng phần cứng.
rook

4
Ngoài ra, bạn nên thêm session.cookie_httponlysession.cookie_secure. Cái đầu tiên giúp cản trở xss (nhưng nó không hoàn hảo). Thứ 2 là cách tốt nhất để ngăn chặn OWASP A9 ...
rook

4
Không hiểu câu trả lời tuyệt vời như vậy nhưng thiếu phần nhập nhiều nhất: sử dụng SSL / HTTPS. Gia số bộ đếm là nguồn gây ra nhiều vấn đề với nhiều yêu cầu nhanh chóng, người dùng làm mới một trang hai lần hoặc nhấn nút gửi hai lần. Giải pháp địa chỉ IP hiện nay là một vấn đề với tất cả người dùng di động và luôn thay đổi IP. Bạn có thể nhìn vào bộ IP đầu tiên, nhưng vẫn gặp rắc rối. Tốt nhất là ngăn chặn việc phát hiện id phiên ở vị trí đầu tiên và đó là sử dụng SSL / HTTPS.
Sanne

37

Cả hai phiên tấn công đều có chung một mục tiêu: Có quyền truy cập vào phiên hợp pháp của người dùng khác. Nhưng các vectơ tấn công thì khác:

Trong cả hai cuộc tấn công, ID phiên là dữ liệu nhạy cảm mà cuộc tấn công này được tập trung vào. Vì vậy, đó là ID phiên cần được bảo vệ cho cả truy cập đọc (Truy cập phiên) và truy cập ghi (Sửa lỗi phiên).

Quy tắc chung về bảo vệ dữ liệu nhạy cảm bằng cách sử dụng HTTPS cũng áp dụng trong trường hợp này. Ngoài ra, bạn nên làm như sau:

Để ngăn chặn các cuộc tấn công Cố định phiên , hãy đảm bảo rằng:

Để ngăn chặn các cuộc tấn công cướp phiên , hãy đảm bảo rằng:

Để ngăn chặn cả hai cuộc tấn công phiên, hãy đảm bảo rằng:

  • để chỉ chấp nhận các phiên mà ứng dụng của bạn đã bắt đầu. Bạn có thể làm điều này bằng cách lấy dấu vân tay của một phiên khi bắt đầu với thông tin cụ thể của khách hàng. Bạn có thể sử dụng User-Agent ID nhưng không sử dụng địa chỉ IP từ xa hoặc bất kỳ thông tin khác có thể thay đổi từ giữa các yêu cầu.
  • để thay đổi ID phiên sử dụng session_regenerate_id(true)sau khi thử xác thực ( truechỉ khi thành công) hoặc thay đổi đặc quyền và hủy phiên cũ. (Đảm bảo lưu trữ bất kỳ thay đổi nào của $_SESSIONviệc sử dụng session_write_close trước khi tạo lại ID nếu bạn muốn duy trì phiên liên quan đến ID cũ; nếu không thì chỉ có phiên có ID mới sẽ bị ảnh hưởng bởi những thay đổi đó.)
  • để sử dụng triển khai hết hạn phiên thích hợp (xem Làm cách nào để hết hạn phiên PHP sau 30 phút? ).

Bài đăng tuyệt vời, đặc biệt là phần cuối cùng.
Mattis

6

Các mã thông báo bạn đề cập là "số nonce" - số được sử dụng một lần. Chúng không nhất thiết phải được sử dụng chỉ một lần, nhưng chúng càng được sử dụng lâu, tỷ lệ cược mà nonce có thể bị bắt và sử dụng để chiếm quyền điều khiển phiên càng cao.

Một nhược điểm khác đối với nonces là rất khó để xây dựng một hệ thống sử dụng chúng và cho phép nhiều cửa sổ song song trên cùng một hình thức. ví dụ: người dùng mở hai cửa sổ trên một diễn đàn và bắt đầu làm việc trên hai bài đăng:

window 'A' loads first and gets nonce 'P'
window 'B' loads second and gets nonce 'Q'

Nếu bạn không có cách theo dõi nhiều cửa sổ, bạn sẽ chỉ lưu trữ một lần mở - đó là cửa sổ B / Q. Khi người dùng sau đó gửi bài đăng của họ từ cửa sổ A và chuyển qua 'P', hệ thống sẽ từ chối bài đăng dưới dạng P != Q.


Vì vậy, điều này có liên quan gì đến việc cố định phiên?
rook

2
Anh ta có một điểm hợp lệ, đặc biệt là trong lĩnh vực sử dụng đồng thời nhiều yêu cầu AJAX.
DanielG

2

Tôi không đọc bài viết của Shiflett, nhưng tôi nghĩ bạn đã hiểu nhầm điều gì đó.

Theo mặc định, PHP chuyển mã thông báo phiên trong URL bất cứ khi nào khách hàng không chấp nhận cookie. Ngoài ra, trong trường hợp phổ biến nhất, mã thông báo phiên được lưu trữ dưới dạng cookie.

Điều này có nghĩa là nếu bạn đặt mã thông báo phiên vào URL, PHP sẽ nhận ra nó và cố gắng sử dụng nó sau đó. Sửa lỗi phiên xảy ra khi ai đó tạo phiên và sau đó lừa người dùng khác chia sẻ cùng một phiên bằng cách mở URL chứa mã thông báo phiên. Nếu người dùng xác thực theo một cách nào đó, thì người dùng độc hại sẽ biết mã thông báo phiên của một người được xác thực, người có thể có các đặc quyền khác nhau.

Như tôi chắc chắn Shiflett giải thích, điều thường làm là tạo lại một mã thông báo khác nhau mỗi khi đặc quyền của người dùng thay đổi.


Để thêm vào điều này, vui lòng chắc chắn để hủy bất kỳ phiên nào đã mở trước đó vì chúng vẫn sẽ hợp lệ với các quyền của người dùng hiện có.
corrodedmonkee

0

Có, bạn có thể ngăn việc sửa phiên bằng cách tạo lại id phiên sau khi đăng nhập. Bằng cách này nếu kẻ tấn công sẽ không biết giá trị cookie của phiên mới được xác thực. Một cách tiếp cận khác hoàn toàn ngăn chặn vấn đề được đặt session.use_only_cookies=Truetrong cấu hình thời gian chạy của bạn. Kẻ tấn công không thể đặt giá trị của cookie trong bối cảnh của một tên miền khác. Việc sửa lỗi phiên dựa vào việc gửi giá trị cookie dưới dạng GET hoặc POST.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.