Вы находитесь на странице: 1из 30

FACULDADE DE ENGENHARIA DA UNIVERSIDADE DO PORTO

PROGRAMAO SEGURA
FILIPA FONSECA SANTOS 070509094 JOO DIAS BARBOSA - 070509112

RELATRIO DE PROJETO MESTRADO INTEGRADO EM ENGENHARIA INFORMTICA E COMPUTAO NOVEMBRO DE 2011

Resumo
AS TCNICAS DE PROGRAMAO SEGURA, SO MUITAS VEZES TIDAS EM POUCA CONSIDERAO O QUE LEVA A
VULNERABILIDADES NO CDIGO QUE POSSIBILITAM MUITAS VEZES JANELAS DE ATAQUE E EXPLORAO A UTILIZADORES COM INTENES MENOS CORRETAS. VULNERABILIDADES COMO O BUFFER OVERFLOW, DANGLING

POINTERS OU DOUBLE FREES SO APENAS ALGUNS EXEMPLOS, QUE APESAR DE EM CDIGO SE RESUMIREM A PEQUENOS ERROS OU DISTRAES, QUANDO EXPLORADOS PODEM DAR ORIGEM A CONSEQUNCIAS DRAMTICAS PARA OS SEUS PROPRIETRIOS. NO ENTANTO , EXISTEM ATUALMENTE FERRAMENTAS QUE POSSIBILITAM UMA BOA ANLISE DE CDIGO DE FORMA A DETECTAR VULNERABILIDADES E PREVENIR ASSIM POSSVEIS ATAQUES . A FERRAMENTA VALGRIND UM BOM EXEMPLO DE UM ANALISADOR , E EM SIMULTNEO UMA FRAMEWORK QUE PERMITE CRIAR NOVOS ANALISADORES , MELHORES E MAIS EFICIENTES. NESTE TRABALHO FORAM ESTUDADOS AS PRINCIPAIS VULNERABILIDADES DE CDIGO RESULTANTES DE ERROS DE PROGRAMAO OU PROGRAMAO NO SEGURA, SIMULADOS ATAQUES A ESTAS VULNERABILIDADES E CRIADOS TESTES SOBRE A FERRAMENTA VALGRIND DE FORMA A COMPROVAR O SEU POTENCIAL . P OR FIM , FOI AINDA DESENVOLVIDO UM MANUAL DE BOAS PRTICAS DE PROGRAMAO ,
TENDO EM VISTA CONSCIENCIALIZAR OS PROGRAMADORES E FUTUROS PROGRAMADORES DE CUIDADOS A TER NO DESENVOLVIMENTO DE APLICAES .

ndice
Resumo.......................................................................................................................................... 2 1. 2. 3. a. b. c. 4. Introduo ............................................................................................................................. 4 Programao Segura ............................................................................................................. 5 Vulnerabilidades.................................................................................................................... 6 Buffer Overflow.............................................................................................................. 6 Dangling Pointers ........................................................................................................... 7 Double Free .................................................................................................................... 8 Valgrind ................................................................................................................................. 9 4.1. Pontos Fortes ................................................................................................................... 10 4.2. Pontos Fracos ................................................................................................................... 10 5. Testes .................................................................................................................................. 11 5.1. Testes sobre o Buffer Overflow........................................................................................ 11 5.2. Testes sobre Double Frees ............................................................................................... 16 6. Concluso ............................................................................................................................ 18

Referncias .................................................................................................................................. 19

1. Introduo
Este documento foi desenvolvido no mbito da disciplina de Segurana em Sistemas Informticos do quinto ano e primeiro semestre do curso de Mestrado Integrado em Engenharia Informtica e Computao da Faculdade de Engenharia da Universidade do Porto. O trabalho teve como objectivo o estudo do tema Programao Segura, nomeadamente as principais vulnerabilidades que podem ser encontradas na programao e estudada a ferramenta Valgrind que constitui uma boa soluo para este tipo de problemas. O objectivo deste documento assim fornecer uma viso global do problema, abordagens utilizadas, concluses e resultados obtidos. No presente relatrio consta primeiramente uma abordagem ao tema da programao segura, as vulnerabilidades mais preocupantes e os riscos que podem causar. No captulo seguinte so exploradas as vulnerabilidades do tipo buffer overflow, dangling pointers e double frees fazendo referncia s suas principais causas e consequncias. Seguidamente abordada a ferramenta Valgrind tendo em conta os seus principais pontos fortes e fracos. No seguinte captulo especificado o resultado de testes sob a ferramenta Valgrind de forma a comprovar a sua eficcia face s vulnerabilidades abordadas. Por fim esto presentes breves consideraes finais sobre o trabalho realizado bem como a bibliografia e utilizada no desenvolvimento deste relatrio. ainda apresentado no anexo A um manual de boas prticas de programao desenvolvido de maneira a consciencializar os programadores das vulnerabilidades existentes em cdigo C e C++.

