Desafio da Semana #8



 


DESAFIO DA SEMANA #8


 


 


Por: Roberto Alexis Farah


 


Olá pessoal!


O desafio de hoje trata de uma potencial falha de segurança que pode ocorrer em aplicações. Apesar disso o nosso foco não será no lado de segurança em si.


 


 


CENÁRIO


 


Imagine que um cliente o chama para ajudar a diagnosticar uma aplicação console que é chamada por outra aplicação.


Portanto, embora a aplicação possa ser usada manualmente, chamando-a pela linha de comando, ela pode, também, ser chamada por outra aplicação.


A aplicação console no nosso exemplo não faz nada de útil, apenas salva o conteúdo fornecido como linha de comando num buffer interno, desde que o tamanho dos dados seja menor que o tamanho do buffer interno, apenas para simplificar o cenário.


 


O formato usado é:


 


– primeiro parâmetro é o tamanho do buffer. Basicamente o tamanho da string a ser fornecida no segundo parâmetro.


– segundo parâmetro é o conteúdo, ou seja, a string propriamente dita.


 


Exemplo de uso:


 


App.exe 25 “isto e’ um teste”              ß Nada será salvo pois 25 é maior que o buffer interno. Msg é mostrada.


App.exe 6   “isto é um teste”              ß O buffer interno será preenchido, mas com os 6 primeiros caracteres iniciais.


 


Para gerar a aplicação, crie uma aplicação console no Visual C++ usando esse código e os necessários arquivos de header:


 


#define BUFFER_SIZE 10


 


int main(int argc, char* argv[])


{


        if(argc < 3)


        {


                return 0;


        }


       


        int nLen = 0;


       


        // Nao assumir string com NULL terminator.


        // Por isso usei ‘cBuffer’ ao inves de ‘pszBuffer’.


        char cBuffer[BUFFER_SIZE]; 


       


        nLen = atoi(argv[1]);


       


        if(nLen < BUFFER_SIZE)


        {


                memcpy(cBuffer, argv[2], nLen);


        }


        else


        {


                printf(“Muita informacao para copiar…\n”);


        }


       


        return 0;


}


 


 


SINTOMA


 


Crash intermitente de aplicação.


Nota: O sintoma poderia se manifestar de outro modo, talvez bem mais discreto.


 


 


OBJETIVO


 


Identifique o PROBLEMA ocasionando o intermitente Crash de aplicação e proponha uma SOLUÇÃO.


 


 


 


 

Comments (2)

  1. Marcelo Cortes says:

    PROBLEMA:

    O crash vai ocorrer nesse programa apenas quando memcpy for executado com um número de caracteres a serem copiados muito grande, o que vai causar "access violation".

    A pergunta é: o programa está testando o tamanho do buffer passado pelo usuário antes de executar memcpy, seria impossivel de passar um buffer muito grande para memcpy?

    A resposta é simples: Executando o programa com um número negativo como primeiro parâmetro.

    Um número negativo vai passar pelo nosso teste:

    "if(nLen < BUFFER_SIZE)"

    E quando memcpy for executado:

    memcpy(cBuffer, argv[2], nLen);

    O parametro nLen vai ser convertido de int para size_t de acordo com a descrição do método memcpy na MSDN:

    void *memcpy(void *dest, const void *src, size_t count);

    Ao ser convertido de negativo para size_t (que é unsigned), o valor vai ser provavelmente enorme (se o valor negativo for pequeno), o que causará o crash.

    O desafio foi muito bom, e muitos programadores escrevem programas com essas pequenas falham que parecem ser simples e impossiveis de acontecer, mas são essas falham que crackers e hackers exploram para violar programas e sistemas.

    SOLUÇÃO

    A solução é bem simples, basta converter a variavel nLen de int para "unsigned int" e nosso teste if(nLen < BUFFER_SIZE) vai ser eficiente sempre.

  2. Roberto Farah says:

    Marcelo, sua resposta está corretíssima! Parabéns e continue participando.

    Hoje estarei postando minha resposta onde detalho como o problema ocorre.

    Obrigado