Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Hoje um amigo me pediu ajuda porque o sistema dele não estava gravando informações de caminhos no Windows, ex:
Ele queria gravar em uma coluna x o valor
$teste = "D:\wamp\www\";
Expliquei pra ele sobre o addslashes que resolveria esse problema, porém parei para pensar: Todo POST que é editável pelo usuário e vai para o banco corre o risco de ter palavras-chave do SQL.
Pergunta: É uma boa prática passar TODAS as variáveis que vem de POST por um mysql_real_escape_string() antes de gravar no banco?
O que você falou faz sentido. Checar sempre antes de inserir. Mas no caso então de Strings, o importante seria usar um anti sql injection sempre, certo?
Isso,
o pessoal usa muito a function
function anti_injection($sql){
$seg = preg_replace(sql_regcase("/(from|select|insert|delete|where|drop table|show tables|#|\*|--|\\\\)/"),"",$sql); //remove palavras que contenham a sintaxe sql
$seg = trim($seg); //limpa espaços vazios
$seg = strip_tags($seg); // tira tags html e php
$seg = addslashes($seg); //adiciona barras invertidas a uma string
return $seg;
}@jquerymagazine.com.br, nem todas as injections são baseadas em aspas..
porque substituir as keywords do mysql ?
há algum motivo em especial ?
se o cara mandar um eval, base64, isso ai vai passar batido ..
@Andrey Knupp
Mas eu não falei que são baseadas em aspas.
Tanto é que falei para usar regex
Por isso eu falei, o pessoal usa a function tal.
Eu uso regex !
ótimo, agora vou me referir a você ..
porque substituir N keywords de sql ? ;)
Novamente respondo eu uso regex,
Até porque se for um campo busca e o pessoa digitar
algum assunto sobre drop, a mesma não irá funcionar.
Só coloquei ela pois nesses ultimos posts do forum
tem um usuario que postou em seu fonte.
eu não perguntei oque você usa :P
eu te perguntei o 'motivo' de substituir ..
não vejo sentido algum em substituir essas keywords..
mesmo porque não são maliciosas se você fazer uma boa varredura na query
antes de enviar pro sgdb ..
tenho db, que tem senha com 'select' no meio .. :o
( sem ofensas )
Deleu utilize PDO com prepare que não terá problemas.
>
Deleu utilize PDO com prepare que não terá problemas.
Terá sim, o PDO não meche na query pra sua informação ;)
o prepare é apenas pra fazer um casting com bindValue ou Param ou column ..
Tb acho inutil, só postei pois na preguii catei daqui
http://forum.imasters.com.br/topic/434365-problema-com-validacao-de-login-em-php/
>
Note:
Emulated prepared statements does not communicate with the database server so PDO::prepare()
does not check the statement.
Andrey Knupp, então posta a solução para o Deleu que ele ta precisando, já que você ta corrigindo todo mundo.
>
Andrey Knupp, então posta a solução para o Deleu que ele ta precisando, já que você ta corrigindo todo mundo.
Não.
Não estou corrigindo todo mundo não, apenas falando sobre oque ele tem que se prevenir
e compartilhando oque eu sei ..
a minha solução, que eu mesmo próprio uso
eu verifico se tal string é base64
se for, eu faço um decode dessa string, só dai então vai pra um filter ..
Muitas vezes vemos em vários lugares regex e mais regex para evitar SQL injection, e sabemos que um simples mysql_escape_string() não resolve absolutamente nada, além de ser falho e ter que ficar dando stripslashes na hora de resgatar os dados. Mas, como nosso amigo PDO veio para facilitar nossa vida, ele faz isso por nós, usando prepared statements! Elas evitam qualquer injeção de forma eficaz e te poupa linhas de código além de ser mais rápido que regex.
Gente, apesar de eu ter usado o título como 'SQL Injection', quero me referir a todo o sistema. No sistema de login, imagino que seja importante remover tags PHP, HTML, JavaScript, Pascal, Binário, Linguagem da calculadora, etc.
Porém, a questão, para mim, é em relação ao sistema como um todo. Fiz alguns testes e, usando mysql_real_escape_string eu consegui gravar, via post, a seguinte linha:
"SELECT * FROM tbnome WHERE id = $_SESSION['index_Variavel']";
Chegou ao banco exatamente como tá aqui, quando removi a função, o SQL deu erro na execução. Daí surge a dúvida: um campo cujo grava uma linha de código dessas poderá ser prejudicial para o sistema? Particularmente, acredito que não.
Não quero remover palavras-chave do SQL porque pode ser que eu precise guardá-las no banco, o foco mesmo é ter certeza de que não vou jogar performance fora ao fazer com que meu sistema passe por essa função toda vez que eu for inserir uma string no banco.
@Andrey
Então seria isso
BASE64
Essa criptografica eu gosto muito… Se chama base64 e é um método para codificação dos dados para transferência na Internet. Ela é uma codificação de mão dupla, e usando uma segunda função você pode descobrir a string original de uma string codificada.
Para usar ela no PHP você tem as duas formas:
$string = 'O rato reu a ropa do rei de Roma';
$codificada = base64_encode($string);
echo "Resultado da codificação usando base64: " . $codificada;
// TyByYXRvIHJldSBhIHJvcGEgZG8gcmVpIGRlIFJvbWE=
echo "<br /><br />";
$original = base64_decode($codificada);
echo "Resultado da decodificação usando base64: " . $original;
// O rato reu a ropa do rei de Roma
// Note que $original vai ser idêntica a $string
>
Muitas vezes vemos em vários lugares regex e mais regex para evitar SQL injection, e sabemos que um simples mysql_escape_string() não resolve absolutamente nada, além de ser falho e ter que ficar dando stripslashes na hora de resgatar os dados. Mas, como nosso amigo PDO veio para facilitar nossa vida, ele faz isso por nós, usando prepared statements! Elas evitam qualquer injeção de forma eficaz e te poupa linhas de código além de ser mais rápido que regex.
@Adson aquino, olha que legal minha prepared statement !
C:\Users\Andrey>cd ..
C:\Users>cd ..
C:\>cd \dev\mysql\bin\
C:\dev\mysql\bin>mysql -u root -p
Enter password: ******
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.1.41 Source distribution
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> create database injection;
Query OK, 1 row affected (0.01 sec)
mysql> use injection;
Database changed
mysql> create table teste(
-> id int( 11 )
-> )engine = myisam;
Query OK, 0 rows affected (0.08 sec)
mysql> show tables;
+---------------------+
| Tables_in_injection |
+---------------------+
| teste |
+---------------------+
1 row in set (0.00 sec)
PHP, prepared statement !
<?php
$PDO = new PDO( 'mysql:host=localhost;dbname=injection', 'root', '123' );
$PDO->setAttribute( PDO::ATTR_TIMEOUT, 5 );
$PDO->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$id = "0;drop table `teste`";
$query = $PDO->prepare( 'SELECT * FROM `teste` WHERE `id` = '.$id.'' );
$query->execute();
Executei o código, e retornou o seguinte:
mysql> show tables;
Empty set (0.03 sec)
Legal ! ..
@jquerymagazine.com.br
Você tá sugerindo que eu encripte tudo que vem via POST e guarde encriptado e, antes de mostrar ao usuário, desencripte?
@Andrey Knupp
Não entendi o que aconteceu.
Entendi, PUTS...
>
@Andrey Knupp
Não entendi o que aconteceu.
o adson, falou que o PDO evita erros ..
eu nem aspas usei, apenas finalizei uma query
e a tabela que eu tinha criado, foi se pro beleleu
>
@Andrey Knupp
Não entendi o que aconteceu.
Ele deu um sql injection usando PDO, não é a ferramenta que é segura e sim quem cria que tem que deixar seguro, o que acontece se você utilizar um colete a prova de balas errado?
======================================================================================================
Ps: Desculpa não vi o post do Andrey
Amigo do modo que você usou o prepare vai acontecer isso, agora usa ele assim.
$id = "0;drop table `teste`";
$query = $PDO->prepare( 'SELECT * FROM teste WHERE id = :id' );
$query->bindParam(':id', $id, PDO::PARAM_STR);
$query->execute();
Agora executa assim e vê se vai acontecer o mesmo.
Sim, realmente ..
Não tem o mesmo efeito, foi até uma boa dica, eu não via diferença antes
de PDO::query, pra PDO::prepare ..
o bindParam eu já sabia, mais achei que ele fosse apenas um 'replace'
pra as marcações na query, como :id, :nome ..
mais assim, parece que ele faz um handle da string ..
impedindo várias querys .. :P :) ^_^ ;) :joia: :clap:
Então Deleu utiliza do modo que postei acima que não terá problemas.
eu verifico se tal string é base64
Qual seria a melhor maneira para fazer essa verificação?
As variaveis tem que ser tratadas sempre, isso não quer dizer que será mysql_real_escape_string()
Se você está esperando uma variavel do tipo int, verifica se é inteira usa uma regex.
A variavel senha por ex: se você usa um MD5 ou sha1 não tem porque usar mysql_real_escape_string().