2. Programao Segura
A programao segura uma cincia que muitas vezes no muito abordada uma vez que o desenvolvimento de software 100% seguro nem sempre benfico para as empresas, dado que implica elevados custos cujo benefcio, tendo em conta o tipo de utilizao do programa, muitas vezes pouco significativo uma vez que alguns possveis ataquem tm uma baixa probabilidade de acontecer. ento necessrio para os programadores decidir em primeiro lugar, qual a informao a proteger, e fazer uma anlise do risco que correm ao no implementarem mecanismos de segurana noutros pontos do programa. No entanto, pode por vezes acontecer que funcionalidades menos susceptveis a ataques possam levar explorao de outros pontos importantes do programa. Vulnerabilidades so fraquezas numa aplicao, que podem ser fruto de uma falha de design ou implementao e que, de certa forma, possibilitam uma janela de ataque que permite que um atacante realize operaes maliciosas no programa (danos aos dados, leitura de informao confidencial, injeco de cdigo, etc.) Uma das principais preocupaes em termos de programao segura a proteo de memria, nomeadamente memria de acesso aleatria (RAM). Podem ocorrer vrios tipos de erros de memria, dependo da linguagem de programao usada e algumas das preocupaes exploradas. So exemplo o Buffer Overflow, erros de memria dinmica (Dangling Pointers, Double Frees, Invalid Frees e Null Pointer accesses), variveis no inicializadas (como acontece com os Wild Pointers) e erros de excedncia de memria (Stack Overflow e Allocation Failures). Algumas destas vulnerabilidades vo ser analisadas ao longo deste relatrio, bem como os efeitos nocivos que podem ser originados, no caso de haver a explorao maliciosa durante execuo do programa. Uma programao segura deve garantir os trs seguintes princpios: Integridade: o programa tem um comportamento esperado, de acordo com o especificado nos requisitos e estabelecido nos algoritmos usados. Robustez: as operaes do sistema so resistentes a qualquer tipo de inputs inesperados e a fluxos de aces no comuns. O tratamento de erros eficiente. Segurana: o programa possui propositadamente malicioso. operaes com resistncia a uso

3. Vulnerabilidades
a. Buffer Overflow
Uma das mais comuns anomalias devido a descuidos de programao o Buffer Overflow que diz respeito a irregularidades de memria. Esta anomalia acontece quando um programa, ao escrever informao no buffer, ultrapassa o limite previsto deste e utiliza ento memria adjacente. Tipicamente, este tipo de fragilidade acontece ao copiar cadeias de caracteres de um buffer para o outro. Tipicamente, o buffer overflow ocorre em cdigo que depende de dados exteriores que controlam o seu comportamento ou em cdigo demasiado complexo e difcil de prever todos os seus comportamentos. O seguinte cdigo constitui um exemplo de uma vulnerabilidade possvel de explorar tendo em vista um buffer overflow: char buf[BUFSIZE]; gets(buf); O cdigo depende de dados exteriores para controlar o seu comportamento e utiliza a funo gets() para ler uma quantidade de informao arbitrria para o stack buffer. O problema est na no limitao da informao a ser lida, que apoia-se apenas no bom senso do utilizador. Os atacantes utilizam o buffer overflow de maneira a corromperem a stack de execuo de um programa. Um atacante pode at conseguir tomar posse da prpria mquina. O ataque mais simples do tipo buffer overflow denomina-se stack smashing e consiste em sobrescrever um buffer na stack para substituir o endereo de retorno. Assim, quando a funo retornada, em vez de saltar para o endereo de retorno, ir saltar para o endereo colocado na stack pelo atacante e permitir ento que este execute o cdigo arquitectado pelo atacante. O buffer overflow pode ser explorado e usado por atacantes que pretendem tirar proveito desse tipo de vulnerabilidade ao enviar inputs planeados com o intuito de alterar as funcionalidades de um programa. O resultado destes ataques pode ser visto de diversas formas, nomeadamente: erros de acesso de memria, resultados incorretos, violaes de segurana, loop infinito de um programa. A linguagem de programao C particularmente susceptvel a este tipo de ataques uma vez que na implementao desta foram mais valorizadas as condies de espao e performance do que a de segurana. A linguagem no possui qualquer tipo de controlo sob 6

