it-gundan.com

PHP에서 $ _SERVER []가 안전한 데이터 소스입니까?

$_SERVER[]$_GET[]처럼 위생 처리 할 필요가없는 안전한 데이터 소스로 $_POST[]에 100 % 의존 할 수 있습니까?

29
user2079272

이것은 스택 오버플로에 대한 내 질문 중 하나에서 가져옵니다. $ _ SERVER 변수는 안전합니까?

서버 제어

이러한 변수는 서버 환경에 의해 설정되며 전적으로 서버 구성에 따라 다릅니다.

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

부분적으로 서버 제어

이러한 변수는 클라이언트가 전송 한 특정 요청에 따라 다르지만 웹 서버에서 모든 유효하지 않은 값을 거부하고 스크립트 호출을 시작하지 않기 때문에 제한된 수의 유효한 값만 사용할 수 있습니다. 따라서 신뢰할 수있는 으로 간주 될 수 있습니다.

  • 'HTTPS'
  • 'REQUEST_TIME'
  • 'REMOTE_ADDR' *
  • 'REMOTE_Host' *
  • 'REMOTE_PORT' *
  • 'SERVER_PROTOCOL'
  • 'HTTP_Host'
  • 'SERVER_NAME'
  • 'SCRIPT_FILENAME'
  • 'SERVER_PORT'
  • 'SCRIPT_NAME'

* REMOTE_ 값은 TCP/IP 핸드 셰이크에 의해 검증 된대로 클라이언트의 유효한 주소임을 보증합니다. 이것은 응답이 전송 될 주소입니다. REMOTE_Host는 역방향 DNS 조회를 사용하므로 서버에 대한 DNS 공격으로 인해 스푸핑 될 수 있습니다 (이 경우 더 큰 문제가 발생 함). 이 값은 프록시 일 수 있으며, 이는 TCP/IP 프로토콜의 단순한 현실이며 사용자가 할 수있는 일은 없습니다.

† 웹 서버가 Host 헤더에 관계없이 any 요청에 응답하는 경우 안전하지 않은 것으로 간주해야합니다. $ _ SERVER [“HTTP_Host”]는 얼마나 안전합니까? 를 참조하십시오.
또한 http://shiflett.org/blog/2006/mar/server-name-versus-http-Host 를 참조하십시오.

완전히 임의의 사용자 제어 값

이러한 값은 전혀 확인되지 않으며 서버 구성에 의존하지 않으며 클라이언트가 전적으로 임의의 정보를 보냅니다.

  • 'argv', 'argc' (CLI 호출에만 적용 가능하며 일반적으로 웹 서버에 대한 문제는 아님)
  • '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' (오염 된 데이터를 포함 할 수 있음)
  • 'PHP_SELF' (오염 된 데이터, 즉 /index.php/evilstring을 포함 할 수 있음)
  • 'PATH_TRANSLATED'
  • 다른 'HTTP_' 가치

웹 서버가 특정 요청 방법 만 허용하는 한 신뢰할 수있는 것으로 간주 될 수 있습니다.

§ 웹 서버에서 인증을 완전히 처리하는 경우 신뢰할 수있는 것으로 간주 될 수 있습니다.

슈퍼 글로벌 $_SERVER에는 여러 환경 변수도 포함됩니다. 이것들이 "안전한지"여부는 그것들이 어떻게 (그리고 어디에서) 정의되는지에 달려 있습니다. 서버 제어에서 사용자 제어에 이르기까지 다양합니다.

44
rook

$ _GET [] 및 $ _POST []처럼 살균 할 필요가없는 안전한 데이터 소스가되기 위해 $ _SERVER []에 100 % 의존 할 수 있습니까?

귀하의 질문은 즉시 실패를 나타냅니다. 모든 입력 소스 는 반드시 소독해야합니다 . 입력은 사용자가 직접 제어 할 수있는 채널로 간주되는 것이 아니라 응용 프로그램 외부의 모든 데이터 소스입니다.

이 방법으로 생각하면 응용 프로그램에는 데이터를 얻는 두 가지 방법, 즉 응용 프로그램에 하드 코딩 된 정보와 입력이 있습니다. 동일한 시스템의 다른 프로그램에서 생성 된 경우에도 여전히 프로그램에 입력됩니다.

