Ir para conteúdo

POWERED BY:

Arquivado

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

Wilian Fiabani

Segurança em PHP

Recommended Posts

Pessoal, essa dá p/ dizer q é facil de mais, mas vamos lá....

 

como filtrar os dados recebidos de um formulário?

 

ou seja, você recebe do user uma string qualquer e remove tudo o que for indesejado, como (', ", <script>), só aceitando caracteres maiusculos, minusculos e numeros.

 

o usuário envia: ' or 1='1

e você devolde: or11

 

entenderam?

 

eu já fiz o meu aqui, no final eu mostro.

Compartilhar este post


Link para o post
Compartilhar em outros sites

function sqlinj($s) {

$s = addslashes($s);

$s = htmlspecialchars($s);

$s = str_replace("SELECT","",$s);

$s = str_replace("FROM","",$s);

$s = str_replace("WHERE","",$s);

$s = str_replace("INSERT","",$s);

$s = str_replace("UPDATE","",$s);

$s = str_replace("DELETE","",$s);

$s = str_replace("DROP","",$s);

$s = str_replace("DATABASE","",$s);

$s = str_replace("USE","",$s);

return $s;

}

=D

Compartilhar este post


Link para o post
Compartilhar em outros sites

Um detalhe: "só aceita caracteres maiusculos, minusculos e numeros". Essa function está aceitando outros caracteres tbm.

 

Uma dica: Se você usar htmlspecialchars() não precisa usar addslashes(), assim você ganha em desempenho.

 

valew pelo post narizgudo!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Vlw pela dica =D

 

Eu fiz um teste aqui e olha soh o resutlado

 

echo addslashes(htmlspecialchars("' or 1=1")); // mostra >> \' or 1=1
echo htmlspecialchars("' or 1=1"); // mostra >> ' or 1=1

Se eu tirar o addslashes eu nao escapo ' nem " e nem outros caracteres especiais

 

function sqlinj($string) {
	$string = strip_tags($string);
	$string = htmlspecialchars($string);
	$string = addslashes($string);
	$string = str_ireplace("SELECT","",$string);
	$string = str_ireplace("FROM","",$string);
	$string = str_ireplace("WHERE","",$string);
	$string = str_ireplace("INSERT","",$string);
	$string = str_ireplace("UPDATE","",$string);
	$string = str_ireplace("DELETE","",$string);
	$string = str_ireplace("DROP","",$string);
	$string = str_ireplace("DATABASE","",$string);
	$string = str_ireplace("USE","",$string);
	return $string;
}

vê se ta melhor

Compartilhar este post


Link para o post
Compartilhar em outros sites

a htmlspecialchars() converte as ' em ' (se ENT_QUOTES for passado como segundo parâmentro na função), segundo a documentação do php, por isso que addslashes() não seria necessário, mas tudo bem.

 

aqui está o código do filro de dados ideal:

CODE

class Utils{

 

//caracteres permitidos

public static $chars = "1234567890abcdefghijlmnopqrstuvxzwykABCDEFGHIJLMNOPQRSTUVXZWYK";

 

//remove qualquer tipo de ataque

public static function secure($str){

$str = (string) $str; //obtem a string do parametro recebido

$arr_str = str_split($str); //quebra a string em um array

$num_chars = count($arr_str); //tamanho da string, poderia ser strlen($str) tambem

$new_str = ""; //cria uma nova string, que sera retornada

for($i=0 ; $i<$num_chars ; $i++){

if($arr_str[$i] !== ""){ //se a array nao é vazia

if(strpos(self::$chars , $arr_str[$i]) !== false){ //a string pertence ao conjunto permitido

$new_str .= $arr_str[$i]; //adiciona o caracetere a string q sera retornada

}

}

}

return($new_str); //retorna a string

}

}

 

assim você só pega os dados de um form e:

$data = Utils::secure($_POST['data']);

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bem, lá vai o meu:

 

$filtracao= getenv('REMOTE_ADDR');
$badwords =array(";","'","\"","*","union","del","DEL","insert","truncate","update","drop","sele","memb","set","$","wareh","%","--","+");
  foreach($_POST as $value)
  foreach($badwords as $word)
  if(substr_count($value, $word) > 0)
  die ("<center><ul><li><font color='red'><b>[ERRO]- Alerta:  Caracteres inválidos.</b></font>
  </li>
  </ul>
  </center>");
Basta colocar no início do documento, assim todo caractere inválido que form enviado pelo metodo POST será impedido de acordo a regra. :D

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bem, lá vai o meu:

 

$filtracao= getenv('REMOTE_ADDR');
$badwords =array(";","'","\"","*","union","del","DEL","insert","truncate","update","drop","sele","memb","set","$","wareh","%","--","+");
  foreach($_POST as $value)
  foreach($badwords as $word)
  if(substr_count($value, $word) > 0)
  die ("<center><ul><li><font color='red'><b>[ERRO]- Alerta:  Caracteres inválidos.</b></font>
  </li>
  </ul>
  </center>");
Basta colocar no início do documento, assim todo caractere inválido que form enviado pelo metodo POST será impedido de acordo a regra. :D

belo código cara, a lógica é +/- essa, só q ali tu tá dando um die(), o que tem q fazer segundo desafio é receber os dados do form, tirar as impurezas e utilizar somente os caracteres validos, sem interromper a execução do script.

 

ou seja, o user manda nome='<script>alert(\'oi mundo\');</script>' você filtra isso usando apenas nome='scriptalertoimundoscript';

com mais umas linhas de código você consegue, tá no caminho fera http://forum.imasters.com.br/public/style_emoticons/default/grin.gif valew, t

Compartilhar este post


Link para o post
Compartilhar em outros sites

Fácil amigo, basta juntar com a função que o Fabyo fez,ou com o do narizgudo, segue abaixo:

limpar.php

function anti_injection($sql)
{
 // remove palavras que contenham sintaxe sql
 $sql = preg_replace(sql_regcase("/(from|select|insert|delete|where|drop table|show tables|#|\*|--|\\\\)/"),"",$sql);
 $sql = trim($sql);//limpa espaços vazio
 $sql = strip_tags($sql);//tira tags html e php
 $sql = addslashes($sql);//Adiciona barras invertidas a uma string
 return $sql;
 }

 //modo de usar pegando dados vindos do formulario
 $nome = anti_injection($_POST["nome"]);
 $senha = anti_injection($_POST["senha"]);

 ?>
protecao.php

$badwords=array(";","'","\"","*","union","del","DEL","insert","truncate","update","drop","sele","memb","set","$","wareh","%","--","+");
  foreach($_POST as $value)
  foreach($badwords as $word)
  if(substr_count($value, $word) > 0){
  (file_exists('limpar.php')) ? (require('limpar.php')) : false;
  anti_injection($_POST['data']);
  }

Compartilhar este post


Link para o post
Compartilhar em outros sites

<?php
$input = "' or 1='1";

// Caracteres do mal
$badchars = str_split(" '*$\"\\=+-><@#%¨&{}[]");

// Strings do mal
$badstrings = array();
//UPERCASE
$badstringsu [] = 'SELECT';
$badstringsu [] = 'INSERT';
$badstringsu [] = 'UPDATE';
$badstringsu [] = 'TRUNCATE';
$badstringsu [] = 'DROP';
$badstringsu [] = 'USE';
$badstringsu [] = 'CREATE';
$badstringsu [] = 'RESET';
//LOWER
$badstringsl = array();
foreach($badstringsu as $k => $vstr) { $badstringsl []  = strtolower($vstr); }

// Reune todos os caracteres invalidos
$invalid = array_merge($badstringsu,$badstringsl,$badchars);

// Substitui todos os invalidos por ''
foreach($invalid as $v) {
	$output = str_replace($invalid,'',$input);
}

echo $output;

?>

Ainda não tive tempo de estudar esse assunto direito, fiz isso aí no improviso. Portanto, NÃO USE ESTE CÓDIGO

 

 

mas o objetivo foi cumprido, a saída é como a do desafio.... hehehehe....

 

Só não entendi pra que invalidar o '='...

 

 

[ADICIONADO EM 2/5/2008:]

Bom, estudando melhor o assunto, achei melhor:

- retirar as tags PHP e HTML

- usar regexp, mas não para retirar os caracteres ruins, mas sim selecionar somente os que eu permito, para isso usei a seguinte exp: [^a-z0-9]

- não retirar palavras reservadas do SQL: SELECT, UPDATE, etc.

 

$input = "' or 1='1";

$input = strip_tags($input); // retirar tags php

$output = eregi_replace("[^a-z0-9ã-õá-úà-úãõâ-ûç,.;]", '', $input);

echo $output;

É isso.

Compartilhar este post


Link para o post
Compartilhar em outros sites

humm também ficou legal mangakah...

vou fazer um ante SI (sql injection) com class, e depois vou fazer um teste pra ver no que da.

abraço.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Tipo, vocês estão retirando algumas coisas que se vier de uma textarea vai quebrar a formatação de algum usuário.

 

Se colocar apenas uma barra invertida na frente desses caracteres já não inibe o slqinjection?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Tipo, vocês estão retirando algumas coisas que se vier de uma textarea vai quebrar a formatação de algum usuário.

 

Se colocar apenas uma barra invertida na frente desses caracteres já não inibe o slqinjection?

na verdade esse script serviria para limpar os dados de um textfield de login. em um textarea certamente surgirão alguns poréns. a contra-barra antes dos caracteres não resolve muito, a não ser na frente de aspas simples. eu diria não resolve muito, por que ai não ocorre o controle de ataques xss csrf, etc...

 

A retirada do '=' em particular não acarreta problemas, assim como a existência de outras expressões tbm não tem muita influência, como por exemplo o '@'.

Compartilhar este post


Link para o post
Compartilhar em outros sites

concordo com Andre Cocuroci

 

nao há necessidade em limitar muitas expressões

 

basta evitar os escapes pois são eles que permitem as injeções

 

o importante é "evitar que a agulha penetre na veia". conseguindo isso não precisa se preocupar com o "conteúdo da seringa".

 

uma dica para evitar injeções é filtrar caracteres no formato ASC

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eu tive esse problema, to mandando um site pessoal, onte vou falar de programacao e vou deixar os visitantes enviarem seus códigos,

eis o problema, como deixar que mandem códigos sobre PHP, MySQL, JavaScript (Futuramente + linguagens) sem sofre com Injection e sem destruir o código enviado?

 

<?

function sqlinj($string,$substituicao = true) {

if ($substituicao) {

$string = strip_tags($string);

$string = preg_replace("'(SELECT|FROM|WHERE|INSERT|UPDATE|DELETE|DROP|DATABASE|USE)'","",$string);

}

$string = htmlspecialchars($string,ENT_QUOTES);

return $string;

}

?>

é login? $login = sqlinj($login);

é código? $codigo = sqlinj($codigo,false);

 

* O uso do htmlspecialchars junto ao addslashes é pq ainda nao estudei a fundo vulnerabilidades de um ou de outro

 

Ate a próxima =D

Compartilhar este post


Link para o post
Compartilhar em outros sites

eis o problema, como deixar que mandem códigos sobre PHP, MySQL, JavaScript (Futuramente + linguagens) sem sofre com Injection e sem destruir o código enviado?

basta escapar as aspas..

 

exemplo

 

<?php

function addslashes_deep( $value )
{
	$value = is_array( $value ) ?
		array_map( 'addslashes_deep', $value ) :
		addslashes( $value );
	return $value;
}

function arrJoin( $v ){
return implode( chr(13), $v );
}

function onlyNumber( $string ){
	$rs = '';
	if( $string != '' && !is_array( $string ) ){
		$string = mb_convert_kana( $string, 'n' );   // http://php.net/mb_convert_kana

		$allowed = "/[^0-9]/i";
		$rs = preg_replace( $allowed, '', $str );
	}
	return $rs;
}

function sqlClear( $rs, $opt ){

	switch( $opt ){
		case 'string';
			$rs = "'" . addslashes_deep( trim( $rs ) ) . "'";
		break;
		case 'number';
			$rs = onlyNumber();
		break;
	}

	return $rs;

}


$test1 = "teste";
$test2 = "'; DROP table;--"; // simulando uma injeção...

$values[] = sqlClear( $test1, 'string' );
$values[] = "," . sqlClear( $test2, 'string' );

$fields[] = "filed1";
$fields[] = ", field2";

$sql[] = "INSERT INTO";
$sql[] = " table ";
$sql[] = " ( " . arrJoin( $fields ) . " ) ";
$sql[] = " VALUES ";
$sql[] = " ( " . arrJoin( $values ) . " );";

echo arrJoin( $sql );

?>

Compartilhar este post


Link para o post
Compartilhar em outros sites

utilizo essa pessoal:

 

function tratadados()
{
	//pega os argumentos
	$argumentos = func_get_args();
	//pega o numero de argumentos inseridos
	$quantidade_argumentos = func_num_args();
	
	for($cont=0;$cont<$quantidade_argumentos;$cont++)
	{
		$resultado[$argumentos[$cont]] = trim($_POST[$argumentos[$cont]]);
		$resultado[$argumentos[$cont]] = strip_tags($resultado[$argumentos[$cont]]);
		$resultado[$argumentos[$cont]] = addslashes($resultado[$argumentos[$cont]]);
	}
	return $resultado;
}

ela trabalha com quantidade de argumentos da função indefinidos e é especifica pra usar com formulario, observem o post lá dentro. Ou seja se você tiver um formulario com os campos nomes, sobrenome, endereco (issos sao os names de cada campo), você insere os nomes dos campos do seu formulario ... ou seja, pode chamar a função com 2, 10, 100 argumentos. Ex:

 

formulario

<form>
<input type='text' name='nome'>
<input type='text' name='sobrenome'>
<input type='text' name='endereco'>
</form>

poderia chamar com diferentes argumentos:

tratadados(nome,sobrenome,endereco);
tratadados(nome);

ela volta um vetor com nome das variaveis inseridas:

 

$dados = tratadados(nome,sobrenome,endereco);

$dados['nome']
$dados['sobrenome']
$dados['endereco']

outra coisa tb, e verificar sempre todos os dados de formulario, mesmo os fixos, como <option> <select>, e se forem valores numericos pode-se economizar tempo verificando simplesmente se ele é numerio com floatvar(), no caso:

 

$var = '123.321 php';
$var = floatval($var);
echo $var;
//saida 123.321

Compartilhar este post


Link para o post
Compartilhar em outros sites

Diogo Lana resumindo sua função irá tratar mas ira retornar \\\ caso a pessoa digite exemplo ' ou " ou seja vai inserir no banco de dados, creio que juntando sua função mas outra que faça a detecção e informe que aquele campo tem caracteres creio que seja ideal, teria como você adaptar na sua função para poder limitar caracteres exemplo -- não pode - pode, * não pode, e por ai vai assim a pessoa alem de tratar o erro ainda bloquiaria os que não quer ao inves de ter que fazer ao contrario de dizer quais não quer.

 

vlw.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Diogo Lana resumindo sua função irá tratar mas ira retornar \\\ caso a pessoa digite exemplo ' ou " ou seja vai inserir no banco de dados, creio que juntando sua função mas outra que faça a detecção e informe que aquele campo tem caracteres creio que seja ideal, teria como você adaptar na sua função para poder limitar caracteres exemplo -- não pode - pode, * não pode, e por ai vai assim a pessoa alem de tratar o erro ainda bloquiaria os que não quer ao inves de ter que fazer ao contrario de dizer quais não quer.

 

vlw.

mas eu acho que o intuito nao é esse .... limitar caracteres que possam ser usados por uma pessoa normal sem segundas intençoes não e bom, ja que você estaria modificando os dados enviados pela mesma...

 

eu prefiro transformar, (na verdade eu acho que é essa a atitude certa) caracteres possivelmente perigosos em inofensivos, sem modificar/distorcer qq dados ...

Compartilhar este post


Link para o post
Compartilhar em outros sites

mas imagina o pessoal cadastrando

 

* \\\\ ' & ¨% $ # ( ) { [ } ] / ^~`´º

 

fica meio esquezito fora muitas outras coisas, por isso acho o seguinte melhor metodo de evitar injeções e criar funções tradando o que pode ou o que não pode exemplo.

 

Vamos supor um campo de usuário:

 

function checa($string)
{
	$string = preg_match("/^[0-9A-z]*$/i", $string);
	return $string;
}

Ou seja a função a cima só ira permitir letras e numeros evitando assim o inject.

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.