limites de buffers e a prpria biblioteca standard inclui muitas funes que podem ser inseguras se no forem usadas com as devidas precaues. Apesar disso, muitos programas que requerem cuidados em termos de segurana so desenvolvidos em C. A linguagem C++ tambm uma linguagem de programao que no possui qualquer proteo contra este tipo de ataques. Mas no so apenas estas linguagens de programao afectadas: estas vulnerabilidades podem ser encontradas em servidores web, aplicaes web, cdigo assembly, entre outros. Uma das tcnicas de preveno possvel de utilizar o uso de linguagens seguras, bibliotecas seguras, ou controlo dos limites dos buffers utilizados. A anlise esttica de cdigo tambm uma boa abordagem para detectar vulnerabilidades no cdigo antes de ser executado, como definiram Larochelle D. e Evans D. em [1].

b. Dangling Pointers
Em muitas aplicaes necessrio a alocao de memria para diferentes objetos. Depois da sua utilizao, a aplicao encarrega-se da libertao da memria utilizada, de forma a libertar recursos. Em alguns casos em que so utilizados apontadores para esses objectos, nestas alturas que estes mesmos apontadores ficam a apontar para um objecto que j no est a ser utilizado, ou seja, cuja memria foi j libertada. Estes apontadores so ento denominados de dangling pointers. Se tal acontecer, a aplicao poder entrar num estado de execuo indefinido que pode levar a crashes ou a comportamentos perigosos que podem levar a uma explorao maliciosa por parte de atacantes. Um ataque que pode ser feito atravs da explorao deste tipo de vulnerabilidades a injeco de cdigo. Podendo o atacante colocar o programa com funcionamento indesejvel. Tal pode ocorrer quando o atacante prepara os dados de forma a estes ficarem alocados na posio que havia sido previamente ocupada pelo objecto para o qual o dangling pointer apontava antes da libertao de memria. Fazendo a de-referenciao do dangling pointer, os dados do atacante sero posteriormente interpretados pelo programa como function pointers ,(apontadores utilizados para invocaes a funes) desviando o fluxo do programa para a localizao indicada pelo atacante, podendo este efectuar injeco de cdigo malicioso. (ex: shellcode). Programao orientada a objectos com gesto manual de memria muitas vezes um convite a este tipo de ataques. Os ataques possveis no se limitam apenas alterao do fluxo de controlo do programa. Podem ser tambm atacados atributos dos dados em questo. Apontadores de dados atacados, podem ser explorados de forma a reescreverem informao noutros alvos, se um programa efectua uma escrita de dados atravs de um atributo de um apontador de dados

de um objecto j desalocado, um atacante controlando o contedo da memria do objecto desalocado pode desviar a escrita de dados para uma localizao de memria arbitrria. Outros potenciais ataques prendem-se com fugas de informao, atravs da leitura de dangling pointers que apontam, agora, para informao confidencial. A alterao de privilgios outro dos ataques possveis, atacando campos de dados que possam conter informaes de credenciais de acesso. [2] Algumas linguagens j possuem mecanismos para tentarem eliminar referncias a possveis dangling pointers, removendo o controlo sobre alocaes de memria. Em algumas linguagens a operao de libertao de memria (ex: free() em C) j no existe. Para realizar a desalocao de memria que j no utilizada, so utilizados gestores de memria locais ou garbage collectors (java). Estes mecanismos j previnem automaticamente essas possveis referncias.[3]

c. Double Free
Uma outra vulnerabilidade frequente na programao acontece quando, como o nome sugere, se liberta mais do que uma vez um endereo de memria, ou seja, chamada mais do que uma vez a funo free() com o mesmo endereo de memria como argumento. Este tipo de anomalia pode levar a um buffer overflow. O seguinte cdigo exemplo de um double free: char ptr* = (char*) malloc (SIZE); if(abrt){ free(ptr); } free(ptr); A causa dos double frees muitas vezes devido a milhares de linhas de cdigo em grandes quantidades de ficheiros que torna a anlise destes complicada e como consequncia os endereos de memria podem ser libertados mais do que uma vez sem que o programador tenha conscincia de o ter feito.

4. Valgrind
Valgrind uma framework de desenvolvimento de aplicaes de anlise cdigo e, em simultneo um sistema de deteco de bugs.

Figura 1 - Logotipo Valgrind

O Valgrind pode (e deve) ser usado no desenvolvimento de programas de maneira a detectar de imediato vulnerabilidades de memria. Das ferramentas do Valgrind de salientar a Memcheck que detecta problemas de memria e mais direcionada a linguagens como C e C++ e analisa todos os reads e writes feitos memria. Esta ferramenta a mais adequada s vulnerabilidades abordadas neste relatrio. A ferramenta Cachegrind uma ferramenta que detecta zonas de cdigo onde um programa tem uma m interao com o processador e como consequncia executa mais devagar. Foi melhorada e extendida na ferramenta Callgrind. A ferramenta Massif um analisador da heap que ajuda a reduzir a quantidade de memria que um programa utiliza. Por ltimo, a ferramenta DRD um analisador de threads e procura falhas de sincronizao entre threads de maneira a evitar problemas de dependncias. Atualmente encontra-se na verso 3.7 que acrescenta o suporte para sistemas operativos Android. Para este trabalho, foi escolhido o Valgrind por ser bastante recomendado por diversas fontes na pesquisa feita.

