Segurança com PHP I – SQL Injection

Não não….eu não falarei de um segurança de shopping ou segurança particular que desenvolve em PHP, falarei aqui sobre: “Medidas de segurança para aplicações WEB utilizando PHP”. Como este termo ficou grande, preferi por este menor =D.

Sem mais conversa fiada (e piadinhas infames), irei fazer uma série de artigos que ajudará você a fazer uma aplicação mais segura e confiável.

UM POUCO DE BLÁ BLÁ BLÁ

Antes de começar, queria falar uma coisa para que todos fiquem cientes: NÃO EXISTEM APLICAÇÕES 100% SEGURAS (Pronto, desabafei ! =D)

Isso mesmo pessoal, toda aplicação tem uma brecha de segurança ou em algum lugar deve estar faltando um tratamento a mais para devido dado. Um exemplo bem do nosso dia a dia é que de tempos em tempos a gente pode ver no noticiário hackers invadindo Internet Banking (Aplicações WEB de Agências Bancárias) de vários bancos por aí.

Procurando nesta WEB de meu Deus, fiz uma busca SUPER CRITERIOSA (Google ¬¬’) dos principais tipos de ataques em aplicações WEB, seguem:

  • SQL-Injection – Injeção de script SQL;
  • PHP Injection – Injeção de script PHP;
  • CSRF – Cross Site Request Forgeries;
  • XSS – Cross-Site Scripting;
  • Session Hijacking – Sequestro/Roubo de Sessão;

Reservarei um artigo para cada tipo de ataque listado. Hoje, falaremos sobre o famoso: SQL-Injection.

DEFINIÇÃO/FORMA DO ATAQUE

“É um tipo de ameaça de segurança que se aproveita de falhas em sistemas que interagem com bases de dados via SQL. A injeção de SQL ocorre quando o atacante consegue inserir uma série de instruções SQL dentro de uma consulta (query) através da manipulação das entradas de dados de uma aplicação.”Fonte: Wikipedia

A definição já fala tudo, mas vamos fazer um exemplo com e sem a prevenção deste ataque.

FORMULÁRIO

Segue um simples formulário que tem o intuito de consultar algum dado em uma tabela da nossa base de dados:

<form name='frm-busca' action='' method='post'>
    <input type='text' name='palavra' id='palavra' />
    <button name='btn-consultar'>Buscar</button>
</form>

SCRIPT PHP COM CONSULTA A BASE DE DADOS

Geralmente, o que vejo por aí, muitos desenvolvedores que não dão importância a segurança da sua aplicação implementa a consulta dos dados desta forma (utilizaremos o SGBD MySQL no exemplo):

// ----------------------------------------
// Rotinas de conexao com sua base de dados
// ----------------------------------------
 
$sql = "SELECT * FROM clientes WHERE nome = '{$_POST['palavra']}'";
$qry = mysql_query($sql) or die ('Erro: ' . mysql_error());
 
// ----------------------------------------
// Rotinas de envio das informacoes para tela
// ----------------------------------------

Sendo implementado desta forma, será mmmuuuuuiiiittooo fácil para o atacante forçar um erro, descobrir com que tabela se trata esta consulta e, ainda digo mais, executar um script SQL para remover esta tabela. Vamos ver logo abaixo.

EXEMPLO I: Se colocarmos no campo de entrada a seguinte informação:

Kilderson Sena

Até aqui belezura total. A nossa query ficara no seguinte formato:

SELECT * FROM clientes WHERE nome = 'Kilderson Sena'

EXEMPLO II: Se colocarmos no campo de entrada a seguinte informação:

sena’; show tables; —

AAAAARRRRÁÁÁÁ, por essa você não esperava não é ?! Vamos ver como ficará a nossa query com esse informação inesperada:

SELECT * FROM clientes WHERE nome = 'sena'; show tables ; -- '

Dependendo da configuração da sua base de dados, aqui fará que seja mostrado todas as tabelas da sua base de dados (comando show tables) quando você for buscar as linhas da consulta. O ‘’ representa um comentário inline, portanto, a última aspa simples sera desprezada.

EXEMPLO III: O atacante ciente que já conhece o nome de TODAS as tabelas de sua base de dados, poderá fazer isso:

‘ OR 1=1; DROP TABLE clientes; —

“Eita nóis” ! Olha o tamanho do problema que este bendito usuário me arrumou! Vejam só a SQL resultante:

SELECT * FROM clientes WHERE nome = '' OR 1=1; DROP TABLE clientes; -- '

Aqui simplesmente será disparado comando de remover a tabela clientes. =(

MACACOS ME MORDAM, COMO ME PREVINIR DESTAS BRECHAS ?!?

Como já dizia o poeta: “Muita HORA nessa CALMA”. Pessoal, vimos que o grande problema nesses valores enviados pelo formulário são as aspas simples, então, vamos “escapá-las”.

Segue abaixo o código que previne a injeção de SQL Injection. Mas existem várias formas de implementar esta prevenção:

// ----------------------------------------
// Rotinas de conexao com sua base de dados
// ----------------------------------------
 
$palavra = (string)addslashes($_POST['palavra']);
$sql = "SELECT * FROM clientes WHERE nome = '{$palavra}'";
$qry = mysql_query($sql) or die ('Erro: ' . mysql_error());
 
// ----------------------------------------
// Rotinas de envio das informacoes para tela
// ----------------------------------------

Apenas adicionando uma linha no nosso script, já podemos evitar uma brecha que pode custar a vida inteira de uma aplicação e base de dados.

É isso pessoal, agora vocês já aprenderam a se prevenir contra ataques de SQL Injection, mas vai uma dica extra que serve para prevenção de 90% de todos os ataques:

“Sempre trate informações vindas do usuário (Escapar entradas) e formate as saídas.”

Abraços e até o nosso próximo tópico de segurança!