Este documento apresenta conceitos sobre filtragem e validação de strings em aplicações. Ele discute as abordagens de "lista negra" e "lista branca" para lidar com dados recebidos, recomendando a abordagem de lista branca por ser mais segura. Também aborda a importância da coerência dos dados e casos mais complexos que não se encaixam perfeitamente nas duas abordagens.
1. Preto, Branco e
as Sombras de Cinza:
Filtrando e Validando Strings
CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott – 2010-11-23 – 1 / 16
2. Objetivo
Esta apresentação tem por objetivo apresentar conceitos e soluções para a
questão de tratamento de strings, o tipo de dado mais complexo que podemos
encontrar ao receber dados em uma aplicação.
Serão apresentados os seguintes tópicos:
● O que é Filtragem
● O que é Validação
● Dados de tipos específicos
● Dados com máscaras pré-definidas
● Opções de abordagens de Validação e Filtragem
● Vantagens e desvantagens de cada abordagem
● Exemplos práticos
Embora teoricamente esta apresentação sirva para linguagens em geral, os exemplos
serão apresentados em PHP.
CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott – 2010-11-23 – 2 / 16
3. O que é Filtragem
Filtragem é a transformação de um dado, substituindo, removendo e/ou adicionando
um ou mais caracteres, de forma que:
● O Dado assuma o tipo esperado
● O formato do Dado se torne compatível com a máscara de dados esperada
● O valor do Dado possua apenas caracteres legítimos
CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott – 2010-11-23 – 3 / 16
4. O que é Validação
Validação é o processo pelo qual ocorre uma decisão baseada em uma condição. É
o teste feito em cima de um dado recebido, decidindo se o dado é ou não válido, através
de uma ou mais comparações:
● O tipo do Dado é o tipo esperado
● O valor do Dado está entre os valores esperados
● O formato do Dado é compatível com a máscara de dados esperada
● O valor do Dado é coerente
CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott – 2010-11-23 – 4 / 16
5. Como proceder
Ambos os processos (Validação e Filtragem) se completam ao tratarmos de um dado
externo à nossa aplicação. O primeiro processo a ser aplicado deve ser o de Filtragem.
Após a transformação do dado devemos então realizar a Validação final.
CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott – 2010-11-23 – 5 / 16
6. Abordagens
Existem duas abordagens para seguir no momento de realizar qualquer um dos dois
processos:
● Black List, ou “Lista Negra” : É o processo pelo qual definimos caracteres, substrings
e/ou formatos inválidos para o dado.
Exemplos:
“A aspa simples é um caractere inválido”
“O sinal de maior e o sinal de menor são caracteres inválidos”
● White List, ou “Lista Branca”: É o processo pelo qual definimos caracteres, substrings
e/ou formatos válidos para o dado.
Exemplos:
“Somente letras são considerados caracteres válidos”
“Somente números são considerados caracteres válidos
CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott – 2010-11-23 – 6 / 16
7. Black List
A abordagem de Black List é extremamente comum, mas traz problemas que nem
sempre são óbvios. Num primeiro olhar usar Black List parece, sem sombra de dúvida,
a coisa certa a fazer:
+ É aparentemente lógico;
+ Os casos especificados são seguramente tratados;
+ Nível de dificuldade “fácil”
Quando se reflete melhor as coisas começam a se tornar mais claras:
– É comum ignorarmos casos, por engano ou esquecimento;
– É extremamente complexo prevermos todas as formas de representar um caractere;
– Em casos de aplicações que implementem i18n e l10n a complexidade aumenta
CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott – 2010-11-23 – 7 / 16
8. Black List
Exemplos clássicos de uso equivocado de Black List:
● htmlentities:
● Não considera caracteres como: / - ! |
● Em certo ponto é preciso fazer o processo inverso, tornando a aplicação igualmente
vulnerável
● addslashes/addcslashes:
● Não considera representações como URL encoded, por exemplo
● preg_replace('/select|insert|update|delete/', '', $str):
● Não considera dezenas de outros comandos como: grant, create, revoke, drop, etc...
● Em textos na língua inglesa impede o uso legítimo dos termos
CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott – 2010-11-23 – 8 / 16
9. White List
A abordagem de White List é, via de regra, a coisa certa a se fazer. Ela parece possuir
um grau maior de dificuldade (e às vezes isso até é verdade), mas em contrapartida é em
geral muito mais segura e precisa do que o uso da Black List.
+ É mais fácil definir o que é válido, reduzindo ou eliminando a possibilidade de erros;
+ Apenas os casos especificados são tratados;
+ Independente de representação;
+ Independente de i18n e l10n
A “dificuldade” em se implementar uma abordagem White List é ilusória. Na verdade
o que acontece é que precisamos realizar processos com os quais não estamos
acostumados:
● Conceitualizar o dado
● Definir seu tipo, valor, formato e regra de coerência
● Dedicar tempo ao planejamento
CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott – 2010-11-23 – 9 / 16
10. White List
Exemplos comentados de uso de White List
Exemplo #1 – Aceitar apenas números
if (!preg_match('/^d+$/'), $str) {
die('Dado inválido!');
}
Exemplo #2 – Dados numéricos
if (!(int)$str) {
die('Dado inválido!');
}
CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott – 2010-11-23 – 10 / 16
11. White List
Exemplo #3 – Data, no formato dd/mm/aaaa
if (!preg_match('/d{1,2}/d{1,2}/d{4}$/'), $str) {
die('Dado inválido!');
}
Exemplo #4 – Números de telefone
if (!preg_match('/^(d{2})s*d+-*d+$/'), $str) {
die('Dado inválido!');
}
CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott – 2010-11-23 – 11 / 16
12. Coerência
Alguns dados necessitam ser coerentes, como o exemplo das datas. A coerência é
parte importantíssima do processo de validação. Embora muitas vezes dados incoerentes
não comprometam a segurança da aplicação diretamente não há sentido em armazenar
informações inúteis.
Não esqueça: a aplicação, além de segura, deve ser eficiente!
Alguns exemplos:
Datas de Nascimento:
- Obrigatoriamente no passado
- Obrigatoriamente com um limite máximo
- Opcionalmente com um limite mínimo
Datas de Agendamento:
- Obrigatoriamente no futuro
- Obrigatoriamente com um limite máximo
- Obrigatoriamente com um limite mínimo
- Obrigatoriamente dependentes de disponibilidade
CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott – 2010-11-23 – 12 / 16
13. Coerência
Validação coerente de datas? Pura matemática! Com a Unix Timestamp fica simples
de fazer a maioria das verificações do slide anterior. Veja o exemplo:
Exemplo #5 – Data no passado e dentro do limite
$limite = 18 * 3600 * 24 * 365;
$data = mktime(0, 0, 0, $mes, $dia, $ano);
if ((time() - $data) < $limite) {
die('Apenas para maiores!');
}
CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott – 2010-11-23 – 13 / 16
14. Nem Black List, “nem White List”
E se não pudermos aplicar nenhum dos dois conceitos? Se eu quiser, por exemplo,
permitir algumas tags HTML em um texto enviado pelo usuário?
Tecnicamente usaremos quase uma abordagem White List para isso, mas é um
exemplo bem mais complexo do que vimos até o momento. Além disso precisamos
identificar, dentro do dado recebido, o que é tag HTML e o que não é.
É justamente nesse ponto que reside a complexidade da situação. Se usarmos uma
rotina flexível demais corremos o risco de “censurar” conteúdo legítimo – por processar
texto comum na informação – ou de deixarmos a aplicação vulnerável.
O método que explicarei aqui é uma sugestão simplificada. Ele está longe, bem longe
da perfeição, inclusive possuindo falhas graves que comentarei aqui.
Se você achar uma solução melhor compartilhe!
CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott – 2010-11-23 – 14 / 16
15. Nem Black List, “nem White List”
Exemplo #6 (simplificado e falho) – Encontrando e limitando tags XHTML
$validTags = array('table', 'thead', 'tbody', 'tfoot', 'tr', 'th', td');
preg_match_all('/<[a-z]+/', $str, $foundTags);
foreach ($foundTags[0] as $tag) {
if (!in_array(substr($tag, 1), $validTags)) {
die("Tag invalida: $tag");
}
}
Uma forma mais complexa e mais segura seria a análise caractere-a-caractere. Cada
código numérico de cada caractere seria então comparado ao código numérico do sinal de
menor, seguido de letras e outros caracteres típicos de tags XHTML, seguido por uma
forma de fechamento (barra seguida do nome da tag ou barra seguida do sinal de maior).
O que é realmente importante neste exemplo é a definição da White List (o array
do início).
CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott – 2010-11-23 – 15 / 16
16. OBRIGADO!
Sobre o Autor:
Er Galvão Abbott trabalha há mais de 15 anos
desenvolvendo sistemas e aplicações com interface web.
Palestra em eventos, dá cursos em diversas instituições e
faz parte da organização da PHP Conference Brasil e do
Fórum de Software Livre de Curitiba.
Especializou-se em segurança de aplicações web,
abordando o tema em uma época quando isso ainda era raro no
Brasil. Trabalhou com diversas empresas de grande parte, tanto
nacionais como internacionais.
Site: http://www.galvao.eti.br/
Twitter: @galvao
Slides e Documentos: http://slideshare.net/ergalvao
CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott – 2010-11-23 – 16 / 16