공통 관용구 Filter-In, Escape-Out는 사용자 입력뿐만 아니라 응용 프로그램에 들어오고 나가는 모든 것에 적용됩니다.

따라서 $_SERVER에 있으면 해야합니다 필터링/위생. 응용 프로그램에서 하드 코딩되지 않은 내용에 의존해서는 안됩니다.

이것이 왜 중요한가? 사용자의 모든 입력을 필터링 한 다음 데이터베이스에서 가져온 데이터를 신뢰한다고 가정 해 봅시다. 필터링에 허점을 악용 할 수 있으면 신뢰할 수있는 데이터를 주입 할 수 있습니다. 이로 인해 2 차 XSS 또는 SQLi가 발생할 수 있습니다. 그러나 응용 프로그램에 들어오는 모든 것을 필터링하면 응용 프로그램의 위치와 상관없이 응용 프로그램에 들어올 때 안전합니다!

따라서 $_SERVER, $_GET, $_POST, $_COOKIE, $_REQUEST, $_ENV, $argc, $argv, 데이터베이스, 파일 시스템 (버전 제어 코드 제외) 등 ...

14
ircmaxell

바보 같은 질문이 아닙니다!

QUERY_STRING, REQUEST_URI 및 모든 HTTP_ * 변수와 같이 많은 $ SERVER 변수가 사용자 브라우저에서 전달되거나 사용자의 영향을받을 수 있습니다.

REMOTE_ADDR 변수조차도 원시 소켓을 사용하여 스푸핑 할 수 있습니다 (알고있는 한 유효한 IP로만 가능).

나는 좋은 정책의 문제로 그들 모두를 피할 것입니다.

http://php.net/manual/en/reserved.variables.server.php

6
GBC

"안전한 데이터 소스"와 같은 것은 없습니다. 데이터를 다른 것으로 전달할 때는 항상 데이터가 올바른 형식인지 확인해야합니다.

아포스트로피 ( ')로 구분 된 문자열 [1] 내에서 SQL로 출력하는 경우 아포스트로피 (또는 문자열을 손상시킬 수있는 다른 것)를 이스케이프해야합니다. Javascript 아포스트로피로 구분 된 문자열 [2]로 출력하는 경우 HTML과 아포스트로피를 모두 이스케이프해야합니다. 그것은 모두 당신이 출력하는 것에 달려 있습니다. 완벽하게 안전한 문자열은 악의적 인 방식이 아니더라도 대상 스크립트를 손상시킬 수 있습니다. (종종 깨질 수 있으면 악용 될 수도 있습니다.)

[1] 예 : $db->query("SELECT * FROM users WHERE name = '$username'");
[2] 예 : <script>alert('Hi <?php echo $username;?>');</script>

내 블로그에서 이스케이프 처리에 대해 이야기했지만 내 게시물은 특별히 XSS에 관한 것이지만 여기에도 동일한 원칙이 적용된다고 생각합니다. XSS 란 무엇이고 웹 사이트를 보호하는 방법 .

PHP 자체가 이미 특정 형식을 적용하고 있다는 것을 알지 못하면 거의 모든 것을 안전하지 않은 것으로 간주 할 수 있습니다. IP 주소는 일반적으로 xxxx 형식으로 제공되지만 IPv6의 경우 x : x : x : x : x : x : x : x 또는 IPv6 패킷의 IPv4 대상의 경우 0 : 0 : 0 : 0 : 0 : ffff : xxxx이어야합니다. 매우 흥미로운 버그로 이어질 수 있습니다.

이제 IP 주소에는 아포스트로피가 포함되지 않습니다. 원격 주소를 사용하기 전에 $ _SERVER [ "HTTP_X_FORWARDED_FOR"] 헤더를 확인하는 사람들이 있습니다. 헤더가 올바르게 설정되어 있다면 (@GBC의 응답에 대한 의견에서 @Ladadadada가 지적한 것처럼) 훌륭하지만 스푸핑 일 수도 있습니다. 그런 다음 다른 사람이 데이터베이스에 저장 한 데이터를 사용하면 악의적 인 내용이 다시 나타날 수 있습니다. 따라서 결국 입력을 신뢰하지 마십시오. 한 번 잊어 버리는 것보다 너무 많이 확보하는 것이 좋습니다.

3
Luc