4.1. Pontos Fortes


Esta ferramenta permite encontrar diversos bugs de memria de programas e salvar assim horas de depurao. Para alm disso ajuda a encontrar bottlenecks em cdigo (i.e. partes crticas em termos de consumo de recursos) de maneira a optimizar o cdigo. disponibilizada na totalidade e sem qualquer necessidade de pagamento, para alm de permitir modificaes no cdigo fonte. fcil de usar e instalar. Para instalar basta correr os comandos : ./config, make e make install e para testar o comando: valgring --tool=memcheck program_name. A ferramenta pode ser executada em diversas plataformas como x86/Linux, AMD64/Linux e PPC32/Linux e mais recentemente Android. possvel testar programas escritos em qualquer linguagem, seja ela compilada ou interpretada, uma vez que o analisador atua diretamente sob binrios. No entanto as suas ferramentas esto mais direcionadas s linguagens C e C++, que como j referido, tm menos protees e mais tendncia a bugs. Por ltimo, o Valgrind extensvel, ou seja, permite que programadores criem novas ferramentas a partir das funcionalidades j implementadas.

4.2. Pontos Fracos


O factor mais problemtico a eficincia de um programa ao ser testado no Valgrind que pode diminuir significativamente. O facto de a plataforma no correr em sistemas operativos Windows pode ser visto como uma restrio significativa para muitos programadores. Alm disto existem algumas vulnerabilidades de cdigo que no so verificadas diretamente no Valgrind como a existncia de dangling pointers.

10

5. Testes
De forma a comprovar a eficincia da aplicao foram criados alguns programas de teste e analisados na ferramenta memcheck.

5.1. Testes sobre o Buffer Overflow


Em primeiro lugar foram testados ataques, de maneira a causar o efeito de buffer overflow em dois programas distintos, em Windows. O primeiro programa, escrito em C++, resume-se a um sistema de login.

Figura 2 - userPass.cpp

Como possvel ver na figura acima, o sistema possui uma varivel de autenticao (o inteiro authentication) inicializada a 0 e dois arrays de tamanho 10 para o username e password. Em seguida, utiliza a funo no segura strcpy() para copiar do buffer para os arrays os parmetros introduzidos pelo utilizador: username e pasword respectivamente. Aps copiados, ento feita uma comparao dos parmetros introduzidos com os esperados. Caso o username corresponda a admin e a password corresponda a adminpass a varivel de autenticao alterada para 1. Caso a varivel seja 1 (ou verdadeira), ento permitido o acesso, caso contrrio este negado.

11

Figura 3 - Buffer overflow sobre userPass.exe

Posto isto, foi simulado um ataque ao programa (Figura 3), fazendo com que as variveis fossem sequencialmente alteradas. Assim, como o array cPassword apenas permitia 10 caracteres, os restantes introduzidos foram colocados nas variveis cUsername e cPassword. Por sua vez, a varivel cPassword, agora com o valor diferente de zero, permitiu o acesso ao programa. Esta vulnerabilidade do programa, deveu-se ao uso da funo no segura strcpy() que no verifica os limites a copiar, e como consequncia, pode ser explorada de forma a causa um buffer overflow. Em seguida, foi utilizado o Valgrind para testar o mesmo programa (Figura 4), o resultado, como pode ser visto, na figura a seguir.

Figura 4 Anlise do Valgrind ao programa userPass

12

Como pode ser visto pela mensagem dada pelo Valgrind, a instruo realizada no suportada pela aplicao, e por isso lana um sinal SIGILL que ir terminar o programa. No entanto em vez da habitual mensagem de Falha de Segmentao, obtemos Instruo Ilegal, um tipo de mensagem que costuma surgir quando ocorrem problemas de stack overflows.

Figura 5 Mensagem de Instruo Ilegal

Um outro teste foi realizado, desta vez num programa em linguagem C e tendo em vista aceder a uma funo que nunca seria executada em casos regulares. A funo main() necessita de 2 parmetros em que o segundo utilizado como argumento na chamada funo foo(). Para alm disso esta imprime os endereos das funes foo() e bar() a utilizar no teste e verifica se o nmero de argumentos da funo igual a 2. A funo foo() imprime os valores da stack antes e depois de ser chamada a funo no-segura strcpy(). A funo bar() corresponde a uma funo nunca executada que imprimiria apenas uma mensagem.

