Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

rvlira

Problema com função anti-injection

Recommended Posts

Pessoal, para evitar problemas de sql e php injection estou utilizando a seguinte função para tratar tudo que o script recebe de formulários e parâmetros via query string:

 

function anti_injection($txt){

	 $txt = get_magic_quotes_gpc() == 0 ? addslashes($txt) : $txt;
	 return preg_replace("@(--|\#|\*|;|=)@s", "", $txt); 

   }

   function processaString($texto){

	 return anti_injection(strip_tags($texto));

   }

O primeiro teste que fiz com essa função foi na página de login. No campo nome de usuário digitei:

 

fulano' or 1=1

 

No campo de login digitei:

 

teste' or 1=1

 

Na página que valida o login eu tenho:

 

$nome = processaString($_REQUEST['username']);
$senha = processaString($_REQUEST['password']);

$sql = "SELECT SENHA FROM USUARIOS WHERE LOGIN='".$nome."'";
#Notem que estou colocando o login entre aspas simples acima

Bem, o banco de dados que estou usando é o firebird.

 

Eu achava que essa função anti-injection fosse tratar toda a string passada pelo usuário como uma string, ou seja, removendo aspas simples e duplas.

 

Mas rodando o exemplo acima, colocando aspas simples no campo de login ou senha o script apresenta erro porque considerou a aspas simples quando deveria bloqueá-la.

 

Poderiam me ajudar a acertar essas funções?

 

Muito obrigado.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Para bloquer...pode fazer algo como:

<?php
//$str = sua string
if(preg_match('/(\'|\")/', $str)){
	die('\' e \" Não são permitidos!');
}
?>

Compartilhar este post


Link para o post
Compartilhar em outros sites

Valeu ai pessoal!

 

Só não entendi uma coisa: qual a função de inserir barras invertidas antes das aspas?

 

Quer dizer... não impede o SQL injection... Creio que ajuda apenas contra PHP injection, não é? Porque vai jogar as aspas para dentro da string, não é isso?

 

Uma outra pequena dúvida: Lá na função "anti_injection" tem um preg_replace para remover caracteres especiais. Eu não entendo de expressões regulares. Queria saber como eu poderia modificar a função preg_replace para que remova as aspas duplas e simples de dentro da string.

 

Novamente agradeço pela ajuda.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Enquanto isso estive em uns artigos que encontrei e parece que o addslashes realmente impede, porém, acho que só no MySQL.

 

Porque aqui no Firebird, se ele encontra uma \ antes de um apóstrofe, a barra estará dentro da string delimitada pelo apóstrofe, ou seja, não impedirá o sql injection. Ou estou enganado?

 

t+!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ta enganado, firefox nao tem nada haver com o resto é só um navegador

 

o que você tem que ver se você ta com magic_quotes ativado

 

uma dica antes de querer fazer um ant sql injection

 

procure entender do que você esta se protegendo, o que é sql injection, senao você vai ficar só viajando nessas funções

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não é Firefox não. É o banco de dados Firebird. Eu não uso o MySQL.

 

Apenas para ilustrar meu raciocínio. Se eu tiver:

 

$sql = "SELECT * FROM USUARIOS WHERE LOGIN='".$nome."'"; #Sem nenhuma proteção mesmo

E o usuário inputar:

 

' or 1=1;--

 

O banco vai retornar todas as linhas da tabela, pois a SQL terá ficado assim:

 

SELECT * FROM USUARIOS WHERE LOGIN='' or 1=1;--'

 

Se eu adicionar addslahes antes de jogar a variável dentro da sql, o comando ficará assim:

 

SELECT * FROM USUARIOS WHERE LOGIN='\' or 1=1;--'

 

Ou seja, continuará trazendo todos os registros da tabela, pois apesar de não haver um usuário com login "\", 1 é igual a 1.

 

t+!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Você está equivocado.Dá uma lida sobre sql-injection...

Se você coloca a barra de escape,o que vem depois é interpretado como uma string e não como parte da sua consulta.

Abraço!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá novamente.

 

O MySql pode até ignorar o apóstrofe e a aspas quando estão escapadas, mas o firebird e o oracle não o fazem. Fiz o teste em ambos. O mesmo teste que eu coloquei no último post. Por sinal, eu editei que estava errado.

 

