PHP $ _SERVER [ 'HTTP_HOST'] 대 $ _SERVER [ 'SERVER_NAME'], 맨 페이지를 제대로 이해하고 있습니까?
PHPPHP $ _SERVER [ 'HTTP_HOST'] 대 $ _SERVER [ 'SERVER_NAME'], 맨 페이지를 제대로 이해하고 있습니까?
나는 많은 검색을했고 PHP $ _SERVER 문서도 읽었습니다. 내 사이트 전체에서 사용되는 간단한 링크 정의를 위해 PHP 스크립트에 사용할 권한과 관련하여이 권리가 있습니까?
$ _SERVER [ 'SERVER_NAME']은 웹 서버의 구성 파일 (제 경우에는 Apache2)을 기반으로하며, (1) VirtualHost, (2) ServerName, (3) UseCanonicalName 등 몇 가지 지시문에 따라 다릅니다.
$ _SERVER [ 'HTTP_HOST']는 클라이언트의 요청을 기반으로합니다.
그러므로 가능한 한 내 스크립트를 호환 가능하게 만드는 데 사용할 적절한 것이 $ _SERVER [ 'HTTP_HOST'] 일 것입니다. 이 가정이 맞습니까?
추가 답변 :
나는이 기사를 읽은 다음 약간의 사람들이 "$ _SERVER vars 중 어떤 것도 믿지 않을 것"이라고 말한 후 조금 편집증 적이라고 생각합니다.
분명히 토론은 주로 $ _SERVER [ 'PHP_SELF']에 대한 것이고 XSS 공격을 막기위한 적절한 이스케이프 처리가없는 경우 양식 활동 속성에서 사용해서는 안되는 이유입니다.
위의 원래 질문에 대한 내 결론은 양식에서 사용되는 경우에도 XSS 공격에 대해 걱정할 필요없이 사이트의 모든 링크에 $ _SERVER [ 'HTTP_HOST']를 사용하는 것이 "안전"하다는 것입니다.
내가 틀렸다면 나를 바로 잡아주세요.
해결법
-
==============================
1.아마 모두가 처음 생각합니다. 그러나 조금 더 어려워. Chris Shiflett의 SERVER_NAME 대 HTTP_HOST 문서를 참조하십시오.
아마 모두가 처음 생각합니다. 그러나 조금 더 어려워. Chris Shiflett의 SERVER_NAME 대 HTTP_HOST 문서를 참조하십시오.
은색 총알이없는 것 같습니다. Apache가 정식 이름을 사용하도록 강제 할 때만 SERVER_NAME을 사용하여 항상 올바른 서버 이름을 얻습니다.
따라서 여러분은 그걸 가지고 가거나 호스트 명을 화이트리스트와 대조해보아야합니다 :
$allowed_hosts = array('foo.example.com', 'bar.example.com'); if (!isset($_SERVER['HTTP_HOST']) || !in_array($_SERVER['HTTP_HOST'], $allowed_hosts)) { header($_SERVER['SERVER_PROTOCOL'].' 400 Bad Request'); exit; }
-
==============================
2.추가 참고 사항 - 서버가 80 이외의 포트에서 실행되는 경우 (개발 / 인트라넷 시스템에서 일반적 일 수 있음) HTTP_HOST에는 포트가 포함되지만 SERVER_NAME에는 포트가 포함되지 않습니다.
추가 참고 사항 - 서버가 80 이외의 포트에서 실행되는 경우 (개발 / 인트라넷 시스템에서 일반적 일 수 있음) HTTP_HOST에는 포트가 포함되지만 SERVER_NAME에는 포트가 포함되지 않습니다.
$_SERVER['HTTP_HOST'] == 'localhost:8080' $_SERVER['SERVER_NAME'] == 'localhost'
(적어도 아파치 포트 기반의 가상 호스트에서 발견 한 것입니다)
Mike가 아래에서 언급했듯이 HTTP_HOST에는 HTTPS를 실행할 때 443 개가 포함되지 않습니다 (테스트하지 않은 비표준 포트에서 실행중인 경우 제외).
-
==============================
3.symfony가 호스트 이름을 얻기 위해 사용하는 것을 상세하게 번역 한 것입니다 (보다 직역적인 번역을위한 두 번째 예제 참조).
symfony가 호스트 이름을 얻기 위해 사용하는 것을 상세하게 번역 한 것입니다 (보다 직역적인 번역을위한 두 번째 예제 참조).
function getHost() { $possibleHostSources = array('HTTP_X_FORWARDED_HOST', 'HTTP_HOST', 'SERVER_NAME', 'SERVER_ADDR'); $sourceTransformations = array( "HTTP_X_FORWARDED_HOST" => function($value) { $elements = explode(',', $value); return trim(end($elements)); } ); $host = ''; foreach ($possibleHostSources as $source) { if (!empty($host)) break; if (empty($_SERVER[$source])) continue; $host = $_SERVER[$source]; if (array_key_exists($source, $sourceTransformations)) { $host = $sourceTransformations[$source]($host); } } // Remove port number from host $host = preg_replace('/:\d+$/', '', $host); return trim($host); }
구식 :
이것은 Symfony 프레임 워크에서 사용되는 최선의 방법으로 가능한 한 모든 방법으로 호스트 이름을 얻으려고 시도하는 방법을 PHP로 번역 한 것입니다.
function get_host() { if ($host = $_SERVER['HTTP_X_FORWARDED_HOST']) { $elements = explode(',', $host); $host = trim(end($elements)); } else { if (!$host = $_SERVER['HTTP_HOST']) { if (!$host = $_SERVER['SERVER_NAME']) { $host = !empty($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : ''; } } } // Remove port number from host $host = preg_replace('/:\d+$/', '', $host); return trim($host); }
-
==============================
4.둘 중 하나를 사용하십시오. 어쨌든 SERVER_NAME은 HTTP_HOST에서 채워지는 경우가 많으므로 둘 다 똑같이 안전합니다. 나는 일반적으로 HTTP_HOST를 사용하여 사용자가 시작한 정확한 호스트 이름을 유지합니다. 예를 들어 .com 및 .org 도메인에 동일한 사이트가있는 경우 .org에서 .com으로 다른 사람을 보내지 않으려 고합니다. 특히 .org에 로그인 토큰이 있으면 다른 도메인.
둘 중 하나를 사용하십시오. 어쨌든 SERVER_NAME은 HTTP_HOST에서 채워지는 경우가 많으므로 둘 다 똑같이 안전합니다. 나는 일반적으로 HTTP_HOST를 사용하여 사용자가 시작한 정확한 호스트 이름을 유지합니다. 예를 들어 .com 및 .org 도메인에 동일한 사이트가있는 경우 .org에서 .com으로 다른 사람을 보내지 않으려 고합니다. 특히 .org에 로그인 토큰이 있으면 다른 도메인.
어쨌든, 당신은 단지 당신의 webapp이 잘 알려진 도메인에 대해서만 응답 할 수 있도록 할 필요가 있습니다. 이것은 (a) Gumbo와 같은 응용 프로그램 쪽 검사를 통해 또는 (b) 알 수없는 호스트 헤더를 제공하는 요청에 응답하지 않는 원하는 도메인 이름에 가상 호스트를 사용하여 수행 할 수 있습니다.
그 이유는 이전 이름으로 사이트에 액세스하도록 허용하면 DNS 리바운드 공격 (다른 사이트의 호스트 이름이 IP를 가리키고 사용자가 공격자의 호스트 이름으로 사이트에 액세스 한 다음 호스트 이름 공격자의 IP로 이동하여 쿠키 / 승인) 및 검색 엔진 하이재킹 (공격자가 자신의 사이트에서 자신의 호스트 이름을 가리키고 검색 엔진이이를 '최상의'기본 호스트 이름으로 간주하도록 시도)을 수행합니다.
Pfft. 뭐, htmlspecialchars ($ string, ENT_QUOTES)로 이스케이프하지 않으면 어떤 속성에서도 사용할 수 없으므로 서버 변수에 특별한 것은 없습니다.
-
==============================
5.이 둘의 주요 차이점은 $ _SERVER [ 'SERVER_NAME']은 서버 제어 변수이고 $ _SERVER [ 'HTTP_HOST']는 사용자가 제어하는 값이라는 것입니다.
이 둘의 주요 차이점은 $ _SERVER [ 'SERVER_NAME']은 서버 제어 변수이고 $ _SERVER [ 'HTTP_HOST']는 사용자가 제어하는 값이라는 것입니다.
엄지 손가락의 규칙은 사용자의 값을 결코 신뢰하지 않는 것이므로 $ _SERVER [ 'SERVER_NAME']이 (가) 더 나은 선택입니다.
Gumbo가 지적했듯이, UseCanonicalName을 On으로 설정하지 않으면 Apache는 SERVER_NAME을 사용자 제공 값으로 구성합니다.
편집 : 모든 사이트의 이름 기반 가상 호스트를 사용하는 경우, HTTP 호스트 헤더가 기본 사이트가 아닌 사이트에 도달하는 유일한 방법입니다.
-
==============================
6.예, 승인하기 전에 $ _SERVER [ 'HTTP_HOST'] (그리고 심지어 $ _GET 및 $ _POST)를 사용하는 것이 안전합니다. 이것이 안전한 프로덕션 서버를 위해 내가하는 일입니다.
예, 승인하기 전에 $ _SERVER [ 'HTTP_HOST'] (그리고 심지어 $ _GET 및 $ _POST)를 사용하는 것이 안전합니다. 이것이 안전한 프로덕션 서버를 위해 내가하는 일입니다.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ $reject_request = true; if(array_key_exists('HTTP_HOST', $_SERVER)){ $host_name = $_SERVER['HTTP_HOST']; // [ need to cater for `host:port` since some "buggy" SAPI(s) have been known to return the port too, see http://goo.gl/bFrbCO $strpos = strpos($host_name, ':'); if($strpos !== false){ $host_name = substr($host_name, $strpos); } // ] // [ for dynamic verification, replace this chunk with db/file/curl queries $reject_request = !array_key_exists($host_name, array( 'a.com' => null, 'a.a.com' => null, 'b.com' => null, 'b.b.com' => null )); // ] } if($reject_request){ // log errors // display errors (optional) exit; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ echo 'Hello World!'; // ...
$ _SERVER [ 'HTTP_HOST']의 장점은 $ _SERVER [ 'SERVER_NAME']보다 동작이 잘 정의되어 있다는 것입니다. 콘트라스트 ➫➫ :
와:
$ _SERVER [ 'HTTP_HOST']와 같이 정의 된 인터페이스를 사용하면 더 많은 SAPI가 신뢰할 수있는 잘 정의 된 동작을 사용하여 SAPI를 구현합니다. (다른 것과는 달리.) 그러나 SAPI는 전적으로 SAPI에 의존합니다.
호스트 이름을 올바르게 검색하는 방법을 이해하려면 먼저 코드 만 포함 된 서버가 네트워크에서 자신의 이름을 알 수있는 (사전 검증 필요) 방법이 없음을 이해해야합니다. 자체 이름을 제공하는 구성 요소와 인터페이스해야합니다. 다음을 통해이 작업을 수행 할 수 있습니다.
일반적으로 로컬 (SAPI) 구성 파일을 통해 수행됩니다. 올바르게 구성했는지 확인하십시오 (예 : 아파치 ➫➫ :
-
==============================
7.$ _SERVER [ 'HTTP_HOST']는 클라이언트의 헤더에 따라 다르므로 잘 모르겠습니다. 다른 방법으로 클라이언트가 요청한 도메인이 내 도메인이 아니라면 DNS와 TCP / IP 프로토콜이 올바른 대상을 가리 키기 때문에 내 사이트에 들어 가지 않습니다. 그러나 DNS, 네트워크 또는 Apache 서버를 납치 할 수 있는지 여부는 알 수 없습니다. 안전을 기하기 위해 환경에 호스트 이름을 정의하고이를 $ _SERVER [ 'HTTP_HOST']와 비교합니다.
$ _SERVER [ 'HTTP_HOST']는 클라이언트의 헤더에 따라 다르므로 잘 모르겠습니다. 다른 방법으로 클라이언트가 요청한 도메인이 내 도메인이 아니라면 DNS와 TCP / IP 프로토콜이 올바른 대상을 가리 키기 때문에 내 사이트에 들어 가지 않습니다. 그러나 DNS, 네트워크 또는 Apache 서버를 납치 할 수 있는지 여부는 알 수 없습니다. 안전을 기하기 위해 환경에 호스트 이름을 정의하고이를 $ _SERVER [ 'HTTP_HOST']와 비교합니다.
SetEnv MyHost domain.com을 루트의 .htaccess 파일에 추가하고 Common.php에 ths 코드를 추가하십시오.
if (getenv('MyHost')!=$_SERVER['HTTP_HOST']) { header($_SERVER['SERVER_PROTOCOL'].' 400 Bad Request'); exit(); }
나는이 Common.php 파일을 모든 PHP 페이지에 포함시켰다. 이 페이지는 session_start ()와 같은 각 요청에 필요한 모든 작업을 수행하며 세션 쿠키를 수정하고 post 메소드가 다른 도메인에서 온 경우 거부합니다.
-
==============================
8.XSS는 $ _SERVER [ 'HTTP_HOST'], $ _SERVER [ 'SERVER_NAME'] 또는 $ _SERVER [ 'PHP_SELF']를 사용하더라도 항상 존재합니다.
XSS는 $ _SERVER [ 'HTTP_HOST'], $ _SERVER [ 'SERVER_NAME'] 또는 $ _SERVER [ 'PHP_SELF']를 사용하더라도 항상 존재합니다.
from https://stackoverflow.com/questions/1459739/php-serverhttp-host-vs-serverserver-name-am-i-understanding-the-ma by cc-by-sa and MIT license
'PHP' 카테고리의 다른 글
PHP 싱글 톤 수업에 대한 우수 사례 [duplicate] (0) | 2018.09.20 |
---|---|
양식을 제출 한 후 백그라운드에서 PHP 스크립트를 실행하려면 어떻게해야합니까? (0) | 2018.09.20 |
isset () 및 empty ()를 피하는 방법 (0) | 2018.09.20 |
PHP에서 언어 구성과 "내장"기능의 차이점은 무엇입니까? (0) | 2018.09.20 |
어떤 $ _SERVER 변수가 안전합니까? (0) | 2018.09.20 |