13

Figura 6 - hacking.c

Mais uma vez, foi simulado um ataque ao programa hacking.exe. O objetivo explorar o uso da funo strcpy() de maneira a corromper a stack. Numa execuo normal, aps a funo foo() ser executada seguir-se-ia a instruo de return, no entanto, em caso da stack ser corrompida, a funo a executar ser a que estiver na stack. Sabendo que o endereo da funo 004012D5 (como pode ser visto na Figura 6), apenas necessrio fornecer o input adequado de forma a colocar na stack esse endereo. Isto pode ser conseguido atravs de um script simples escrito em Perl: $arg = "ABCDEFGHIJKLMPAAAAAAAAAAAAAA"."\xD5\x12\x40"; $cmd = "./hacking ".$arg; system($cmd);

Resumidamente, o script causa overflow atravs dos caracteres ABCD e insere os caracteres pretendidos do endereo da funo bar(): 4012D5. Pode ser visto na Figura 6, a funo bar() a ser executada.

14

Figura 7 - Buffer Overflow sobre hacking.exe

15

5.2. Testes sobre Double Frees


Outro dos testes efectuados tinha como objectivo a deteco de libertaes invlidas de memria, chamadas invalid frees, que podem ocorrer quando um determinado objecto foi previamente desalocado. Para o efeito foi feito o seguinte cdigo:

Figura 8 Cdigo de teste para invalid frees

Como pode ser visto na figura, so alocados 50 bytes para o apontador c. Obviamente o programa vai entrar na poro de cdigo que est dentro da clausula if e a podemos verificar que x vai ficar a apontar para o endereo de c. Em seguida ocorre a libertao de memria por parte de c. sada da clausula if j ocorreu ento uma libertao de memria por parte de c, pelo que a segunda ser invlida, o mesmo se aplicando libertao da memria de x, que no entretanto se tornou num dangling pointer, pois apontava para um endereo cuja memria j havia sido libertada. Ao correr o programa no Valgrind podemos verificar:

16

Figura 9 Anlise do Valgrind ao teste de invalid frees

Na linha 17 ocorre a primeira libertao de memria de c. Na linha 19 onde ocorre a segunda chamada free(c) uma vez que a memria deste j havia sido libertada, o Valgrind reconhece esta chamada como sendo um invalid free, o mesmo se passado para o caso da linha 20 (free(x)).

17

6. Concluso
Como concluso, no fim deste trabalho podemos afirmar que as trs vulnerabilidades estudadas podem gerar problemas graves na execuo de um programa, a vrios nveis: acesso a informao confidencial, mau-funcionamento, crashes. ento importante ter alguns cuidados para serem evitados este tipo de vulnerabilidades que podem gerar vrios problemas. No entanto, como foi referido, os custos associados implementao de sistemas seguros so elevados e por vezes no compensam o tempo perdido, uma vez que h o risco de se estar a proteger algo que nunca vai ser atacado. Por esta razo, vimos que fundamental no incio de cada projeto ter uma noo daquilo que necessrio proteger no sistema, e de que forma que os ataques podem ser processados. Ainda assim, destacamos a existncia de alguns padres de desenvolvimento de software seguro que devem ser seguidos pelos programadores, por forma a garantirem a boa funcionalidade das aplicaes. Como ponto negativo temos a destacar o facto de o tema ser bastante complexo para permitir uma componente prtica no tempo de vida deste projecto. Pelo que foi antes abordada uma perspectiva mais terica, desenvolvendo um estudo do tema e um conjunto de testes teis.

18

Referncias
[1] Larochelle D, Evans D. Statically Detecting Likely Buffer Overflow Vulnerabilities. Science. [2] https://www.owasp.org/ [3] Periklis Akritidis, Cling: A Memory Allocator to Mitigate Dangling Pointers [4] http://www.cse.scu.edu/~tschwarz/coen152_05/Lectures/BufferOverflow.html [5] David A. Wheeler, Secure Programming for Linux and Unix HOWTO [6] Chad Dougherty, Kirk Sayre, Robert C. Seacord, David Svoboda, Kazuya Togashi, Secure Design Patterns [7] https://www.owasp.org/index.php/Secure_Coding_Principles

19

[Anexo A]

20

Manual de Boas Prticas de Programao

21

Introduo
Aquando da definio de arquitectura de um sistema, necessrio ter em conta a cobertura de riscos tanto para utilizadores tpicos como para atacantes experientes. Os arquitectos da aplicao devem lidar com vrios tipos de eventos como tentativa de decifrao brute force, injeo de cdigo e fraude. A arquitectura deve portanto fornecer controlos para proteger a confidencialidade e integridade da informao e fornecer o seu acesso quando (devidamente) pedido.

