Quais variáveis ​​$ _SERVER são seguras?

97

Qualquer variável que um usuário pode controlar, um invasor também pode controlar e, portanto, é a fonte de um ataque. Isso é chamado de variável "contaminada" e não é segura.

Ao usar $_SERVER, muitas das variáveis ​​podem ser controladas. PHP_SELF, HTTP_USER_AGENT, HTTP_X_FORWARDED_FOR, HTTP_ACCEPT_LANGUAGEE muitos outros são uma parte do cabeçalho da solicitação HTTP enviada pelo cliente.

Alguém conhece uma "lista segura" ou uma lista não contaminada de $_SERVERvariáveis?

torre
fonte
8
Depende de como você define "seguro". Os valores são todos seguros como estão, só depende para que você os usa.
deceze
6
Acho que, neste contexto, Rook está dizendo "Quais variáveis ​​de servidor não podem ser falsificadas pelo usuário", como REMOTE_ADDR.
vcsjones
6
Qualquer coisa precedida de HTTP_é um cabeçalho de solicitação e pode ser definida pelo navegador ou proxy entre eles. Eu os consideraria como qualquer outra entrada do usuário.
datasage
3
@ bob-the-destroyer REMOTE_ADDR é puxado diretamente do soquete TCP do apache, este valor não pode ser falsificado pela Internet por causa do handshake de três vias.
torre
2
@Rook: bom ponto. Eu acho que com a menção de "spoofing", eu estava mais inclinado para o antigo ato de spoofing do próprio ip, ao invés de qualquer tipo de falsificação do valor real de REMOTE_ADDR. E isso estaria fora do escopo desta questão. É bom ter uma ideia de como esse valor é definido, então, obrigado.
bob-the-destroyer

Respostas:

147

Não existem valores "seguros" ou "inseguros" como tais. Existem apenas valores que o servidor controla e valores que o usuário controla e você precisa estar ciente de onde um valor vem e, portanto, se ele pode ser confiável para um determinado propósito. $_SERVER['HTTP_FOOBAR']por exemplo, é totalmente seguro armazenar em um banco de dados, mas eu certamente não faria evalisso.

Como tal, vamos dividir esses valores em três categorias:

Controlado por servidor

Essas variáveis ​​são definidas pelo ambiente do servidor e dependem inteiramente da configuração do servidor.

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

Parcialmente controlado pelo servidor

Essas variáveis ​​dependem da solicitação específica enviada pelo cliente, mas só podem assumir um número limitado de valores válidos, uma vez que todos os valores inválidos devem ser rejeitados pelo servidor da web e não causar a invocação do script. Portanto, eles podem ser considerados confiáveis .

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

* Os REMOTE_valores têm a garantia de ser o endereço válido do cliente, conforme verificado por um handshake TCP / IP. Este é o endereço para onde qualquer resposta será enviada. REMOTE_HOSTdepende de pesquisas reversas de DNS e pode, portanto, ser falsificado por ataques DNS contra seu servidor (nesse caso, você terá problemas maiores de qualquer maneira). Este valor pode ser um proxy, que é uma realidade simples do protocolo TCP / IP e nada sobre o qual você possa fazer nada.

† Se o seu servidor web responder a qualquer solicitação, independentemente do HOSTcabeçalho, isso também deve ser considerado inseguro. Veja Quão seguro é $ _SERVER [“HTTP_HOST”]? .
Consulte também http://shiflett.org/blog/2006/mar/server-name-versus-http-host .

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

Valores totalmente arbitrários controlados pelo usuário

Esses valores não são verificados e não dependem de nenhuma configuração de servidor, são informações totalmente arbitrárias enviadas pelo cliente.

  • 'argv', 'argc'(aplicável apenas à invocação CLI, geralmente não é uma preocupação para servidores da 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' (pode conter dados corrompidos)
  • 'PHP_SELF' (pode conter dados corrompidos)
  • 'PATH_TRANSLATED'
  • qualquer outro 'HTTP_'valor

§ Pode ser considerado confiável , desde que o servidor da web permita apenas determinados métodos de solicitação.

‖ Pode ser considerado confiável se a autenticação for totalmente controlada pelo servidor da web.

A superglobal $_SERVERtambém inclui várias variáveis ​​de ambiente. Se eles são "seguros" ou não, depende de como (e onde) são definidos. Eles podem variar de totalmente controlados por servidor a totalmente controlados pelo usuário.

deceze
fonte
3
@Rook Mas como eu disse, depende absolutamente de como você o usa . Valores por si só não são seguros nem inseguros; depende de para que você os usa . Mesmo os dados enviados por um usuário nefasto estão perfeitamente seguros, desde que você não faça nada com eles que possa comprometer sua segurança.
deceze
2
@Rook: sua ideia de "seguro" faz esta questão parecer um pouco arbitrária, especialmente porque está totalmente ligada a uma extensão obscura ou versão personalizada do PHP. Embora você diga "não deveria ter uma" abordagem improvisada ", qualquer resposta parece exigir, no mínimo, familiaridade com o código fonte do PHP para descobrir como esses valores são definidos. Enviar e-mail para desenvolvedores de PHP não seria a melhor abordagem para encontrar uma resposta?
bob-the-destroyer
2
@Rook: Miscommunication. Como deceze sugeriu, "seguro para que propósito". Como mencionei, seu propósito é desconhecido e, além disso, existem vários outros $_SERVERvalores não documentados , dependendo de como o arquivo é servido. Na minha opinião, os documentados não esclarecem a verdadeira fonte. Do contrário, acredito que você não estaria fazendo essa pergunta. Que bom que você tem uma lista que pode usar. Mas eu ainda sugiro enviar um relatório de bug (quando seu site de bug for corrigido), enviar um e-mail aos mantenedores dos documentos ou atualizar você mesmo os documentos (se você tiver acesso ao link). Seria benéfico para a comunidade saber esta informação.
bob-the-destroyer
3
SERVER_NAMEnão é necessariamente controlado pelo servidor. Dependendo do gateway e das configurações, ele pode ser duplicado HTTP_HOSTe, portanto, sujeito à mesma advertência.
bobince
1
@deceze @Rook SERVER_PORTPrecisa daquela cruzzinha ? bugs.php.net/bug.php?id=64457
Dejan Marjanović
12

No PHP, cada $_SERVERvariável começando com HTTP_pode ser influenciada pelo usuário. Por exemplo, a variável $_SERVER['HTTP_REINERS']pode ser contaminada definindo o cabeçalho HTTP REINERSpara um valor arbitrário na solicitação HTTP.

Reiners
fonte
re "arbitrário"; Não são totalmente arbitrários, pois obedecem a um formato. Por exemplo, $_SERVER['HTTP_REINERS'] não pode conter caracteres de nova linha na maioria dos sapis.
Pacerier