PHPSecInfo – PHP Security Consortium

PHPSecInfo

O PHPSecInfo é um projeto da própria PHP Security Consortium cujo objetivo é próoor uma melhor configuração do ambiênte visando sempre a segurança e estabilidade do mesmo.

O PHPSecInfo funciona muito parecido com a função php_info() do php. Ela lê, analiza e oferece algumas sugestões caso alguma diretiva esteja configurada fora do padrão de segurança que se deve ter em um ambiênte de produção.

Instalação

Não precisa instalar nenhuma extensão nem nada do tipo, basta jogar a pasta do projeto no local de sua preferência e acessa-la via browser.

[]’s
Igor.

Posts Relacionados:

Proteção contra o SQL Injection

Olá a todos, desculpem pela ausência, por algum motivo (algo relacionado com o Speedy) eu não estava conseguindo acessar o meu blog o que me impossibilitava de escrever, i’m sorry.

Hoje vou falar um pouco sobre como funciona o SQL Injection e como podemos proceder para que nós não sejamos pegos por este tipo de vulnerabilidade.

O que é SQL Injection?

SQL Injection é uma técnica de injeção de código que explora uma vulnerabilidade de segurança localizada na camada de banco de dados (database layer) do servidor. Na prática é utilizada por hackers (ou não) para ter acesso ao banco de dados do servidor da vítima sem que ele precise de um login ou uma senha efetivamente para fazê-lo.

Como funciona o SQL Injection?

Para entendermos melhor como funciona os ataques via injeção de códigos SQL (SQL Injection), vou utilizar um caso bem comum entre os programadores para que vocês se familharizem com mais facilidade.

Pense em um formulário para login no sistema e uma consulta na base de dados para verificar se determinado usuário e senha existe em na base de dados.
Exemplo
SELECT usuario,senha FROM usuarios WHERE usuario = 'igorescobar' AND senha='123456'

O ataque acontece justamente no ponto, aonde o usuário preenche o usuário e a senha no formulário de login do site. Se você não filtra todos os dados que vem de FORA para DENTRO da sua aplicação, você corre o risco de ser atacado.

Na prática o código fica algo parecido com isso:
SELECT usuario,senha FROM usuarios WHERE usuario = '$usuario' AND senha='$senha';

Estas variáveis ($usuario e $senha) estão vindo do $_POST do seu formulário e o servidor iria interpretar assim:
SELECT usuario,senha FROM usuarios WHERE usuario = 'igorescobar' AND senha='123456';

Agora imagine que eu sou um usuário mal intencionado e desejo logar no servidor de vocês sem ser autorizado.

No campo senha vou inserir o seguinte conteúdo:
123456' OR 'a'='a

Vamos ver como fica?
SELECT usuario,senha FROM usuarios WHERE usuario = 'igorescobar' AND senha='123456' OR 'a'='a';

Hun… como diria eu mesmo (há!): F-U-D-E-U!

Quer outro exemplo? … um mais bacana?

Agora no campo senha eu vou inserir o seguinte conteúdo:
123456'; DROP TABLE usuarios; --

Vamos ver como fica?
SELECT usuario,senha FROM usuarios WHERE usuario = 'igorescobar' AND senha='123456'; DROP TABLE usuarios; --';

Ok, agora você já esta pronto para passar no RH :)

Oh my god :O como eu me protejo dos ataques SQL Injection ?

Primeiro: Separe sempre a exibição de erros em 2 ambientes, o ambiente de desenvolvimento e o ambiente de produção. O ambiênte de desenvolvimento pode ter qualquer tipode erro emitido na tela, afinal, você precisa ver os erros para tratá-los, no ambiênte de produção omita qualquer tipo de erro, qualquer erro pode ser uma pista para o hacker descobrir detalhes sobre o seu ambiênte.

Ambiente de Desenvolvimento

<?php error_reporting(E_ALL ^ E_NOTICE);  ?>

Ambiente de Produção

<?php error_reporting(0);  ?>

Segundo: Filtre todo o tipo de variável dados que veem de urls ou inputs de formulário $_GET ou $_POST para que nenhum dos dados inputados pelo usuário possa ser interpretado como parte da instrução SQL.

Vale lembrar que o certo seria utilizarmos PDO que já tem uma proteção definitiva contra isso, pois ele tem o acesso ao modelo do seu banco de dados e pode fazer muito melhor do que uma simples filtrarem generica nos campos, ele pode filtrar cada campo dependendo do tipo de cada campo o que é muito melhor.