Para uma programao segura e eficaz necessrio compreender os seguintes conceitos: Requisitos Quando envolvido num projecto com mais do que uma pessoa, o programador deve ter noo exacta dos requisitos a seguir, uma vez que pode cair no erro (muitas vezes no-intencional) de adicionar requisitos no necessrios ao projecto a desenvolver. Nestas situaes em que o programador est envolvido num projecto com mais do que uma pessoa, fundamental que todas as partes compreendam os requisitos e objectivos a seguir antes de avanar para a escrita de cdigo.

Arquitectura A escolha de arquitectura apropriada para o projecto um aspecto chave. necessrio que o programador saiba o que est a construir antes de poder iniciar o projecto, uma vez que necessita de ter a noo de como criar a soluo mais indicada ao problema em questo. A investigao sobre os pontos fortes e fracos de plataformas, tecnologias e anotao dos respectivos defeitos e facilidades um passo pelo qual se deve passar antes do incio do desenvolvimento de cada projecto.

Design Mesmo depois de bem definida a arquitectura a implementar, necessrio que o programador no caia na tentao de exagerar no design da aplicao, ou seja, em no disponibilizar ao utilizador mais do que este ir necessitar. Para isto os dois princpios essenciais so manter o programa o mais simples possvel: Keep It Simple, e em esconder do utilizador toda a informao que este no necessite ver. Geralmente aqui que entram os conceitos de anlise orientada a objectos e UML.

Construo de cdigo A construo do cdigo, embora seja muitas vezes vista como o principal no desenvolvimento de um projecto, por ser a mais visvel, apenas uma pequena parte do esforo total. A melhor prtica para construo de cdigo envolve desenvolvimento dirio e consequente teste. Test-Driven-Development um standard que segue esta 22

filosofia, testar medida que se vai desenvolvendo o cdigo. Outra boa prtica, principalmente para projectos com mais do que um programador tem a ver com a qualidade dos comentrios, bem como os standards seguidos para a criao e definio de variveis, acessos a objectos, hierarquia de classes etc.

Testes A criao de testes a parte fulcral de qualquer desenvolvimento de software. necessrio que os casos de teste sejam criados enquanto a aplicao est a ser planeada e o cdigo a ser desenvolvido.

Porque programadores desenvolvem programas inseguros.


Muitas vezes o custo inerente ao desenvolvimento de software no compensa os benefcios da maior qualidade do software desenvolvido. Uma vez que as empresas nem sempre dispem de tempo suficiente para a implementao de alguns mtodos de segurana. ento necessrio avaliar a necessidade real da implementao de alguns mecanismos, tendo em conta o tipo de utilizao esperado do software, o tipo de utilizadores, etc. O tempo despendido no desenvolvimento de mecanismos com uma pequena vantagem podem levar a perdas de oportunidades das empresas para a concorrncia. A complexidade do software desenvolvido tambm um obstculo, uma vez que difcil prevenir quais as interaces possveis entre os diferentes processos, principalmente se o software estiver sujeito a futuros desenvolvimentos.

23

Tcnicas

Revises de cdigo A reviso de cdigo fonte ocorre quando algum, que no o autor original, efetua uma auditoria de cdigo. Revises de cdigo feitas pelo autor do cdigo original so geralmente insuficientes. A reviso deve ser feita por algum que esteve por fora do desenvolvimento do cdigo.

Teste ao software Testes ao software devem ser feitos de forma a garantir que o programa lida de forma eficaz com inputs inesperados. Estes testes podem envolver simples operaes de leitura de strings introduzidas pelo utilizador bem como leitura de ficheiros e combinao dos mesmos.

Reutilizao de cdigo Se o programador possuir cdigo conhecido e previamente testado, a reutilizao deste pode ser uma mais-valia, porque reduz a probabilidade de surgirem bugs no programa. No entanto, a reutilizao de cdigo nem sempre considerada uma boa prtica particularmente quando envolve lgica de negcio ou sequncia de actividades do programa. Uma vez que esse cdigo pode ter um propsito diferente daquele esperado pelo programador. Para uma programao segura, a implementao destas tcnicas deve ser combinada com alguns cuidados a ter no desenvolvimento do cdigo fonte do programa. Algumas dessas precaues so explicadas na seco seguinte

24

Cuidados a ter

