Które zmienne $ _SERVER są bezpieczne?

97

Osoba atakująca może również kontrolować każdą zmienną, którą może kontrolować użytkownik, a zatem jest ona źródłem ataku. Nazywa się to zmienną „skażoną” i jest niebezpieczna.

Podczas używania $_SERVERmożna kontrolować wiele zmiennych. PHP_SELF, HTTP_USER_AGENT, HTTP_X_FORWARDED_FOR, HTTP_ACCEPT_LANGUAGEI wielu innych, są częścią nagłówka żądania HTTP wysłanego przez klienta.

Czy ktoś zna „bezpieczną listę” lub nieskażoną listę $_SERVERzmiennych?

wieża
źródło
8
Zależy od tego, jak zdefiniujesz „bezpieczny”. Wszystkie wartości są bezpieczne i zależy tylko od tego, do czego ich użyjesz.
deceze
6
Myślę, że w tym kontekście Rook mówi „Które zmienne serwera nie mogą być sfałszowane przez użytkownika”, na przykład REMOTE_ADDR.
vcsjones
6
Wszystko poprzedzone HTTP_jest nagłówkiem żądania i może być ustawione przez przeglądarkę lub serwer proxy pomiędzy. Uznałbym je za każde inne wejście użytkownika.
datasage
3
@ bob-the-destruer REMOTE_ADDR jest pobierany bezpośrednio z gniazda TCP Apache, tej wartości nie można sfałszować przez Internet z powodu potrójnego uzgadniania.
wieża
2
@Rook: słuszna uwaga. Wydaje mi się, że ze wzmianką o „spoofing” bardziej skłaniałem się ku staremu aktowi polegającemu na fałszowaniu samego adresu IP niż na jakimkolwiek fałszowaniu rzeczywistej wartości REMOTE_ADDR. I to byłoby poza zakresem tego pytania. Dobrze jest jednak uzyskać wgląd w sposób ustawiania tej wartości, więc dziękuję.
bob-the-

Odpowiedzi:

147

Nie ma czegoś takiego jak „bezpieczne” lub „niebezpieczne” wartości jako takie. Istnieją tylko wartości, które kontroluje serwer i wartości, które kontroluje użytkownik, i musisz być świadomy, skąd pochodzi wartość, a zatem czy można jej ufać w określonym celu. $_SERVER['HTTP_FOOBAR']na przykład jest całkowicie bezpieczny do przechowywania w bazie danych, ale z całą pewnością nie byłoby to evalmożliwe.

W związku z tym podzielmy te wartości na trzy kategorie:

Kontrolowany przez serwer

Te zmienne są ustawiane przez środowisko serwera i zależą całkowicie od konfiguracji serwera.

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

Częściowo kontrolowane przez serwer

Te zmienne zależą od konkretnego żądania wysłanego przez klienta, ale mogą przyjmować tylko ograniczoną liczbę prawidłowych wartości, ponieważ wszystkie nieprawidłowe wartości powinny zostać odrzucone przez serwer sieciowy i nie powodować rozpoczęcia wywołania skryptu. Dlatego można je uznać za wiarygodne .

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

* Podane REMOTE_wartości to prawidłowy adres klienta, zweryfikowany przez uzgadnianie TCP / IP. Jest to adres, na który zostanie wysłana odpowiedź. REMOTE_HOSTpolega jednak na odwrotnym wyszukiwaniu DNS i dlatego może zostać sfałszowany przez ataki DNS na twój serwer (w takim przypadku i tak masz większe problemy). Ta wartość może być proxy, co jest prostą rzeczywistością protokołu TCP / IP i nic nie można na to poradzić.

† Jeśli serwer sieciowy odpowiada na jakiekolwiek żądanie niezależnie od HOSTnagłówka, również powinno to być uznane za niebezpieczne. Zobacz Jak bezpieczny jest serwer $ _SERVER [„HTTP_HOST”]? .
Zobacz także http://shiflett.org/blog/2006/mar/server-name-versus-http-host .

‡ Zobacz 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

