Biến $ _SERVER nào là an toàn?


97

Bất kỳ biến nào mà người dùng có thể kiểm soát, kẻ tấn công cũng có thể kiểm soát và do đó là nguồn của một cuộc tấn công. Đây được gọi là biến "nhiễm bẩn" và không an toàn.

Khi sử dụng $_SERVER, nhiều biến có thể được kiểm soát. PHP_SELF, HTTP_USER_AGENT, HTTP_X_FORWARDED_FOR, HTTP_ACCEPT_LANGUAGEVà nhiều người khác là một phần của tiêu đề yêu cầu HTTP gửi của khách hàng.

Có ai biết về một "danh sách an toàn" hoặc danh sách các $_SERVERbiến chưa được quét không ?


8
Phụ thuộc vào cách bạn định nghĩa "an toàn". Tất cả các giá trị đều an toàn như chúng vốn có, nó chỉ phụ thuộc vào việc bạn sử dụng chúng để làm gì.
lừa đảo

6
Tôi nghĩ trong bối cảnh này, Rook đang nói "Người dùng không thể giả mạo biến máy chủ nào", chẳng hạn như REMOTE_ADDR.
vcsjones

6
Bất kỳ thứ gì mở đầu bằng HTTP_là một tiêu đề yêu cầu và có thể được đặt bởi trình duyệt hoặc proxy ở giữa. Tôi sẽ coi đó là bất kỳ đầu vào nào khác của người dùng.
dữ liệu

3
@ bob-the-Dester-REMOTE_ADDR được lấy trực tiếp từ ổ cắm TCP của apache, giá trị này không thể bị giả mạo qua Internet do bắt tay ba cách.
rook

2
@Rook: điểm tốt. Tôi đoán rằng với việc đề cập đến "giả mạo", tôi đã nghiêng về hành động cũ là giả mạo ip, hơn là bất kỳ hình thức giả mạo giá trị thực tế nào REMOTE_ADDR. Và điều đó sẽ nằm ngoài phạm vi của câu hỏi này. Rất tốt để có được một số thông tin chi tiết về cách đặt giá trị này, vì vậy cảm ơn.
bob-the-khu trục

Câu trả lời:


147

Không có cái gọi là giá trị "an toàn" hoặc "không an toàn" như vậy. Chỉ có các giá trị mà máy chủ kiểm soát và các giá trị mà người dùng kiểm soát và bạn cần biết giá trị đến từ đâu và do đó liệu nó có thể được tin cậy cho một mục đích nhất định hay không. $_SERVER['HTTP_FOOBAR']ví dụ: hoàn toàn an toàn để lưu trữ trong cơ sở dữ liệu, nhưng tôi chắc chắn sẽ không eval.

Như vậy, hãy chia các giá trị đó thành ba loại:

Máy chủ kiểm soát

Các biến này được thiết lập bởi môi trường máy chủ và phụ thuộc hoàn toàn vào cấu hình máy chủ.

  • 'GATEWAY_INTERFACE'
  • 'SERVER_ADDR'
  • 'SERVER_SOFTWARE'
  • 'DOCUMENT_ROOT'
  • 'SERVER_ADMIN'
  • 'SERVER_SIGNATURE'

Máy chủ được kiểm soát một phần

Các biến này phụ thuộc vào yêu cầu cụ thể mà khách hàng đã gửi, nhưng chỉ có thể nhận một số giá trị hợp lệ giới hạn, vì tất cả các giá trị không hợp lệ sẽ bị máy chủ web từ chối và không khiến lệnh bắt đầu của tập lệnh. Do đó chúng có thể được coi là đáng tin cậy .

  • 'HTTPS'
  • 'REQUEST_TIME'
  • 'REMOTE_ADDR' *
  • 'REMOTE_HOST' *
  • 'REMOTE_PORT' *
  • 'SERVER_PROTOCOL'
  • 'HTTP_HOST'
  • 'SERVER_NAME'
  • 'SCRIPT_FILENAME'
  • 'SERVER_PORT'
  • 'SCRIPT_NAME'

* Các REMOTE_giá trị được đảm bảo là địa chỉ hợp lệ của ứng dụng khách, như được xác minh bằng bắt tay TCP / IP. Đây là địa chỉ mà mọi phản hồi sẽ được gửi đến. REMOTE_HOSTTuy nhiên, dựa vào tra cứu DNS ngược và do đó có thể bị giả mạo bởi các cuộc tấn công DNS vào máy chủ của bạn (trong trường hợp đó, bạn vẫn gặp sự cố lớn hơn). Giá trị này có thể là một proxy, đây là một thực tế đơn giản của giao thức TCP / IP và bạn không thể làm gì cả.

† Nếu máy chủ web của bạn phản hồi bất kỳ yêu cầu nào bất kể HOSTtiêu đề, điều này cũng nên được coi là không an toàn. Xem $ _SERVER [“HTTP_HOST”] an toàn như thế nào? .
Cũng xem http://shiflett.org/blog/2006/mar/server-name-versus-http-host .

‡ Xem https://bugs.php.net/bug.php?id=64457 , http://httpd.apache.org/docs/current/mod/core.html#usecanonicalphysicalport , http://httpd.apache. org / docs / 2.4 / mod / core.html # comment_999

