Dużo szukałem, a także przeczytałem dokumentację PHP $ _SERVER . Czy mam prawo do tego, których użyć w moich skryptach PHP do prostych definicji łączy używanych w mojej witrynie?
$_SERVER['SERVER_NAME']
opiera się na pliku konfiguracyjnym serwera WWW (w moim przypadku Apache2) i różni się w zależności od kilku dyrektyw: (1) VirtualHost, (2) ServerName, (3) UseCanonicalName itp.
$_SERVER['HTTP_HOST']
opiera się na żądaniu klienta.
Dlatego wydaje mi się, że właściwy byłby ten, którego należy użyć, aby moje skrypty były jak najbardziej kompatybilne $_SERVER['HTTP_HOST']
. Czy to założenie jest słuszne?
Uwagi uzupełniające:
Wydaje mi się, że po przeczytaniu tego artykułu dostałem trochę paranoi i zauważyłem, że niektórzy ludzie powiedzieli „nie ufaliby żadnemu z $_SERVER
vars”:
http://markjaquith.wordpress.com/2009/09/21/php-server-vars-not-safe-in-forms-or-links/
http://php.net/manual/en/reserved.variables.server.php#89567 (komentarz: Vladimir Kornea 14-Mar-2009 01:06)
Najwyraźniej dyskusja dotyczy głównie $_SERVER['PHP_SELF']
tego, dlaczego nie należy go używać w atrybucie działania formularza bez odpowiedniej ucieczki, aby zapobiec atakom XSS.
Mój wniosek dotyczący mojego pierwotnego pytania powyżej jest taki, że używanie $_SERVER['HTTP_HOST']
wszystkich linków w witrynie jest „bezpieczne” bez martwienia się o ataki XSS, nawet jeśli są używane w formularzach.
Proszę popraw mnie jeżeli się mylę.
$_SERVER['SERVER_NAME']
i$_SERVER['HTTP_HOST']
(oprócz implementacji innego niestandardowego uzgadniania na podstawie żądania użytkownika). Profesjonalni deweloperzy nie ufają rzeczom, których do końca nie rozumieją. Więc albo mają perfekcyjnie poprawną konfigurację SAPI (w takim przypadku opcja, której używają , da poprawny wynik), albo zrobią białą listę tak, że nie ma znaczenia, jakie wartości dostarcza SAPI.array_key_exists
jest bardziej skalowalny w porównaniu zin_array
wydajnością O (n).Tylko dodatkowa uwaga - jeśli serwer działa na porcie innym niż 80 (co może być powszechne na maszynie deweloperskiej / intranetowej), to
HTTP_HOST
zawiera port, aSERVER_NAME
nie.(Tak przynajmniej zauważyłem w virtualhostach opartych na portach Apache)
Jak Mike zauważył poniżej,
HTTP_HOST
czy nie zawierają:443
gdy działa na HTTPS (chyba że działa na niestandardowym porcie, które nie zostały przetestowane).źródło
HTTP_HOST
nie jest dokładnieHost:
parametrem podanym przez użytkownika. Opiera się tylko na tym.Użyj albo. Oba są jednakowo (nie) bezpieczne, ponieważ w wielu przypadkach SERVER_NAME i tak jest po prostu wstawiane z HTTP_HOST. Zwykle wybieram HTTP_HOST, więc użytkownik pozostaje przy dokładnej nazwie hosta, na którym zaczął. Na przykład, jeśli mam tę samą witrynę w domenach .com i .org, nie chcę wysyłać nikogo z .org na .com, szczególnie jeśli może mieć tokeny logowania na .org, które straciłby, gdyby został wysłany do inna domena.
Tak czy inaczej, po prostu musisz mieć pewność, że Twoja aplikacja internetowa będzie reagować tylko na znane, dobre domeny. Można to zrobić (a) za pomocą sprawdzenia po stronie aplikacji, takiego jak Gumbo, lub (b) za pomocą wirtualnego hosta w żądanych nazwach domen, który nie odpowiada na żądania, które zawierają nieznany nagłówek hosta.
Powodem tego jest to, że jeśli zezwolisz na dostęp do swojej witryny pod jakąkolwiek starą nazwą, narażasz się na ataki polegające na ponownym wiązaniu DNS (gdy nazwa hosta innej witryny wskazuje na Twój adres IP, użytkownik uzyskuje dostęp do Twojej witryny za pomocą nazwy hosta atakującego, a następnie nazwy hosta jest przenoszony na adres IP atakującego, zabierając ze sobą pliki cookie / uwierzytelnianie) i przechwytujący wyszukiwarkę (gdy atakujący wskazuje własną nazwę hosta w Twojej witrynie i próbuje sprawić, by wyszukiwarki postrzegały ją jako „najlepszą” podstawową nazwę hosta).
Pfft. Cóż, nie powinieneś używać niczego w żadnym atrybucie bez ucieczki z
htmlspecialchars($string, ENT_QUOTES)
, więc nie ma tam nic specjalnego w zmiennych serwerowych.źródło
attacker.com
jako najlepsze podstawowe źródło adresu IP Twojego serwera”? Wydaje się, że to nic nie znaczy dla wyszukiwarek. Co to w ogóle da?http://example.com/
,http://www.example.com/
ihttp://93.184.216.34/
byłoby połączyć je w jednym miejscu, wybrać najbardziej popularne adresy, a jedynie powrót linki do wersja. Gdybyś mógł wskazaćevil-example.com
ten sam adres i sprawić, by Google na krótko uznało go za bardziej popularny, możesz ukraść sok witryny. Nie wiem, jak praktyczne jest to dzisiaj, ale widziałem w przeszłości rosyjskie osoby atakujące farmy linków.To jest rozwlekłe tłumaczenie tego, czego używa Symfony do uzyskania nazwy hosta ( zobacz drugi przykład dla bardziej dosłownego tłumaczenia ):
Przestarzały:
Oto moje tłumaczenie na gołe PHP metody używanej we frameworku Symfony, która próbuje uzyskać nazwę hosta z każdego możliwego sposobu, w kolejności najlepszych praktyk:
źródło
if ($host = $_SERVER['HTTP_X_FORWARDED_HOST'])
lubx = a == 1 ? True : False
. Kiedy pierwszy raz to zobaczyłem, mój mózg szukał instancji $ hosta i odpowiedzi „dlaczego jest tylko jeden” = „znak?”. Zaczynam nie lubić słabych języków programowania. Wszystko jest inaczej napisane. Nie oszczędzasz czasu i nie jesteś wyjątkowy. Nie piszę kodu w ten sposób, ponieważ po jakimś czasie to ja muszę go debugować. Wygląda naprawdę niechlujnie jak na zmęczony mózg! Wiem, że mój angielski jest zagmatwany, ale przynajmniej próbuję.Tak, jest bezpieczny w użyciu
$_SERVER['HTTP_HOST']
(a nawet$_GET
i$_POST
), o ile zweryfikujesz je przed ich zaakceptowaniem. Oto, co robię dla bezpiecznych serwerów produkcyjnych:Zaletą
$_SERVER['HTTP_HOST']
jest to, że jego zachowanie jest lepiej zdefiniowane niż$_SERVER['SERVER_NAME']
. Kontrast ➫➫ :z:
Używanie lepiej zdefiniowanego interfejsu, takiego jak,
$_SERVER['HTTP_HOST']
oznacza, że więcej SAPI będzie go implementować przy użyciu niezawodnego, dobrze zdefiniowanego zachowania. (W przeciwieństwie do innych .) Jednak nadal jest całkowicie zależny od SAPI ➫➫ :Aby zrozumieć, jak prawidłowo pobrać nazwę hosta, przede wszystkim musisz zrozumieć, że serwer, który zawiera tylko kod, nie ma możliwości poznania (warunku wstępnego weryfikacji) własnej nazwy w sieci. Musi łączyć się z komponentem, który nadaje mu własną nazwę. Można to zrobić za pomocą:
lokalny plik konfiguracyjny
lokalna baza danych
zakodowany na stałe kod źródłowy
żądanie zewnętrzne ( curl )
Host:
żądanie klienta / napastnikaitp
Zwykle odbywa się to za pośrednictwem lokalnego pliku konfiguracyjnego (SAPI). Zwróć uwagę, że skonfigurowałeś go poprawnie, np. W Apache ➫➫ :
źródło
Główna różnica między nimi polega na tym, że
$_SERVER['SERVER_NAME']
jest to zmienna kontrolowana przez serwer, a$_SERVER['HTTP_HOST']
wartość kontrolowana przez użytkownika.Praktyczna zasada brzmi: nigdy nie ufaj wartościom użytkownika, więc
$_SERVER['SERVER_NAME']
jest to lepszy wybór.Jak wskazał Gumbo, Apache skonstruuje SERVER_NAME z wartości podanych przez użytkownika, jeśli tego nie ustawisz
UseCanonicalName On
.Edycja: Powiedziawszy to wszystko, jeśli witryna używa hosta wirtualnego opartego na nazwie, nagłówek HTTP Host jest jedynym sposobem na dotarcie do witryn, które nie są witryną domyślną.
źródło
Host:
chyba że już ją zweryfikowałeś , ręcznie lub przez konfigurację SAPI.Nie jestem pewien i nie ufam,
$_SERVER['HTTP_HOST']
ponieważ zależy to od nagłówka klienta. Z drugiej strony, jeśli domena żądana przez klienta nie jest moją domeną, nie dostaną się do mojej witryny, ponieważ DNS i protokół TCP / IP kierują ją do właściwego miejsca docelowego. Jednak nie wiem, czy można przejąć DNS, sieć, a nawet serwer Apache. Dla pewności definiuję nazwę hosta w środowisku i porównuję z$_SERVER['HTTP_HOST']
.Dodaj
SetEnv MyHost domain.com
plik .htaccess na root i dodaj ten kod do Common.phpDołączam ten plik Common.php do każdej strony php. Ta strona robi wszystko, co jest wymagane dla każdego żądania, na przykład
session_start()
modyfikuje plik cookie sesji i odrzuca, jeśli metoda wysyłania pochodzi z innej domeny.źródło
Host:
wartość bezpośrednio na adres IP twojego serwera.XSS
zawsze będzie tam nawet jeśli używasz$_SERVER['HTTP_HOST']
,$_SERVER['SERVER_NAME']
OR$_SERVER['PHP_SELF']
źródło
Najpierw chciałbym podziękować za wszystkie dobre odpowiedzi i wyjaśnienia. To jest metoda, którą stworzyłem na podstawie wszystkich twoich odpowiedzi, aby uzyskać podstawowy adres URL. Używam go tylko w bardzo rzadkich sytuacjach. Dlatego NIE kładzie się dużego nacisku na kwestie bezpieczeństwa, takie jak ataki XSS. Może ktoś tego potrzebuje.
źródło