Całkowicie dowolne wartości kontrolowane przez użytkownika

Wartości te w ogóle nie są sprawdzane i nie zależą od konfiguracji serwera, są to całkowicie dowolne informacje przesłane przez klienta.

  • 'argv', 'argc'(dotyczy tylko wywołania CLI, zwykle nie dotyczy serwerów WWW)
  • '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' (może zawierać skażone dane)
  • 'PHP_SELF' (może zawierać skażone dane)
  • 'PATH_TRANSLATED'
  • każda inna 'HTTP_'wartość

§ Może być uważany za wiarygodny, o ile serwer sieciowy dopuszcza tylko niektóre metody żądań.

‖ Można uznać, że jest wiarygodne, jeśli uwierzytelnianie jest całkowicie obsługiwane przez serwer WWW.

Superglobal $_SERVERzawiera również kilka zmiennych środowiskowych. To, czy są one „bezpieczne”, czy nie, zależy od tego, jak (i ​​gdzie) zostały zdefiniowane. Mogą się one wahać od całkowicie kontrolowanych przez serwer do całkowicie kontrolowanych przez użytkownika.

zamrozić
źródło
3
@Rook Ale jak powiedziałem, to absolutnie zależy od tego, jak go używasz . Wartości same w sobie nie są ani bezpieczne, ani niebezpieczne, zależy to od tego, do czego je wykorzystasz . Nawet dane wysłane od nikczemnego użytkownika są całkowicie bezpieczne, o ile nie robisz z nimi nic, co mogłoby zagrozić Twojemu bezpieczeństwu.
deceze
2
@Rook: Twój pomysł na „bezpieczny” sprawia, że ​​to pytanie wydaje się nieco arbitralne, zwłaszcza, że ​​jest ono całkowicie powiązane z mało znanym rozszerzeniem lub niestandardową wersją PHP. Chociaż mówisz "nie powinno się" strzelać z biodra ", każda odpowiedź w rzeczywistości wydaje się wymagać przynajmniej znajomości kodu źródłowego PHP, aby dowiedzieć się, jak te wartości są ustawiane. Czy wysyłanie e-maili do programistów PHP nie byłoby lepszym sposobem na znalezienie odpowiedzi?
bob-the-
2
@Rook: Nieporozumienie. Jak zasugerował mróz, „bezpieczny w jakim celu”. Jak już wspomniałem, twój cel jest nieznany, a poza tym istnieje kilka innych nieudokumentowanych $_SERVERwartości w zależności od tego, jak plik jest obsługiwany. Moim zdaniem udokumentowane nie wyjaśniają prawdziwego źródła. W przeciwnym razie myślę, że nie zadałbyś tego pytania. Cieszę się, że masz listę, z której możesz skorzystać. Ale nadal sugerowałbym przesłanie raportu o błędzie (gdy ich witryna z błędami została naprawiona), wysłanie do opiekunów dokumentów e-maili lub samodzielne zaktualizowanie dokumentów (jeśli znasz link). Znajomość tych informacji przyniosłaby korzyści społeczności.
bob-the-
3
SERVER_NAMEniekoniecznie jest kontrolowane przez serwer. W zależności od bramy i ustawień może on być kopiowany HTTP_HOSTi podlegać temu samemu zastrzeżeniu.
bobince
1
@deceze @Rook Czy SERVER_PORTpotrzebujesz tego małego krzyża? bugs.php.net/bug.php?id=64457
Dejan Marjanović
12

W PHP na każdą $_SERVERzmienną zaczynającą się od HTTP_może mieć wpływ użytkownik. Na przykład zmienna $_SERVER['HTTP_REINERS']może zostać skażona przez ustawienie nagłówka HTTP REINERSna dowolną wartość w żądaniu HTTP.

Reiners
źródło
ponownie „arbitralny”; Nie całkowicie arbitralne, ponieważ są zgodne z formatem. Na przykład $_SERVER['HTTP_REINERS'] nie może zawierać znaków nowej linii w większości sapi.
Pacerier