Các giá trị do người dùng kiểm soát hoàn toàn tùy ý

Các giá trị này hoàn toàn không được kiểm tra và không phụ thuộc vào bất kỳ cấu hình máy chủ nào, chúng hoàn toàn là thông tin tùy ý do máy khách gửi.

  • 'argv', 'argc'(chỉ áp dụng cho lệnh gọi CLI, thường không phải là mối quan tâm đối với máy chủ web)
  • 'REQUEST_METHOD' §
  • 'QUERY_STRING'
  • 'HTTP_ACCEPT'
  • 'HTTP_ACCEPT_CHARSET'
  • 'HTTP_ACCEPT_ENCODING'
  • 'HTTP_ACCEPT_LANGUAGE'
  • 'HTTP_CONNECTION'
  • 'HTTP_REFERER'
  • 'HTTP_USER_AGENT'
  • 'AUTH_TYPE'
  • 'PHP_AUTH_DIGEST'
  • 'PHP_AUTH_USER'
  • 'PHP_AUTH_PW'
  • 'PATH_INFO'
  • 'ORIG_PATH_INFO'
  • 'REQUEST_URI' (có thể chứa dữ liệu bị ô nhiễm)
  • 'PHP_SELF' (có thể chứa dữ liệu bị ô nhiễm)
  • 'PATH_TRANSLATED'
  • bất kỳ 'HTTP_'giá trị nào khác

§ Có thể được coi là đáng tin cậy miễn là máy chủ web chỉ cho phép một số phương thức yêu cầu nhất định.

‖ Có thể được coi là đáng tin cậy nếu quá trình xác thực được xử lý hoàn toàn bởi máy chủ web.

Siêu cầu $_SERVERcũng bao gồm một số biến môi trường. Những điều này có "an toàn" hay không phụ thuộc vào cách (và vị trí) chúng được xác định. Chúng có thể bao gồm từ hoàn toàn do máy chủ kiểm soát đến hoàn toàn do người dùng kiểm soát.


3
@Rook Nhưng như tôi đã nói, nó hoàn toàn phụ thuộc vào cách bạn sử dụng nó . Bản thân các giá trị không an toàn hay không an toàn, nó phụ thuộc vào việc bạn sử dụng chúng để làm gì . Ngay cả dữ liệu được gửi từ một người dùng bất chính cũng hoàn toàn an toàn miễn là bạn không làm bất cứ điều gì có thể ảnh hưởng đến bảo mật của bạn.
dối trá

2
@Rook: ý tưởng "an toàn" của bạn khiến câu hỏi này có vẻ hơi tùy tiện, đặc biệt là vì nó hoàn toàn gắn liền với một tiện ích mở rộng hoặc phiên bản tùy chỉnh của PHP. Trong khi bạn nói "không nên có cách tiếp cận" bắn từ hông "", bất kỳ câu trả lời nào thực sự dường như yêu cầu sự quen thuộc tối thiểu với mã nguồn PHP để tìm hiểu cách các giá trị này được đặt. Gửi email cho các nhà phát triển PHP không phải là một cách tiếp cận tốt hơn để tìm câu trả lời?
bob-the-khu trục

2
@Rook: Thông tin sai lệch. Như lừa dối đã gợi ý, "an toàn cho mục đích gì". Như tôi đã gợi ý, mục đích của bạn là không xác định và bên cạnh đó có một số $_SERVERgiá trị không có tài liệu khác tùy thuộc vào cách tệp được phân phát. Theo tôi, những tài liệu không làm rõ nguồn gốc thực sự. Nếu không, tôi tin rằng bạn sẽ không hỏi câu hỏi này. Rất vui khi bạn có một danh sách mà bạn có thể sử dụng. Nhưng tôi vẫn khuyên bạn nên gửi báo cáo lỗi (khi trang web lỗi của họ được sửa), gửi email cho người bảo trì tài liệu hoặc tự cập nhật tài liệu (nếu bạn biết liên kết). Nó sẽ có lợi cho cộng đồng khi biết thông tin này.
bob-the-

3
SERVER_NAMEkhông nhất thiết phải được kiểm soát bởi máy chủ. Tùy thuộc vào cổng và cài đặt, nó có thể được sao chép từ HTTP_HOSTvà do đó phải chịu cùng một cảnh báo.
bobince

1
@deceze @Rook Có SERVER_PORTcần dấu thập nhỏ đó không? bug.php.net/bug.php?id=64457
Dejan Marjanović

12

Trong PHP, mọi $_SERVERbiến bắt đầu bằng HTTP_có thể bị ảnh hưởng bởi người dùng. Ví dụ: biến $_SERVER['HTTP_REINERS']có thể bị nhiễm bẩn bằng cách đặt tiêu đề HTTP REINERSthành một giá trị tùy ý trong yêu cầu HTTP.


lại "tùy tiện"; Không hoàn toàn tùy ý vì chúng tuân theo một định dạng. Ví dụ: $_SERVER['HTTP_REINERS'] không được chứa các ký tự dòng mới dưới hầu hết các sapis.
Pacerier
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.