1. Validao de Input
Durante a execuo de um programa alguns inputs so introduzidos, directa ou indirectamente, por utilizadores no confiveis, desta forma, um dos principais cuidados a ter para uma programao segura prende-se com a proteo ao nvel do input do programa. Esses inputs devem ser previamente filtrados, deve ser definido pelo programador o que legal, e rejeitada qualquer ocorrncia que no corresponda ao estabelecido. desaconselhvel praticar-se o inverso, identificar aquilo que ilegal e executar cdigo para rejeitar esses casos, porque h uma grande probabilidade de no serem cobertos todos os casos. Alguns cuidados a ter com validao de inputs dividem-se em algumas das situaes:

a. Limite de tamanho do input O cdigo deve estabelecer um limite para o tamanho do input a introduzir (dados muito longos podem causar instabilidade do programa). Deve ser feita a filtragem de alguns caracteres em strings.

b. Filtragem de Metacaracteres Este tipo de caracteres deve ser evitado uma vez que so caracteres que invocam uma interpretao alternativa para os restantes caracteres presentes na sequncia. A no verificao deste tipo de inputs pode levar introduo de linhas de comando que podem ter efeitos adversos na execuo de um programa.

c. Cuidados com filenames Geralmente num sistema de ficheiros a introduo de .. (parent directory) deve ser evitada, especialmente se o programa tiver a possibilidade de ser acedido por utilizadores no confiveis uma vez que estes poderiam ter acesso a documentos/directorias no permitidas O Directory Traversal Attack um ataque consequente da introduo de .. num sistema de ficheiros. Uma boa prtica neste caso, seria ento proibir qualquer alterao referente ao directrio actual, por exemplo no incluindo / na lista de caracteres aceites como input. Outra boa prtica para este tipo de situao seria a no incluso do caracter * uma vez que este permite obter todos os ficheiros de um determinado tipo presentes naquela directoria.

25

d. Verificao de caracteres limitadores de strings Em alguns programas cujos dados so separados por , ou ; ou outro qualquer caractere definido pelo programador, a ocorrncia destes num determinado input poderia causar problemas, uma vez que poderia dividir os dados de forma incorrecta.

e. Contedos de ficheiros Se um programa segue determinadas instrues/direces de um determinado ficheiro, ento no dever confiar em ficheiros que no tenham acesso restrito para utilizadores confiveis. Ou seja, isto significa que um utilizador no confivel no dever poder alterar esse ficheiro, nem a sua directoria.

2. Evitar buffer overflows


Uma primeira medida para evitar buffer overflows implica a utilizao frequente de funes como gets(), strcpy(), strcat(), *sprintf(), *scanf(%s) em que o limite de caracteres introduzido no verificado. Uma boa abordagem para isso envolve a utilizao de chamadas a funes da biblioteca standard de C que por si s j so uma proteco contra este problema como por exemplo a utilizao de strncpy(3) e strncat(3). Se esperada a reutilizao de um mesmo buffer vrias vezes, a utilizao das funes acima referidas uma boa soluo uma vez que exigem que lhes seja passado o nmero de caracteres a copiar. A funo strncpy() no possui caractere de terminao de string se a string original possui, no mnimo, o mesmo tamanho do buffer de destino, por isso, conveniente que o programador defina esse ltimo caractere na string de destino depois de utilizar strncpy(). Ainda assim necessrio efectuar a verificao de caracteres a copiar uma vez que este nmero poder ser maior do que o tamanho do buffer de destino. Apesar disto, este tipo de funes pode ter uma performance inferior quando comparadas com outras funes semelhantes que podem ser vistas como possveis alvos de buffer overflow, por isso convm verificar a necessidade de usar este tipo de funes, uma vez que em alguns casos pode no ser essencial este tipo de proteo. Outra funo que pode ser utilizada sprintf(), apesar de necessitar de algumas precaues. O controlo desta funo pode ter vrios especificadores de converses (por exemplo %s ou %i), e o controlo destes especificadores pode ter valores opcionais com o tamanho e preciso dos respectivos dados. Ora, estes controlos implicam diferentes condies, o comprimento do campo, apenas define o tamanho mnimo e desta forma intil como preveno para buffer 26

overflow. (exemplo %10s, string com tamanho mnimo de 10 caracteres). Por sua vez a preciso estabelece um limite mximo da string em questo, e pode portanto ser utilizada como combate a este problema. (exemplo %.10s). No que toca a preciso este tipo de controlos s funciona quando estamos a lidar com strings. O seu significado diferente para outro tipo de dados. Se o controlo for definido com %.*s, poder ser usado o valor mximo do tamanho da string. Uma desvantagem da utilizao de spritnf() que, no caso de o formato dos dados ser complexo, necessrio verificar que existe espao suficiente em memria para guardar a maior combinao possvel de dados, o que por vezes poder ser complicado uma vez que a preciso s controla um dos parmetros. Se tal no acontecer pode ser originado um buffer overflow.

Arrays estticos vs arrays dinmicos Existem duas formas de guardar informao em arrays: de forma esttica, em que o buffer alocado para o tamanho mais longo, e mantem essa forma; e de forma dinmica: em que o seu tamanho vai sendo dinamicamente alterado conforme a necessidade. Como vamos verificar, ambas as abordagens tm algumas desvantagens. Em arrays estticos, supondo que o que se pretende guardar tem, normalmente, um comprimento elevado, guardar tal informao num array esttico pode levar a que a parte final da string a guardar fique cortada o que poder obviamente ter efeitos indesejveis para o programa. (exemplo: no caso de ser guardado um caminho de um determinado ficheiro, guardando um caminho invlido, leva inacessibilidade do ficheiro. Para este tipo de abordagens prefervel a utilizao de arrays dinmicos, uma vez que a informao pode ser guardada com tamanho arbitrrio. A contrapartida desta abordagem que com arrays dinmicos a alocao de memria mais ineficiente, o que pode levar a que memria que seja necessria para o processamento de determinados dados esteja a ser utilizada noutro ponto do programa, para alm de haver a possibilidade de o programa ficar sem memria disponvel apesar de tal ser pouco aceitvel nos dias que correm. Outra alternativa possvel a utilizao de strlcat e strlcpy. Estas funes permitem cpia e concatenao seguindo uma abordagem esttica, mas menos sujeita a erros. Ambas as funes recebem como parmetro o tamanho do buffer de destino (e no o mximo de caracteres a copiar/concatenar) garantindo assim que o destino preenchido com o caractere de terminao.

27

28

Princpios de desenho

1. Principio do menor privilgio Cada utilizador deve utilizar o sistema usando o mnimo de privilgios possvel. Este principio limita os danos no caso de um acidente, erro ou ataque. Reduz tambm o nmero de potenciais interaces entre programas com alto nvel de privilgios o que impede que uso incorrecto desses privilgios seja pouco provvel de acontecer. Na execuo de um programa, somente a parte do cdigo que necessite de ser executada com determinados privilgios que deve ter acesso a eles. Exemplo: Se num servidor middleware necessitar de acesso a uma rede ou a uma tabela de determinada base de dados, a nico permisso que lhe dever ser concedida somente aquela de que necessita. Em nenhuma situao devem ser concedidos privilgios de administrao.

Vulnerabilidades a combater: Falha de libertao de privilgios A no libertao de privilgios na altura devida no considerada uma vulnerabilidade propriamente dita, no entanto, pode aumentar o perigo de outras vulnerabilidades, uma vez que o atacante dispe de maiores privilgios para explorar o sistema e consequentemente explorar outras possveis vulnerabilidades. Se possvel, devem ser limitadas as permisses de acesso a pequenas pores de cdigo em que estas sejam estritamente necessrias.

2. Design aberto A forma como feita a proteo do sistema no deve ser feita com base em esconder a informao do atacante, isto , esconder os detalhes do sistema de segurana, para que o atacante com base no conhecimento do sistema, saiba como agir. O mecanismo deve ser pblico. Os utilizadores devem estar convencidos de que o sistema que esto a utilizar adequado, e torna mais fcil para os utilizadores a sua avaliao.

29

3. Separao de privilgios O acesso a objectos deve depender de mais do que uma condio, assim, desbloquear um sistema de proteco (adquirindo um determinado de tipo de privilgio) no ir garantir directamente o acesso a um determinado objecto. 4. Mnimo de mecanismos comuns

Deve ser minimizado o uso de mecanismos/objectos comuns uma vez que estes podem ser vistos como potenciais canais de fluxo de informao e de interaces indeterminadas. 5. Princpio da aceitabilidade psicolgica A interface deve ser fcil de utilizar de maneira a que os utilizadores possam facilmente utilizar os mecanismos de proteco facilmente. Erros sero reduzidos se o mecanismo de segurana for intuitivo para o utilizador e para a sua ideia de proteco.

6. Desconfiana de outras entidades Muitas organizaes utilizam processos de parceiros, que muitas vezes seguem princpios e polticas de segurana bastante diferentes. No comum que um utilizador (empresa neste caso) tenha influncia ou consiga controlar alguma entidade externa. Desta forma a confiana em sistemas de segurana externos no aconselhada uma vez que os mesmos podem no estar garantidos para casos diferentes. Por exemplo, um programa confivel pode fornecer dados para um Banco, esses dados podem ser cdigos de segurana e respectiva identificao. No entanto, estes mesmos dados devem ser verificados para garantir que existem nmeros de identificao mal atribudos e que correspondem ao esperado.

30

Вам также может понравиться