Caso você não use PDO, você pode utilizar também uma função chamada mysql_real_escape_string que também cumpre o que promete.

Solução definitiva para o SQL Injection
Está solução é válida apenas para as pessoas que não utiliza nenhuma das 2 (duas) soluções citadas acima.

<?php

/**
 * Protege o banco de dados contra ataques de SQL Injection
 *
 * Remove palavras que podem ser ofensivas à integridade do banco
 * Adiciona barras invertidas a uma string
 *
 * @uses $_REQUEST= _antiSqlInjection($_REQUEST);
 * @uses $_POST = _antiSqlInjection($_POST);
 * @uses $_GET = _antiSqlInjection($_GET);
 *
 * @author Igor Escobar
 * @email blog [at] igorescobar [dot] com
 *
 */

function _antiSqlInjection($Target){
	$sanitizeRules = array('OR','FROM','SELECT','INSERT','DELETE','WHERE','DROP TABLE','SHOW TABLES','*','--','=');
	foreach($Target as $key => $value):
		if(is_array($value)): $arraSanitized[$key] = _antiSqlInjection($value);
		else:
			$arraSanitized[$key] = (!get_magic_quotes_gpc()) ? addslashes(str_ireplace($sanitizeRules,"",$value)) : str_ireplace($sanitizeRules,"",$value);
		endif;
	endforeach;
	return $arraSanitized;
}

?>

Terceiro: Não tem, só estes 2 passos está bom ;)

ps: Desculpem as piadas, estou de bom humor hoje :)

UPDATE(1): Acrescentei algumas palavras na blacklist da função
UPDATE(2): Troquei o str_replace para o str_ireplace e acrescentei a verificação de magic_quotes.
UPDATE(3): Retirei a função trim por não fazer diferença alguma rs.

[]’s
Igor.

Posts Relacionados:

Evitando frustrações com sessões no PHP

Aplicações Web PHP podem acrescentar estado nas suas aplicações de forma muito fácil, porque a ilusão de estado é mantida através do ID de uma sessão e nela podemos transportar informações entre uma página e outra sem perdê-la no meio do caminho. Talvez você já tenha perdido uma produtividade potencial por conta de bugs bizarros ou até mesmo brechas de segurança por causa dessas belezinhas. Aqui vão quatro dicas para evitar que você fique perdendo tempo e garanta o seu site.

1. Não use underscores em hostnames

A menos que você tenha memorizado o RFC de caracteres permitidos no nome do host, você pode não estar ciente de que não é permitido colocar underscores em nomes de hosts. Em alguns browsers, como o firefox, não aplica esta proibição, mas o Internet Explorer vai se recusar a setar um cookie/session cujo hostname possua underscores. O IE vai fazer com que em cada página carregada seja gerado um novo ID de sessão. Mas o usuário nunca vai aceitá-la. Fonte: documentação set_cookie.

2. Atualize suas sessões depois de redirects

Você deve chamar a função  session_write_close (ou pelo alias session_commit) para escrever os dados na sessão antes que qualquer HTTP Location redirects seja emitido. Este comando também “libera” a sessão do usuário assim ele pode fazer outras atividades na sua aplicação. Veja os comentários por cenaculo e bkatz.

3. Prevenindo a fixação de sessão

Fixação de sessão ou session fixation, permite que qualquer usuário mal intencionado receba o id de uma sessão válida passando um simples link. Sem predizê-la ou roubá-la do cookie de algum usuário ou através de um $_GET comum. A vitima é pega utilizando o id da sessão gerada pelo “hacker” e não através do servidor. Você pode prevenir este tipo de ataque chamando a função  session_regenerate_id(), particularmente após armazenar informações importantes como o nome de um login ou uma flag. Isso vai mostrar para o “hacker” um id de sessão inútil. Chris Shifflet fez uma discussão mais meticulosa sobre Session Fixation.

Exemplo de ataque via Session Fixation

4- Não exponha id’s de sessão.

Cookies talvez sejam, relativamente, o lugar mais seguro para armazenar o id de suas sessões se comparando a incorporá-la diretamente na sua url (via PHPSESSID). Aqui vão duas configurações (via php.ini) para controlar este comportamento, cada um deles são muito importantes, por isso você deve setar ambos. Você deve setar o session.use_trans_sid para (off) e se você estiver utilizando PHP 4.3.0 ou superior você pode setar também session.use_only_cookies para “1?.

[]’s
Igor.

Posts Relacionados: