SQL, validações e PHP
Posted on qui 19 novembro 2009 in HowTo
Dicas quando o assunto é SQL e PHP.
<?php
/*
sanitizar:
Esta função realiza :
- remove espaços no começo e fim do parâmetro
- remove os caracteres *?--%'&#@"/,;
- remoção de acentos, torna tudo minúsculo, preserva apenas: letras, números, .:-_
*/
function sanitizar($parametro=false)
{
$parametro=stripslashes(trim($parametro));
$parametro=str_replace(array("*","?", "--", "%", "'", "&", "#", "@", "\"", "/", ",", ";"),
"", $parametro);
$parametro=strtolower(preg_replace('/[^[:alnum:]|_|.|:|-]/', " ",strtr($parametro,
"áàãâéêíóôõúüçÁÀÃÂÉÊÍÓÔÕÚÜÇ-:","aaaaeeiooouucAAAAEEIOOOUUC-:")));
return $parametro;
}
/*
anti_sql:
Esta função realiza :
- remove caracteres e palavras reservadas de SQL.
Obs: esta idéia foi retirada de um fórum de discussão.
*/
function anti_sql($varivel)
{
$varivel = preg_replace("/(from|union select|select|insert|delete|
where|drop table|show tables|#|\*|--|;|=|@|\\\\)/i","",$varivel);
$varivel = trim($varivel);
return $varivel;
}
/*
Para evitar XSS, ao exibir valores recuperados na tela, utilize a função nativa htmlentities
exemplo:
*/
$str="não encontrei o valor";
echo $str."<br />";
$str="não encontrei o valor <img src='uma_imagem_nao autorizada.png' />";
echo $str."<br />";
echo htmlentities($str)."<br />";
/* Inserir valor de campos numericos não tratados sempre oferecem risco de SQL Injection
devido a não utilização da aspa na composição da query
ex: SELECT titulo,mensagem FROM noticia WHERE noticia_id=234;
já em campos text/string a SQL Injection torna-se dificultada pela existência da aspa
ex: SELECT titulo,mensagem FROM noticia WHERE noticia_titulo='Meu titulo';
porém pode ser contornada, se o interpretador não estiver habilitado para escapar aspas
logo seguem algumas forma de evitar a SQL Injection:
*/
//campo numérico:
/* ---- ERRADO: ---- */
$numero = $_GET['numero'];
$sql= "SELECT titulo,mensagem FROM noticia WHERE noticia_id=".$numero;
/* ---- Fazer: ---- */
$numero = (int) $_GET['numero'];
//ou
$numero = intval($_GET['numero']);
$sql= "SELECT titulo,mensagem FROM noticia WHERE noticia_id=".$numero;
/* ou então pode-se usar o sprintf */
$sql= sprintf( "SELECT titulo,mensagem FROM noticia WHERE noticia_id = %u",$numero);
/* inclusive para casos compostos */
$numero=22;
$titulo='Minha noticia';
$sql= sprintf( "SELECT titulo,mensagem FROM noticia WHERE noticia_id = %u OR titulo = '%s'",$numero, $titulo);
/* a SQL Injection no meio da string irá exigir a entrada de uma aspa
Ex:
"SELECT titulo,mensagem FROM noticia WHERE titulo = 'Meu Teste'
SQL Injection:
"SELECT titulo,mensagem FROM noticia WHERE titulo = 'Meu Teste' OR 1=1 --'
a entrada deverá ser: Meu Teste' OR 1=1 --
para resolver esta entrada, usar as funções pertinente conforme o banco de dados
Ex:
pg_escape_string
pg_escape_bytea
dbx_escape_string
db2_escape_string
maxdb_escape_string
mysql_escape_string
sqlite_escape_string
mysqli_escape_string
ingres_escape_string
maxdb_real_escape_string
mysql_real_escape_string
*/
$titulo = @pg_escape_string($_POST['titulo']);
/* o 'arroba' à frente da função é usado para evitar warning oyu fatal error */
$sql="SELECT titulo,mensagem FROM noticia WHERE titulo = '".$titulo."'";
/*
o uso das funções de preparação de query também é recomendado
pois faz o trabalho de escapar e validar dados antes da execução
ex:
pg_prepare
mysqli_stmt_prepare
ingres_prepare
pg_send_prepare
ovrimos_prepare
maxdb_stmt_prepare
db2_prepare
ifx_prepare
odbc_prepare
maxdb_prepare
swish_prepare
ibase_prepare
sdo_das_relational_executepreparedquery
exemplo retirado de:
http://br2.php.net/manual/pt_BR/function.pg-prepare.php
$dbconn = pg_connect("dbname=mary");
$result = pg_prepare($dbconn, "my_query", 'SELECT * FROM shops WHERE name = $1');
//---> Execute the prepared query. Note that it is not necessary
to escape the string "Joe's Widgets" in any way:
$result = pg_execute($dbconn, "my_query", array("Joe's Widgets"));
//---> Execute the same prepared query, this time with a different parameter:
$result = pg_execute($dbconn, "my_query", array("Clothes Clothes Clothes"));
*/
/*
alguns padrões podem ser verificados com o uso de expressões regulares
seguem exemplos para uma máscare de telefone e uma máscara de CPF
- mas sem validação dos dados, apenas do padrão.
*/
/*verdadeiro se o parâmetro for algo como (99)9999-9999 */
function checar_padrao_telefonico($valor=false)
{
return preg_match('/^\([0-9]{2}\)[0-9]{4}-[0-9]{4}$/',$valor)?true:false;
}
/*verdadeiro se o parâmetro for algo como 999.999.999-99 */
function checar_padrao_cpf($valor=false)
{
return preg_match('/^([0-9]{3}\.){2}[0-9]{3}-[0-9]{2}$/',$valor)?true:false;
}
?>