Como não uso o MySQL, não tenho como testar nele o exemplo que eu dei, mas posso afirmar que no Firebird e no Oracle não funciona.

 

Só preciso agora descobrir que parâmetros adicionar na função preg_replace para remover da string as aspas simples, duplas e espaços. De mais a mais não creio que seja correto armazenar isso no banco de dados. Principalmente se tratando de login e senha.

 

t+!

Compartilhar este post


Link para o post
Compartilhar em outros sites

mas nao tem logica isso porque escapando o apostrofo ficaria assim

 

\' or 1=1;--

 

dai ele vai testar se login = '\' or 1=1;--' , lembre-se você nao ta eliminando o apostrofo do select

 

isso tudo ele vai ler como string e nao executa o "or"

 

eu tenho oracle, sql server, postgresql e mysql aqui na minha maquina

 

mas como falei você primeiro precisa entender o que você tem que proteger e como

 

se ta usando magic_quote, entre outras coisas

 

evitar sql injection é muito simples nao é um bicho de sete cabeças.

 

nao precisa eliminar nenhum caracter para se proteger, basta saber passar um select seguro e os dados por parametros.

 

por exemplo o forum aqui se digita tudo que é caracter e nem por isso se elimina os caracteres e o forum tem select seguro

Compartilhar este post


Link para o post
Compartilhar em outros sites

Fabyo, você falou exatamente a mesma coisa que eu no post do exemplo. Sim, o apóstrofe do final da SQL é mantido. Mas você está assumindo que deveria funcionar e na verdade não funciona.

 

Vou fundamentar as coisas que eu havia dito até então. Veja o seguinte trecho que extraí de um artigo da internet:

 

Note that using the backslash as an escape character is not standard ANSI SQL. If MySQL is the only database you'll ever use, the backslash may be acceptable, but the same SQL statement run on another database may well fail.

 

Em bom português, ele está dizendo o que eu já tinha dito sem comprovação. A barra invertida como caracter de escape não faz parte do padrão ANSI SQL. A estrutura das consultas SQL do Firebird e Oracle respeitam o padrão, não aceitando a barra invertida como caracter de escape. O MySQL é o único banco em que isso funciona.

 

O artigo ainda informa que no padrão SQL o caracter de escape é o próprio apóstrofe. Ou seja, para escapar um apóstrofe numa string temos que adicionar um outro apóstrofe antes dele.

 

Para consultar o artigo completo, segue o link:

http://www.sitepoint.com/article/php-antho...-3-php-mysql/7/

 

Vale ressaltar ainda que o apóstrofe como caracter de escape é comum em muitas outras linguages além do padrão SQL. Em Object Pascal, por exemplo, se fazemos:

 

varString := '''blablabla'''; //Note que entre a palavra estão três aspas simples seguidas

 

O valor da variável será:

 

'blablabla'

 

Para o caso de ainda querer confirmar alguma coisa, disponibilizei a seguinte página:

http://www.nby.com.br/teste/teste.php

 

É um simples exemplo do que estou falando. Coloque para consultar FULANO (em maiúsculas mesmo). A página retornará apenas o registro do fulano.

 

Agora consulta novamente colocando o seguinte:

 

' or 1=1--

 

Pronto! Você verá na tela todos os registros da tabela.

 

E sim, a string passada pelo usuário está sendo escapada com o addslashes.

 

O que acontece é que a SQL ficou assim:

 

SELECT ID, LOGIN FROM USUARIOS WHERE LOGIN='\' or 1=1--'

 

E não sendo a barra invertida o caracter de escape para os bancos que usam o padrão ANSI SQL o resultado é bem óbvio.

 

Segue o código dessa página que confirma tudo o que foi dito:

 

