Tratamento de dados fornecidos pelo usuário: projetando sistemas com mais segurança

De uns tempos para cá comecei a notar que mais gente está programando e conseqüentemente mais gente está entrando no mercado de trabalho precocemente. Estão iniciando sua viagem pelo maravilhoso mundo do desenvolvimento web muito inocentemente, no entanto não sabem eles - os desenvolvedores newbies ou negligentes - que existem usuários maliciosos olho no seu sistema.

[ Hits: 87.979 ]

Por: Ragen Dazs em 07/04/2004 | Blog: http://www.orkut.com


Escapando strings



Como você já deve ter percebido, no MySQL e em shell script por exemplo, existem caracteres especiais reservados, tais caracteres são usados em comandos variados como por exemplo aspa, aspas duplas, aspas cruzadas, barras e etc. Todo desenvolvedor deve(ria) tomar muito cuidado principalmente nesse ítem, pois como mostrados nos exemplos anteriores se houvesse um maior cuidado no escapamento de strings nos códigos SQL anteriores eles não estariam mais susceptíveis a ataques de injeção de código.

Logo a seguir veremos algumas formas de escapamento seguindo o manual do PHP e posteriormente do manual do MySQL.

Escapando query strings MySQL em PHP


<?php
$item = "Zak's Laptop";
$escaped_item = mysql_escape_string($item);
printf ("String escapada: %s\n", $escaped_item);
?>

O exemplo acima deve produzir a seguinte saída:

String escapada: Zak\'s Laptop

Em outras palavras, os caracteres \' são formatados de tal maneira que o MySQL saberia interpretá-los como texto e não mais como query SQL. Porém esse código ainda não está 100% "impermeável", ele ainda aceita pequenas injeções de código.

Vamos ver agora mais a fundo o que diz o manual do PHP:

mysql_escape_string (PHP 4 >= 4.0.3) -- Escapa uma string para uso com o mysql_query.
Descrição:

string mysql_escape_string ( string unescaped_string )

Esta função irá escapar o unescaped_string, assim será seguro colocá-la na função mysql_query().

Nota: mysql_escape_string() não escapa % e _.

Esta função é idêntica a mysql_real_escape_string() exceto que mysql_real_escape_string() precisa de um identificador de conexão e escapa a string de acordo com o conjunto atual de caracteres atual. mysql_escape_string() não precisa de um identificador de conexão e não respeita o conjunto atual de caracteres.

OBS: Logo abaixo (ítem 3.1.3.3) mostrarei que essa função não é totalmente "segura".

Escapando query strings MySQL em C


Para mostrar que escapamento de strings não é algo referente somente a linguagens focadas principalmente para web como PHP, abaixo segue um exemplo de código em C com uso de escapamento de string.

// Exemplo retirado do manual do MySQL e adaptado para esse artigo
// Mais infos: http://www.mysql.com/doc/en/mysql_real_escape_string.html

#include <stdio.h>
#include <mysql/mysql.h>

#define HOST "localhost"
#define USER "root"
#define PASS "root"
#define DB "teste"

int main(void)
{
    // Declaração de vars
    MYSQL conexao;
    char query[1000],*end;

    // Inicio de conexão
    mysql_init(&conexao);


    if (mysql_real_connect(&conexao,HOST,USER,PASS,DB,0,NULL,0)) {

        printf("Conectado com Sucesso!\n");

        // strmov() - Está função está inclusa na biblioteca mysqlclient
        // e trabalha como strcpy() porém retorna um ponteiro to the terminating null
        // of the first parameter.

        end = strmov(query,"INSERT INTO test_table values( " );
        
        *end++ = '\'';
        
        end += mysql_real_escape_string(&mysql, end,"What's this",11);
        
        *end++ = '\'';
        *end++ = ',';
        *end++ = '\'';
        
        end += mysql_real_escape_string(&mysql, end,"binary data: {TEXTO}\r\n",16);

        *end++ = '\'';
        *end++ = ')';

        if (mysql_real_query(&mysql,query,(unsigned int) (end - query))) {
            fprintf(stderr, "Falha ao inserir célula, Error: %s\n",
            mysql_error(&mysql));
        }
        
        mysql_close(&conexao);
   } else {
       printf("Conexão Falhou\n");
       if (mysql_errno(&conexao)) {
           printf("Erro %d : %s\n", mysql_errno(&conexao), mysql_error(&conexao));
       }
   }

   return 0;
}

// **************
// Para compilar: gcc teste_mysql.c -o teste_mysql -lmysqlclient

Como vocês viram, ambas as funções mysql_escape_string e mysql_real_escape_string escapam os caracteres especiais. A primeira função escapa-os levando em conta o atual conjunto de caracteres da conexão, já o segundo você pode especificá-los assim como o handle de sua conexão, em outras palavras, "assim é seguro coloca-la em mysql_query()" SEGUNDO os manuais do PHP e MySQL. Porém ambos frisam que eles não escapam os caracteres % e _, mas com isso por exemplo alguém mal intencionado poderia criar um robot para roubar todas as informações do seu banco de dados - Algo similar aconteceu com a catho, site de currículos na web. Mas não me aprofundarei nesse assunto, por que seria necessário outro artigo somente sobre isso...

Página anterior     Próxima página

Páginas do artigo
   1. Início
   2. Descrição do ambiente
   3. Tratando dados
   4. O que são códigos arbitrários
   5. O que é SQL injection
   6. Escapando strings
   7. Coringas e meta caracteres
   8. Escapando argumentos em shell
   9. O que são casts
   10. Denial of Service em sua página
   11. Cross site script
   12. Explorando falhas locais
   13. Agradecimentos
Outros artigos deste autor

Entendendo um pouco sobre os daemons

O comércio eletrônico e o Linux

PHP 6.0 - Você está pronto?

DotGNU: a resposta Open Source ao dotNET

Projeto Icecream (parte 1)

Leitura recomendada

Monitoramento de redes com o Zenoss

Entendendo as permissões no Linux

Framework OSSIM - Open Source Security Information Management

Firewall com Iptables + Squid

Criptografia com Loop-AES

  
Comentários
[1] Comentário enviado por gustavo_marcon em 07/04/2004 - 19:19h

Cara, muito legal mesmo teu artigo, só achei que vc poderia ter dado uns toques de comandos que podem ser usados pra evitar por exemplo o SQL Injection, mas no mais, tá 10 mesmo. Parabéns.

[2] Comentário enviado por Ragen em 08/04/2004 - 00:31h

Olá Gustavo,

Note que logo abaixo de "O que é SQL injection" tem o que você quer "Escapando Strings", nessa parte é abordado como evitar os bendidos códigos maliciosos...

Só queria fazer mais um pequeno comentário:

Na parte onde eu falo sobre netcat eu fiz algumas pequenas mudanças desde a data de publicação do arquivo, por que eu deixo o assunto muito vago e sem nenhum exemplo concreto do seu uso....

Esse mesmo artigo pode ser encontrado em http://www.florecultura.com.br/bkp/artigo_tratamento.txt

[]`s

Ragen

[3] Comentário enviado por fabio em 11/04/2004 - 14:39h

Putz, acabou que com uma dica sua resolvi de forma trivial um problema que tinha no sistema de busca interno do site. Por exemplo, se você digitasse "sites celular" nada era encontrado. Daí mandei o sistema substituir espaços por %, agora buscas com palavras compostas funcionam. :)

Valeu pela dica!!!


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts