TL; DR - bản sửa lỗi (mà bạn thậm chí không cần) là RẤT ĐƠN GIẢN và ở cuối câu trả lời này.
Tôi sẽ cố gắng giải quyết các câu hỏi cụ thể của bạn, nhưng sự hiểu lầm của bạn về PATH_INFO là gì khiến bản thân các câu hỏi hơi sai.
Câu hỏi đầu tiên phải là "Kinh doanh thông tin đường dẫn này là gì?"
Câu hỏi tiếp theo của bạn nên là: "Làm thế nào để PHP xác định cái gì PATH_INFO
và SCRIPT_FILENAME
là gì?"
- Các phiên bản trước của PHP là ngây thơ và về mặt kỹ thuật thậm chí không hỗ trợ
PATH_INFO
, do đó, những gì được cho là PATH_INFO
đã được đưa vào SCRIPT_FILENAME
, trong đó, bị hỏng trong nhiều trường hợp. Tôi không có phiên bản PHP đủ cũ để thử nghiệm, nhưng tôi tin rằng nó đã thấy SCRIPT_FILENAME
toàn bộ shebang: "/path/to/script.php/THIS/IS/PATH/INFO" trong ví dụ trên (có tiền tố là các docroot như bình thường).
- Với cgi.fix_pathinfo được bật, PHP bây giờ tìm thấy chính xác "/ NÀY / IS / PATH / INFO" cho ví dụ trên và đặt nó vào
PATH_INFO
và SCRIPT_FILENAME
chỉ lấy phần được chỉ ra cho tập lệnh được yêu cầu (dĩ nhiên là tiền tố với docroot).
- Lưu ý: khi PHP thực sự hỗ trợ
PATH_INFO
, họ phải thêm cài đặt cấu hình cho tính năng mới để mọi người chạy các tập lệnh phụ thuộc vào hành vi cũ có thể chạy các phiên bản PHP mới. Đó là lý do tại sao thậm chí có một công tắc cấu hình cho nó. Nó nên được tích hợp sẵn (với hành vi "nguy hiểm") ngay từ đầu.
Nhưng làm thế nào để PHP biết phần nào là tập lệnh và thông tin đường dẫn của nó là gì? Điều gì xảy ra nếu URI giống như:
http://example.com/path/to/script.php/THIS/IS/PATH/INFO.php?q=foo
- Đó có thể là một câu hỏi phức tạp trong một số môi trường. Điều xảy ra trong PHP là nó tìm thấy phần đầu tiên của đường dẫn URI không tương ứng với bất cứ thứ gì trong docroot của máy chủ. Trong ví dụ này, nó thấy rằng trên máy chủ của bạn, bạn không có "/docroot/path/to/script.php/THIS" nhưng bạn chắc chắn có "/docroot/path/to/script.php" vì vậy bây giờ
SCRIPT_FILENAME
đã được xác định và PATH_INFO
nhận phần còn lại.
- Vì vậy, bây giờ ví dụ điển hình về sự nguy hiểm được chi tiết độc đáo trong các tài liệu Nginx và trong câu trả lời của Hrvoje Špoljar (bạn không thể cầu kỳ về một ví dụ rõ ràng như vậy) càng trở nên rõ ràng hơn: ví dụ của Hrvoje (ví dụ http: //. com / foo.jpg / nonexistent.php "), PHP thấy một tệp trên docroot của bạn" /foo.jpg "nhưng nó không thấy bất cứ thứ gì gọi là" /foo.jpg/nonexistent.php "vì vậy
SCRIPT_FILENAME
được" /foo.jpg " (một lần nữa, tiền tố với docroot) và PATH_INFO
được "/nonexistent.php".
Tại sao và làm thế nào nó có thể nguy hiểm bây giờ nên rõ ràng:
- Máy chủ web thực sự không có lỗi - nó chỉ đơn thuần là ủy quyền URI cho PHP, mà vô tình thấy rằng "foo.jpg" thực sự có chứa nội dung PHP, vì vậy nó thực thi nó (bây giờ bạn đã bị xóa!). Điều này KHÔNG đặc biệt đối với Nginx mỗi se.
- Các REAL vấn đề là bạn hãy để nội dung không tin cậy được tải lên ở đâu đó mà không vệ sinh và bạn cho phép các yêu cầu tùy ý khác để cùng một vị trí, mà PHP vui vẻ thực hiện khi nó có thể.
Nginx và Apache có thể được xây dựng hoặc định cấu hình để ngăn chặn các yêu cầu sử dụng mánh khóe này và có rất nhiều ví dụ về cách thực hiện điều đó, bao gồm cả câu trả lời của user2372674 . Bài viết blog này giải thích vấn đề độc đáo, nhưng nó thiếu giải pháp đúng.
Tuy nhiên, giải pháp tốt nhất là chỉ cần đảm bảo PHP-FPM được cấu hình đúng để nó sẽ không bao giờ thực thi một tệp trừ khi kết thúc bằng ".php". Điều đáng chú ý là các phiên bản gần đây của PHP-FPM (~ 5.3.9 +?) Có mặc định này, vì vậy mối nguy hiểm này không còn là vấn đề nữa.
Giải pháp
Nếu bạn có phiên bản PHP-FPM gần đây (~ 5.3.9 +?), Thì bạn không cần phải làm gì, vì hành vi an toàn dưới đây đã là mặc định.
Mặt khác, tìm www.conf
tệp của php-fpm (có thể /etc/php-fpm.d/www.conf
, tùy thuộc vào hệ thống của bạn). Hãy chắc chắn rằng bạn có điều này:
security.limit_extensions = .php
Một lần nữa, đó là mặc định ở nhiều nơi trong những ngày này.
Lưu ý rằng điều này không ngăn kẻ tấn công tải lên tệp ".php" vào thư mục tải lên WordPress và thực hiện bằng cách sử dụng cùng một kỹ thuật. Bạn vẫn cần phải có bảo mật tốt cho các ứng dụng của bạn.