<html><head><title>Teste SQL Injection</title></head><body>
<form name="frmteste" action="teste.php" method="post">
Usuário: <input type="text" name="edlogin" size=40><br>
<input type="submit" name="btnenviar" value="Enviar consulta">
</form>
<?php
if (getenv("REQUEST_METHOD")=="POST"){
  echo "<br><hr><br>";
  #Conecta ao banco de dados
  $conn = ibase_connect("MEU_HOST","MEU_USER","MINHA_SENHA");
  #Pega o nome de usuário consultado já escapando as aspas simples
  $username = get_magic_quotes_gpc() == 0 ? addslashes($_POST['edlogin']) : $_POST['edlogin'];
  #Monta a SQL
  $sql = "SELECT ID, LOGIN FROM USUARIOS WHERE LOGIN='".$username."' ORDER BY LOGIN";
  #Executa a consulta
  $res = ibase_query($conn, $sql);
  #Exibe os resultados na tela
  while ($data=ibase_fetch_row($res)){
	echo $data[0]."\t".$data[1]."<br>";
  }
  #Fecha a conexão com o banco de dados
  ibase_close($conn);
}
?>
</body>
</html>

Bem, com tudo isso explicado, ainda permaneço com o problema.

 

Como posso fazer para escapar a string usando o apóstrofe em vez da barra invertida?

 

Ou então como ficaria a minha função anti_injection (descrita no post inicial) para que remova as aspas simples, duplas e espaços da string que foi passada no parâmetro?

 

Obrigado.

Compartilhar este post


Link para o post
Compartilhar em outros sites

<?php
function removeApostrofe($string){
	$string = preg_replace("/(\'|\")/", "", $string);
	return $string;
}
$string = "' or '1=1";
$string = removeApostrofe($string);
echo $string; //or 1=1
/*foreach($_POST as $key => &$valor){
	$_POST[$key] = removeApostrofe($valor);
}*/
?>

Abraço!

Compartilhar este post


Link para o post
Compartilhar em outros sites

rvlira

 

o firebird/interbase qeu está usando, qual a versão ?

 

pode ser um bug e talvez seja necessário instalar um patch ou fazer update

 

verifique isso

 

 

quanto ao SQL injection.. não precisa dar tanta volta

basta escapar das aspas simples. Obviamente que isso depende de como vo^ce está montando as querys SQL

Compartilhar este post


Link para o post
Compartilhar em outros sites

@proust

 

Valeu cara. Só mais uma coisa. Sua função tem o seguinte:

 

preg_replace("/(\'|\")/", "", $string);

 

E lá na função do primeiro post eu tenho:

 

preg_replace("@(--|\#|\*|;|=)@s", "", $txt);

 

Como eu posso transformar essas duas linhas em uma só? Realmente eu não entendo nada de expressões regulares e por isso eu não sei como fazer isso. Creio que se eu criar uma string com as duas expressões concatenadas não vá funcionar, ou não? Ainda não estou na máquina com o php para fazer o teste.

 

@hinom

 

Uso o Firebird 2.1, que é a versão mais atualizada disponível. De qualquer maneira também testei no Oracle. E como consta no post anterior o problema não é do banco não. É porque no padrão ANSI SQL a barra invertida não é caracter de escape. Isso só funciona no MySQL.

 

Novamente agradeço pela ajuda.

 

t+!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Firebird escapes the single-quote (apostrophe) character in strings with another quote character.

o Firebird escapa da aspas simples em strings com outra aspa simples

 

referência:

http://www.firebirdfaq.org/faq229/

 

 

 

exemplo prático

 

firebird

<?php

$cant = "can't";

$cant = str_replace("'", "''", $cant);

echo "INSERT INTO t1 VALUES('$cant')";

?>

 

mysql

<?php

$cant = "can't";

$cant = str_replace("'", "\'", $cant);

echo "INSERT INTO t1 VALUES('$cant')";

?>

Compartilhar este post


Link para o post
Compartilhar em outros sites

@hinom

 

Sim, isso aí eu sei. No post anterior eu já tinha escrito isso.

 

O artigo ainda informa que no padrão SQL o caracter de escape é o próprio apóstrofe. Ou seja, para escapar um apóstrofe numa string temos que adicionar um outro apóstrofe antes dele.

O problema é que no php tem a função addslashes que escapa com a barra invertida, mas funciona apenas para o MySQL.

 

O ideal seria ter uma função addquotes, hehehe...

 

t+!

Compartilhar este post


Link para o post
Compartilhar em outros sites
O problema é que no php tem a função addslashes que escapa com a barra invertida, mas funciona apenas para o MySQL.

t+!

 

Funciona com SQL Server tbm

 

só nao posso afirmar com Oracle e nem firebird porque nunca precisei testar sql injection neles

:natal_w00t:

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.