atps-desenvolvimento de software seguro

107
1 UNIDADE DE ENSINO VALPARAÍSO DE GOIÁS TECNOLOGIA EM ANÁLISE E DESENVOLVIMENTO DE SISTEMAS DISCIPLINA: DESENVOLVIMENTO DE SOFTWARE SEGURO PROFESSOR Me. EDINEI GONÇALVES LEMES VALPARAÍSO DE GOIÁS / GO 2015

Upload: juvenal-f-batista

Post on 08-Nov-2015

81 views

Category:

Documents


44 download

DESCRIPTION

atps desenvolvimento software

TRANSCRIPT

  • 1

    UNIDADE DE ENSINO VALPARASO DE GOIS

    TECNOLOGIA EM ANLISE E DESENVOLVIMENTO DE SISTEMAS

    DISCIPLINA: DESENVOLVIMENTO DE SOFTWARE SEGURO

    PROFESSOR Me. EDINEI GONALVES LEMES

    VALPARASO DE GOIS / GO

    2015

  • 2

    Universidade Anhanguera UNIDERP Centro de Educao a Distncia

    Tecnologia em Anlise e Desenvolvimento de Sistemas

    Disciplina: Desenvolvimento de Software Seguro

    Prof. EaD: Me. EDINEI GONALVES LEMES

    GRUPO 5

    REGINALDO FERREIRA DE SOUSA RA: 6787372072

    CARLOS CSAR CUNHA DE OLIVEIRA- RA: 7365462891

    DJONNE DE SOUZA DOS SANTOS- RA: 7372573704

    FERNANDA FERNANDES SILVA - RA: 7930683375

    IGOR OLIVEIRA NAVA RA: 6947470168

    JUVENAL F. BATISTA-RA: 7707625583

    Atividade Pratica Supervisionada

    Aplicado aos Cursos Superiores de Tecnologia I

    ATPS

    Valparaso / GO

    2015

  • 3

    Universidade Anhanguera UNIDERP

    Centro de Educao a Distncia

    ATIVIDADE PRTICA SUPERVISIONADA

    Atividade Avaliativa: Desafio de Aprendizagem

    apresentado ao Curso Superior de Tecnologia em

    Anlise e Desenvolvimento de Sistemas da

    Universidade Anhanguera UNIDERP, como

    requisito para a avaliao da Disciplina

    Desenvolvimento de Software Seguro, para a

    obteno e atribuio de nota da Atividade

    Avaliativa.

    Prof. Me. Edinei Gonalves Lemes

    Tutor Presencial: Paulo Dutra

    VALPARASO DE GOIS / GO

    2015

  • 4

    SUMRIO

    Relatrio 1 - Desenvolvendo Softwares Seguros............................................................5

    Relatrio 2 - Evitando Estouro de Buffer........................................................................14

    Relatrio 3 - Utilizando Criptografia.............................................................................43

    Relatrio 4 - Evitando Ataques SQL INJECTION........................................................55

    Relatrio 5 - Evitando ataques RPC E DDOS...............................................................63

    Relatrio 6 - Testes de Segurana e Instalao de Softwares Seguros...................... .95

  • 5

    Relatrio 1 Desenvolvendo Softwares Seguros

    1. Requisitos de Segurana de Software e sua importncia

    Os requisitos de segurana de software so o conjunto de necessidades de segurana que o

    software deve atender, sendo tais necessidades influenciadas fortemente pela poltica de

    segurana da organizao, e compreendendo aspectos funcionais e no funcionais. Os aspectos

    funcionais descrevem comportamentos que viabilizam a criao ou a manuteno da segurana

    e, geralmente, podem ser testados diretamente. Na maioria dos casos, remetem a mecanismos

    de segurana como, por exemplo, controle de acesso baseado em papis de usurios

    (administradores, usurios comuns, entre outros.), autenticao com o uso de credenciais

    (usurio e senha, certificados digitais, entre outros.), dentre outros.

    Os aspectos no funcionais descrevem procedimentos necessrios para que o software

    permanea executando suas funes adequadamente mesmo sob uso indevido. So exemplos

    de requisitos no funcionais: validao de dados de entrada e o registro de eventos em log de

    auditoria com informaes suficientes para anlise forense. A elicitao de requisitos de

    segurana de software consiste na definio das necessidades de proteo exigidas pelo

    software. Tal atividade exige uma colaborao intensa entre os interessados no software,

    especialmente daqueles com viso negocial, que podem ter conscincia das consequncias no

    negcio decorrentes de incidentes de segurana, cujo vetor de ataque se localize no software.

    Algumas das tcnicas mais usadas no levantamento de requisitos de segurana incluem:

    Brainstorming.

    Pesquisas de opinio (questionrios e entrevistas).

    Decomposio da poltica.

    Classificao de dados.

    Matriz de objeto-sujeito.

    Modelagem de caso de uso e abuso.

    Independente da tcnica a ser usada, a elicitao de requisitos exige que pelo menos um dos

    participantes na atividade tenha densidade em segurana de software, para que os fluxos

    regulares que o software prover ou j provm sejam criticados, evidenciando maneiras de

    subvert-los. A definio dos cenrios negativos, cuja realizao indesejada, resultar no

  • 6

    requisito de segurana. Segue, a ttulo de ilustrao, alguns exemplos de requisitos de

    segurana, retirados do livro Official (ISC)2 guide to the CSSLP by Mano Paul.

    1.1 Confidencialidade

    Senha e outros campos de entrada de dados sensveis necessitam ser mascarados.

    Senhas no devem ser armazenadas as claras nos sistemas backend, e quando

    armazenadas devem passar por processo de hash com uma funo pelo menos

    equivalente a SHA-256.

    Transport Layer Security (TLS) como Secure Socket Layer (SSL) deve ser colocado em

    prtica para proteger contra ameaas internas de Man in the Middle (MITM) para todas

    as informaes de carto de crdito que seja transmitida.

    O uso de protocolos reconhecidamente inseguros como, por exemplo, File Transfer

    Protocol (FTP) para transmitir credenciais de contas em texto claro a terceiros fora de

    sua organizao deve ser proibido.

    Arquivos de log no devem armazenar qualquer informao sensvel como definido

    pelo negcio, de modo que seja compreensvel por seres humanos.

    1.2 Integridade

    Todos os formulrios de entrada e query strings necessitam ser validadas frente a um

    conjunto de entradas aceitveis, antes do software aceita-los para processamento.

    O software a ser publicado deve ser disponibilizado juntamente com o checksum e a

    funo hash usada para computar o checksum, de modo que o interessado possa validar

    sua preciso e completude.

    Todos os personagens no humanos como um sistema ou processos batch devem ser

    identificados, monitorados e impedidos de alterao de dados, a medida que ele passa

    no sistema que eles rodam, a no ser que explicitamente autorizado para tal.

    1.3 Disponibilidade

    O software deve oferecer alta disponibilidade de oito (8) noves (9), como definido pelo

    SLA.

    O software deve estar preparado para atender capacidade mxima de 300 usurios

    simultneos.

  • 7

    O software e seus dados devem ser replicados por todos os centros de dados para prover

    balanceamento de carga e redundncia.

    A funcionalidade de misso crtica no software deve ser restaurada a operao normal

    no prazo de 1 hora de descontinuidade; funcionalidade de misso essencial no software

    deve ser restaurada a operao normal no prazo de 4 horas da interrupo, e

    funcionalidade de misso suporte no software deve ser restaurada a operao normal no

    prazo de 24 horas.

    1.4 Autenticao

    O software ser implantado somente na Intranet e o usurio autenticado deve fornecer

    novamente suas credenciais para acessar a aplicao, uma vez que esteja autenticado na

    rede.

    O software dever suportar single sign on a terceiros e fornecedores que esto definidos

    na lista de interessados.

    A poltica de autenticao garante a necessidade para dois ou autenticao com

    mltiplos fatores para todos os softwares de processamento financeiro.

    1.5 Autorizao

    O acesso a arquivos secretos de alta sensibilidade deve ser restrito somente a usurios

    com nveis de permisso secreto e supersecreto.

    Os usurios no devem ser demandados a enviar suas credenciais sempre, uma vez que

    ele tenha se autenticado com sucesso.

    Todos os usurios autenticados herdaro a permisso de leitura somente que so parte

    do papel do usurio convidado enquanto os usurios autenticados por padro tero

    permisso de leitura e escrita como parte do papel de usurio regular. Somente os

    usurios com acesso administrativo, tero todos os direitos dos usurios regulares,

    adicionalmente a execuo de operaes.

    1.6 Auditing and Logging

    Todas as tentativas de logon devem ser registradas juntamente com o timestamp e o

    endereo de IP de origem da requisio.

  • 8

    Os valores anterior e posterior a uma mudana de preo modificado por um usurio,

    quando da atualizao de um preo por um usurio, devem ser monitorados com os

    seguintes campos auditados: identidade, ao, objeto e timestamp.

    Os logs de auditoria devem sempre ser adicionados de novos registros e nunca

    sobrescritos.

    Os logs de auditoria devem ser mantidos de forma segura por um perodo de 3 anos.

    Gerenciamento de Sesso

    Cada atividade do usurio dever ser rastreada de modo nico.

    O software no deve solicitar as credenciais de acesso do usurio, uma vez que ele esteja

    autenticado no Internet Banking.

    As sesses devem ser explicitamente suspensas quando o usurio solicita o log off ou

    fecha a janela do browser.

    Identificadores de sesso usados para identificar a sesso de usurios devem no ser

    passados em claro ou ser facilmente adivinhado.

    1.7 Logging de Aplicao

    O logging uma dimenso muito importante de uma aplicao, mas que amplamente

    negligenciada durante o seu processo de design, assim como a segurana de software. No a

    toa que uma das prticas iniciais recomendadas pelo BSIMMv2 (AA1.1) d enfoque aos

    mecanismos de segurana, contedo no qual o logging se enquadra.

    Talvez seja o fato dos principais interessados: auditor, desenvolvedor e administrador

    do sistema, no estarem to interessados assim, desde o princpio (abordagem build security

    outside in). O administrador do sistema normalmente no estimulado a pensar nos sinais que

    a aplicao deva lhe fornecer para atuar diante de questes de produo. O auditor s chega em

    cena, depois que o circo comea a pegar fogo, ou por imposio regulatria. J o desenvolvedor,

    se vale das ferramentas de debug para resolver os problemas de cdigo, desdenhando do log.

    Mas considere que voc esteja numa situao privilegiada, na qual pode pensar em logging

    antes que necessite de fato do log. Que caminho seguir? De forma bem objetiva e resumida

    recomendaria as seguintes etapas para o sucesso da sua iniciativa de logging.

  • 9

    1.8 Reconhea a aplicabilidade do log.

    Para reconhecer a aplicabilidade fundamental levantar que cenrios sero tratados pela

    sua organizao. Isso pode partir das atividades comuns dos papis citados anteriormente. Por

    exemplo, o auditor precisar atuar diante de cenrios que envolvam ataques, uso inadequado e

    falhas. J o desenvolvedor e o administrador se interessariam mais por cenrios de falhas, erros

    e desempenho. Inclua as seguintes questes durante a sua anlise: A que servir o log? Essa

    questo lhe ajudar a se afastar da tecnologia e perceber que o log possui um objetivo e que

    este deve ser o foco. Temos alguns exemplos: Garantir no repdio de aes executadas por

    usurios autnticos; reconhecer fluxos de execuo ou entradas para a aplicao

    reconhecidamente suspeitas; Identificar a linha do cdigo fonte que comprometeu a execuo

    da aplicao; mostrar a pilha de execuo relacionada a determinado falha da aplicao;

    recuperar os dados que eram processados no momento de alguma falha; reconhecer quando

    determinados eventos so iniciados e concludos. Reconhecer o tempo de processamento de

    determinadas aes da aplicao; reconhecer o estado de recursos, como espao disponvel em

    disco.

    1.9 Como o log ser consumido?

    Essa questo vai influenciar diretamente no contedo do log, que dever ser elaborado

    para que as diferentes formas de consumo sejam possveis. Manualmente com/sem apoio de

    ferramentas automatizadas ou automaticamente.

  • 10

    Qual a origem dos registros do log? Definio que lhe orientar quanto a dinmica

    para consolidar os registros, alm de dar um tratamento homogneo independente da

    origem.

    o Aplicao, WAF, servidor de aplicao, etc.

    Como o log ser armazenado? Sua infraestrutura ter que estar preparada para receber

    os registros, garantir a sua segurana, oferecer acesso concorrente, etc.

    o Arquivo, banco de dados e/ou console.

    o Dimenso mxima da base.

    o Segmentao do arquivo.

    2.0 Defina o contedo do log

    Uma vez que se tem a noo do que se espera do log e do ambiente em que ele estar

    inserido, chega o momento da definio do seu contedo. Uma abordagem bastante interessante

    o reconhecimento dos eventos que devem ser encontrados no log. Como nosso interesse est

    muito voltado para segurana, nada mais natural que tratar de tais eventos. Anton Chuvakin e

    Gunnar Peterson sugerem os seguintes eventos:

    Autenticao, autorizao e acesso:

    o Decises com falha ou sucesso relacionadas a autorizao e autenticao.

    o Acesso a sistema, a dados e componentes; e

    o Acesso remoto, incluindo aqueles entre componentes de uma mesma aplicao

    em ambientes distribudos.

    Mudanas:

    o Mudanas em sistema ou aplicao (especialmente quando envolva alterao de

    privilgios).

    o Mudanas de dados (incluindo a criao e destruio), e

    o Instalao e mudanas em componentes e aplicaes.

    Problemas de disponibilidade:

    o Incio e encerramento de sistemas, aplicaes e mdulos ou componentes de

    aplicaes.

    o Sucesso e falhas de backup que afete disponibilidade.

    Problemas com recursos:

    o Recursos excedendo suas capacidades.

  • 11

    o Problemas com conectividade.

    o Limites estourados.

    Indicao de ameaas:

    o Entradas invlidas ou outros abusos da aplicao.

    o Outros problemas com a aplicao que comprometa a sua operao.

    praticamente impossvel levantar todos os eventos de uma aplicao, mas quanto mais

    ampla for a lista, mais condies se tem de conduzir a forma de elaborao do registro.

    Definidos os eventos, voc pode estabelecer uma conveno de dados do registro relacionado

    a cada evento. Essa uma forma de reduzir o poder discricionrio do desenvolvedor em definir

    o contedo do log, fonte patente de problemas. Definidos os eventos, recomendvel usar uma

    forma de categorizao dos registros do log. Tal categorizao lhe permite priorizar sua ateno

    diante dos eventos produzidos pela aplicao. A maneira amplamente difundida pela sua

    prioridade ou criticidade, que na maioria dos casos varia de trace, nvel menos crtico, at fatal,

    nvel mais crtico. A justificativa para cada categoria segue abaixo:

    FATAL apropriado para eventos que indiquem uma falha crtica de servio. Se um

    servio emitir um erro FATAL, ele est completamente incapaz de responder. Ex.

    Indisponibilidade total de um dos componentes-chave da aplicao.

    ERRO apropriado para eventos que indiquem uma descontinuidade em uma

    requisio ou habilidade do servio em responder. Um servio deve ter alguma

    capacidade de continuar a responder a requisies mesmo na presena de ERROs. Os

    ERROs no podem ser tolerados pela aplicao e devem ser investigados

    imediatamente.

    AVISO apropriado para eventos que indiquem um erro no crtico em determinado servio.

    Erros resumidos ou brechas menores em requisies recaem sobre essa categoria. A distino

    entre AVISO e ERRO muito tnue. Um critrio simples se a falha resulta em chamada de

    suporte pelo usurio. Caso a resposta seja positiva, escolha ERRO, caso contrrio use AVISO.

    Os AVISOs podem ser tolerados pela aplicao, mas devem sempre ser justificados e

    examinados. Ex. Aplicao operando em modo debug. O console da aplicao no impe

    controle de acesso.

  • 12

    INFO apropriado para eventos do ciclo de vida de servios e outras informaes

    cruciais relacionadas. Mensagens INFO para uma determinada categoria de servio

    devem revelar qual o estado corrente do servio. Outra definio de mensagens INFO,

    registram aes que alteram significativamente o estado da aplicao. Ex. Atualizao

    do banco de dados, requisio.

    DEBUG apropriado para mensagens que incorporam informaes extras aos eventos

    de ciclo de vida. Informao de desenvolvimento ou mais aprofundada necessria para

    o suporte a base para esta prioridade. Pode-se considerar a pilha de execuo e

    mensagens trocadas com sistemas externos a aplicao.

    TRACE informao muito detalhada de interesse de desenvolvedores. Tais

    mensagens so mantidas por um perodo de tempo muito pequeno quando a aplicao

    entra em produo e devem ser consideradas temporrias. A dificuldade em se distinguir

    mensagens DEBUG e TRACE a mais elevada. Uma vez que se considere um bloco

    de instrues de logging desprezvel aps o desenvolvimento e teste da aplicao,

    provavelmente ele deve ser classificado como TRACE. Estas mensagens podem conter,

    por exemplo, alm dos mtodos de classes no fluxo de execuo, os argumentos que

    cada mtodo recebe e devolve.

    As categorias citadas anteriormente servem apenas como um exemplo a ser considerado

    para definir as categorias que fizerem sentido para os objetivos do logging. Outra dimenso

    recomendada para categorizar os registros a segurana. Todos os eventos considerados por

    Anton Chuvakin e Gunnar Peterson recaem sobre essa categoria.

    2.1 Disponibilize o mecanismo de logging

    A maneira mais recomendada para conceber um mecanismo de logging adaptar uma das

    diversas bibliotecas disponveis de acordo com suas necessidades. Dentre as funcionalidades

    oferecidas por uma biblioteca de logging, as seguintes se destacam:

    Administrao da sada (dimenso, backup, diviso, gravao, etc.)

    Classificao dos registros (criticidade/prioridade/segurana).

    Gerenciamento de concorrncia.

    Tais funcionalidades esto presentes em vrias bibliotecas como, por exemplo:

    Enterprise Library, SLF4J e ESAPI. A ESAPI merece um destaque especial por este post,

  • 13

    pois foi concebida com pretenses muito ousadas no que se refere a segurana. Decorre da

    a possibilidade de instrumentar de forma bastante simples a aplicao, para que ela se adapte

    automaticamente diante de cenrios de ataque, a partir do uso do AppSensor. Uma vez que

    se defina o que e como logar, para que se obtenha sucesso nessa iniciativa, o desenvolvedor

    deve ser bombardeado de treinamento, orientao e acompanhamento para garantir o uso

    adequado do mecanismo e, principalmente, que o contedo dos registros seja completo e

    compreensvel para o fim a que ele se destina.

    Apresentamos algumas etapas fundamentais no processo de estruturao do logging de

    aplicaes. Cada fase mereceria diversos posts para contemplar assuntos to extensos, mas

    por limitaes de tempo tivemos que nos limitar a elas.

    So ainda questes interessantes a serem discutidas:

    Como ajustar o logging de uma aplicao que usa um WAF?

    Como garantir que o contedo do log no seja subvertido pelo desenvolvedor?

    Como orquestrar o mecanismo de validao de entrada e sada e o mecanismo

    de logging para que a aplicao trabalhe segundo uma abordagem de segurana

    positiva?

    2.2 Erros e Gerenciamento de Exceo

    Todos os erros e excees devem ser explicitamente manipulados a partir de blocos try,

    catch e finally.

    Mensagens de erro que so mostradas ao usurio revelaro somente a informao

    necessria, sem vazamento de detalhes internos do sistema na mensagem de erro.

    Detalhes de excees de segurana devem ser auditados e monitorados periodicamente.

    Parmetros de Configurao

    Os dados sensveis do arquivo de configurao da aplicao web como strings de

    conexo, devem ser encriptados.

    Senhas e chaves de criptografia no devem ser registradas no cdigo fonte do software.

    A inicializao e a liberao de variveis globais necessitam ser monitoradas com muito

    cuidado.

    Eventos de inicializao e interrupo de sesso devem incluir protees na informao

    de configurao como uma salvaguarda contra ameaas de vazamento.

  • 14

    Relatrio 2 Evitando estouro de Buffer

    2.3 O que Buffer?

    Um buffer uma pequena rea de memria ultrarrpida usada para melhorar a

    velocidade de acesso a um determinado dispositivo. encontrado em HDs, gravadores de CD,

    modems, e em muitos outros dispositivos. Apesar de serem sinnimos, o termo "buffer" mais

    usado em relao aos dispositivos anteriormente citados enquanto o termo "cache" mais usado

    com relao aos processadores e memria RAM.

    Embora no seja to importante para o desempenho quanto geralmente se pensa, o buffer

    permite controladora do HD executar um conjunto de operaes teis para melhorar o

    desempenho.

    Geralmente ao ler um arquivo, sero lidos vrios setores sequenciais. A forma mais

    rpida de fazer isso , naturalmente, fazer com que a cabea de leitura leia de uma vez todos os

    setores da trilha, passe para a trilha seguinte, passe para a terceira e assim por diante. Isso

    permite obter o melhor desempenho possvel.

    O problema que na prtica no assim que funciona. O sistema pede o primeiro setor

    do arquivo e s solicita o prximo depois de receb-lo e certificar-se de que no existem erros.

    Se no houvesse nenhum tipo de buffer, a cabea de leitura do HD acabaria tendo que passar

    vrias vezes sobre a mesma trilha, lendo um setor a cada passagem, j que no daria tempo de

    ler os setores sequencialmente depois de todo tempo perdido antes de cada novo pedido.

    Graas ao buffer, este problema resolvido, pois a cada passagem a cabea de leitura l

    todos os setores prximos, independentemente de terem sido solicitados ou no. Aps fazer sua

    verificao de rotina, o sistema solicitar o prximo setor, que por j estar carregado no buffer

    ser fornecido em tempo recorde.

    Nos HDs atuais, o buffer pode ser usado tambm nas operaes de escrita. Imagine, por

    exemplo, que a controladora est ocupada lendo um arquivo longo e o sistema solicita que ela

    atualize um pequeno arquivo de log. Em vez de precisar parar o que est fazendo, a controladora

    pode armazenar a operao no buffer e execut-la mais adiante, em um momento de ociosidade.

    Nos HDs SATA com NCQ, a controladora possui liberdade para reorganizar as

    operaes, realizando-as de forma que sejam concludas mais rpido. A controladora passa

    ento a armazenar os dados no buffer, de forma que, depois de concludas as operaes, possa

    organizar os dados e entreg-los na ordem correta para o sistema.

    O espao excedente usado para armazenar os ltimos arquivos acessados, de forma

    que eles possam ser fornecidos rapidamente caso sejam requisitados novamente. A principal

  • 15

    vantagem de usar um buffer maior seria justamente ter mais espao para arquivos. A questo

    que o sistema operacional tambm mantm um cache de leitura e gravao utilizando a memria

    RAM que, por ser maior que o buffer do HD, acaba sendo mais eficiente e tambm mais rpido,

    j que o buffer do HD tem sua velocidade de transferncia limitada velocidade da interface

    IDE ou SATA, enquanto o cache feito pelo sistema operacional est limitado apenas

    velocidade de acesso da prpria memria RAM.

    2.4 Breve relato histrico

    No fim dos anos 80, especificamente em 1988, o mundo tecnolgico conheceu um dos

    malwares de maior influncia, impacto e explorao da histria, o Morris Worm. Este vrus se

    espalhou de maneira grandiosa, causando danos financeiros enormes, infectando e deixando

    inutilizada uma parcela enorme dos computadores conectados rede mundial de computadores

    da poca. Esse vrus explorava diversas vulnerabilidades at ento desconhecidas, e uma dessas

    vulnerabilidades exploradas, era exatamente um estouro de buffer no servio finger, que era o

    protocolo usado para fazer a troca de informaes de usurios na rede.

    Na maioria das vezes, o ataque consiste em descobrir algum parmetro de entrada

    vulnervel de um sistema que possa ser manipulado de maneira que permita a entrada de

    comandos de mquina maliciosos. Estes comandos se forem bem formulados, podem ser usados

    para comprometer a mquina hospedeira de maneira que o atacante receba privilgios que antes

    no possua. Estas vulnerabilidades podem ser evitadas utilizando as boas prticas de

    programao. O uso errado de funes que operam com arrays a principal causa de brechas

    na segurana de um sistema. Funes que permitem a escrita de um dado em memria alm dos

    limites estabelecidos pelo compilador e devem ser usadas com um cuidado especial, pois podem

    estar colocando vulnerabilidades passiveis de explorao. Hoje quase 30 anos aps o

    lanamento do verme, o estouro do buffer ainda o tipo de vulnerabilidade mais explorado do

    mundo, estando a frente de ataques que so conhecidos como os ataques de negao de servios

    ou Denial of Service, ou ainda DoS.

    2.5 Organizao de Processos em Memria

    Para se entender melhor o que so e como ocorrem os estouros de buffer, precisamos

    entender alguns conceitos que so essenciais e esto relacionados a sistemas operacionais;

    precisaremos compreender o conceito de organizao de um processo em memria, e como se

  • 16

    realiza as chamadas de funes, registradores e dentre outras coisas. Ser utilizado um sistema

    operacional software livre Ubuntu. Entretanto, todos os conceitos aqui tratados so similares

    maioria dos sistemas operacionais existentes.

    2.5.1 Processos

    Um processo um programa em execuo, isto significa que o sistema operacional

    carregou o executvel do programa em memria, providenciou para que ele tivesse acesso aos

    argumentos por linha de comando, e o iniciou. Um processo dividido em memria em cinco

    reas distintas (ROBINS, 2004). So elas:

    1. Cdigo (text): essa a rea onde as instrues executveis residem. Essa rea

    organizada de tal maneira que diversos processos do mesmo programa podem dividir a

    mesma rea de cdigo, apenas uma cpia ficar na memria. Ela tipicamente marcada

    como apenas para leitura, e qualquer tentativa de escrever sobre ela gera um erro de

    segmentao;

    2. Dados inicializados (Data): Variveis globais e estticas inicializadas com valores

    diferentes de zero situam-se no segmento de dados, que uma rea nica para cada

    processo em execuo.

    3. Dados inicializados com zeros (BSS): Variveis globais e estticas inicializadas com

    zero por padro so alocadas na rea conhecido por BSS, que tambm nico para cada

    instancia de um programa em execuo. BSS, que tambm nico para cada instancia

    de um programa em execuo. BSS mantido no segmento de dados quando um

    programa inicia sua execuo. Linux/Unix organizado de tal maneira que apenas as

    variveis que so inicializadas para valores diferentes de zero ocupem espao em

    memria. Por exemplo, um array declarado static char buff [1024], que

    automaticamente inicializado com zeros, no ocupam necessariamente 1K de memria;

    4. Heap: a rea usada para alocao dinmica de memria (atravs do uso de funes

    como malloc() e similares). O espao de endereamento reservada para o processo

    cresce na medida em que mais memria alocada no Heap. dito que a memria

    alocada nessa rea cresce para cima, pois cada item adicionado no Heap ser acrescido

    em um endereo de memria superior aos que foram adicionados anteriormente.

    5. Pilha (Stack): a rea onde se encontram as variveis locais do programa (aquelas

    definidas dentro do escopo de uma funo). Aqui tambm se encontram parmetros de

  • 17

    funo e o seu endereo de retorno para quem a chamou. Essa memria

    automaticamente liberada no trmino da funo. Na maioria das arquiteturas, a pilha

    cresce para baixo, pois, cada item adicionado ser acrescido em endereos de memria

    inferiores aos que foram adicionados anteriormente;

    A figura abaixo ilustra a organizao em memria de um processo:

    Figura 2.5.1: Organizao de um processo de memria.

    Figura 2.5.1.1: Organizao de um processo de memria.

    Stack

    Heap

    BSS

    Data

    Text

  • 18

    Analisando a primeira imagem pode-se perceber que a pilha e o heap crescem um na

    direo oposta do outro. Teoricamente seria possvel que estas duas reas de memria se

    sobrescrevessem, porm, o sistema operacional impede que tal fato ocorra. As diferentes reas

    da memria podem ter diferentes permisses de acesso configuradas para elas. Por exemplo,

    tpico marcar a rea de cdigo com uma permisso de somente execuo e desmarcar tal

    permisso nas reas de pilha e dados. Essa pratica pode at mesmo prevenir alguns tipos de

    ataques de segurana (ROBBINS, 2004).

    O comando Linux size nos permite verificar o tamanho das reas de cdigo, de dados, e

    BSS do processo. O programa a seguir foi criado para demonstrar o uso desse comando.

    Executando o comando size temos:

    #include

    #include

    #include

    Int main(){

    Int a=10;

    Char b[100];

    Strncpy(b, Esse um programa para testar os tamanhos das reas de memria de um

    processo, 99);

    b[99] = \0;

    Printf (%s\n, b);

    Return 0;

    [carlos@carlos-desktop:]~$ size memsize

    Text data bss dec hex filename

    1188 272 8 1468 5bc memsize

  • 19

    2.5.2 Pilha

    A pilha um bloco contguo de memria cujo tamanho dinamicamente ajustado pelo

    kernel em tempo de execuo de um processo. Possui um endereo base fixo e topo varivel.

    O CPU implementa instrues PUSH e POP para adicionar e retirar dados da pilha,

    respectivamente (ALEPHONE, 1996).

    Para controlar as operaes de insero e remoo da pilha, usado o registrador Stack

    pointer (ESP, ou Extended Stack Pointer), que aponta para o seu topo. Ao executar o comando

    PUSH, um valor inserido na pilha e o registrador decrementado. Na chamada do comando

    POP, o valor o qual o Stack pointer aponta retirado da pilha, e seu valor incrementado

    (ALEPHONE, 1996), a seguir, dois exemplos de instrues tpicas para controle de tamanho

    da pilha:

    Para acessar as variveis locais e parmetros da funo, usado um segundo registrador

    chamado de frame pointer (ABP, ou Extend Base Pointer), que aponta para um endereo fixo

    dentro de um frame. Atravs do deslocamento relativo ao frame pointer, possvel calcular o

    endereo dos parmetros e variveis locais. Tal endereamento poderia ser realizado usando-se

    como base o ESP, porm suas mudanas de valor obrigariam que houvesse constantes

    atualizaes dos deslocamentos. Em alguns casos, o compilador possui capacidade para corrigir

    esses valores, em outros no, e em todos os casos necessrio um gerenciamento considervel

    e possivelmente custoso em termos de processamento (ALEPHONE, 1996).

    A pilha organizada em blocos lgicos chamados de frames. Cada frame da pilha possui

    dados como variveis locais e parmetros da funo, endereo de retorno para o frame anterior

    e o valor do ponteiro de instruo (EIP, ou Extended Instruction Pointer) no momento da

    chamada da funo. Um frame colocado na pilha na chamada de uma funo, e retirado no

    seu retorno (ALEPHONE, 1996). A figura abaixo demonstra os elementos presentes em um

    frame:

    add esp, 0xA //diminui o tamanho da pilha em 10 bytes

    sub esp, 0xA //aumenta o tamanho da pilha em 10 bytes

    push ebp // Salva EBP, o colocando na pilha

    pop ebp //Busca EBP, removendo-o da pilha

  • 20

    Endereos altos de memria

    Endereos baixos de memria

    Figura 2.5.2: Sees de um frame da pilha.

    Para demonstrar os componentes da pilha, temos a seguir um exemplo:

    Parmetros da funo

    Endereo de retorno da

    funo

    Frame pointer da funo

    anterior

    Variveis locais

    Int foo (int par1, char par2)

    {

    Int var1 = 7;

    Char var2 = z;

    Return 0;

    }

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

    {

    Foo (3, A);

    Return 0;

    }

  • 21

    Aps uma execuo da funo foo() e verificando os seus valores usando as ferramentas gdb e

    Eclipse, podemos observar na pilha os seguintes valores:

    Figura 2.5.2.1: dados da pilha em uma execuo do programa.

    Representado graficamente, temos:

  • 22

    2.5.3 Operaes da Pilha

    Para melhor entender como ocorrem os estouros de buffer essencial conhecer as

    operaes que ocorrem na pilha tanto na chamada de uma funo como no seu retorno. Ao

    executar um procedimento, h um desvio de fluxo de execuo para a rea de memria onde se

    encontram as instrues da funo chamada. Espera-se que no final de sua execuo, a funo

    chamada retorne para o ponto da funo original, como o endereo de retorno e o valor do frame

    pointer anterior. Veremos a seguir as operaes bsicas que ocorrem na pilha para que esse

    fluxo funcione corretamente. A conveno usada cdecl, que a padro para arquiteturas Intel

    x86.

    Para que uma funo chame outra, tipicamente ocorrem os seguintes passos (TENOUK,

    2008):

    Colocar parmetros na pilha: necessrio que a funo chamada tenha acesso aos

    parmetros que lhe foram repassados. Para isso, a funo chamadora coloca os

    parmetros da funo na pilha.

    Chamar a funo: a instruo assembly call a responsvel por colocar o valor EIP

    (endereo de retorno) na pilha e por desviar o fluxo de execuo para onde se

    encontra a funo chamada. Esse passo realizado executando-se o seguinte

    comando assembly:

    call

    Desviado o fluxo de execuo para a funo chamada, executada uma srie de

    comandos padres para inicializar o novo frame com informaes essenciais para o seu correto

    funcionamento (TENOUK, 2008). Essa etapa chama-se prlogo, e nela ocorrem os seguintes

    passos:

    Salvar o frame pointer antigo da pilha: para que a funo chamada possa restaurar o

    frame da funo chamadora, necessrio gravar o EBP na pilha. O comando assembly

    usado para essa operao :

    Push %ebp

    Alocar um novo frame: para estabelecer um novo frame, o frame pointer deve receber

    o endereo de memria onde ficar alocado o frame da pilha. Para tal, o registrador EBP

  • 23

    receber o valor contido no Stack pointer, que aponta para o endereo de memria onde

    se encontra o valor do EBP salvo no passo anterior. A instruo realizada :

    mov %esp, %ebp

    Alocar espao para variveis locais: conforme visto anteriormente, as variveis locais

    de uma funo ficam armazenadas na pilha e logo aps o frame pointer. Para garantir

    espao em memria para elas, necessrio aumentar o tamanho da pilha, e isso

    realizado com a instruo assembly sub como no exemplo:

    Sub $0x38, % esp

    Aps executar o prlogo, o frame da pilha est pronto para execuo e a funo pode

    seguir o seu processamento. Antes de retornar o controle ao procedimento chamador, a funo

    deve seguir uma srie de instrues para liberar a memria da pilha e restaurar o frame anterior

    (TENOUK, 2008). Esse processo chamado de eplogo, e suas etapas so detalhadas a seguir:

    Destruir o frame da pilha: os Stack pointer recebe o valor do frame pointer, liberando

    as variveis locais da funo. Devemos observar que os valores da rea da memria

    onde se encontram as variveis no so alterados, apenas perde-se a referncia aos seus

    dados. Aps isso, o valor do frame pointer da funo chamadora salvo na pilha

    restaurado para o registrador EBP. A instruo assembly responsvel por executar esse

    comando :

    Leave

    Restaurar o fluxo de execuo anterior; para que o controle possa ser retomado ao

    procedimento anterior, a funo chamada deve buscar da pilha o endereo de retorno da

    funo chamadora. Esse endereo ento copiado para o registrador EIP, que o

    ponteiro para a prxima instruo. Essa etapa realizada pelo comando assembly:

    Ret

    Exemplo

    Para facilitar o entendimento de como funciona a pilha em chamadas de funes,

    ser apresentado a seguir um cdigo fonte em C e seu respectivo cdigo assembly

    gerado.

  • 24

  • 25

    Analisando o cdigo assembly do programa pode-se demonstrar graficamente como

    ficaro os valores em memria da pilha durante a sua execuo

    2.5.4 Buffer Overflow (Estouros de Buffer)

    Aqui apresentarei o que estouros de buffer, como ocorrem e como e quando essa

    vulnerabilidade pode ser explorada.

  • 26

    Um buffer simplesmente um bloco contiguo de memria de um computador, como um

    array de caracteres. Nos compiladores C, qualquer varivel pode ser alocada em tempo de carga

    diretamente na rea de dados de um processo (variveis estticas) ou carregadas dinamicamente

    em tempo de execuo na pilha (variveis dinmicas). Pela expresso Overflow (Estouro em

    portugus), entende-se ter o contedo fluindo sobre ou derramado, como em um continer

    cheio alm de sua capacidade. Estouro de buffer inserir dados em uma varivel alm do

    limite de memria alocada para ela pelo compilador (ALEPHONE, 1996).

    Alguns compiladores (como C e C++) no realizam checagem automtica de limites de um

    buffer, ou seja, qualquer tentativa de escrever dados em memria alm do limite de tamanho de

    um buffer permitida. Quando isso acontece, frequente ocorrer uma falha de segmentao na

    execuo do programa, pois ele est tentando acessar uma rea de memria no permitida. Por

    exemplo:

    Int main () {

    char buffer [10];

    buffer [11] = A;

    }

    O cdigo acima em C um programa vlido, e compila sem nenhum erro. Nele alocada

    uma varivel buffer, o qual possui 10 posies. Como ndices desse array variam de 0 a 9, ao

    tentarmos atribuir o valor A ao ndice 11 estamos na verdade sobrescrevendo uma rea da

    memria que no pertence a essa varivel. O byte seguinte ao ltimo ndice alocado buffer

    ser sobrescrito com o valor de A, e isso pode alterar o espao de memria alocado a outra

    varivel. Dependendo do tamanho do valor sobrescrito, o endereo de retorno armazenado na

    pilha pode ser alterado. Quando isso ocorre, o mais frequente o sistema operacional acusar

    uma falha de segmentao e abortar a execuo do programa, pois ele est tentando acessar um

    endereo invlido. Porm, essa vulnerabilidade pode ser usada para comprometer a segurana

    da mquina onde ele est sendo executado, se o programa vulnervel possuir permisses

    privilegiadas.

    Abaixo mais um exemplo:

  • 27

    Esse programa seta todos os 255 bytes da memria da varivel loc1 com valor A e a

    passa como parmetro para a funo foo(). Nela, a varivel recebida por parmetro copiada

    para um buffer local loc2 de 16 bytes usando-se a funo strcpy(). Porm, essa funo no

    executa nenhuma checagem de limites para verificar se a varivel loc2 tem espao alocado para

    armazenar toda string par, pois ela o copia at encontrar o caracter nulo \0. Se observarmos o

    estado da pilha dentro da funo foo(), teremos:

    Figura 1: estado da pilha antes da execuo de uma funo varivel.

  • 28

    Figura 2: estado da pilha depois da execuo de uma funo varivel.

    2.5.5 Shell Code

    Para que possamos executar cdigos maliciosos diretamente na pilha ou em outras

    partes da memria, necessrio criar cdigos assembly que representam as instrues que

    desejamos injetar na mquina alvo. Um shell code nada mais do que um programa em

    linguagem de mquina que abre um shell, como o cmd no sistema operacional Windows e

    /bin/sh no Linux. Escolhe-se abrir um shell porque a partir dele, pode-se executar qualquer

    outro comando na mquina. Porm no qualquer shell que nos dar acesso total mquina

    alvo, mas apenas um shell com permisses de root ou privilgios de administrador. Para que

    isso seja possvel, necessrio que o programa vulnervel tenha permisses elevadas no

    sistema, pois assim ao abrir-se um shell a partir dele, teremos os mesmos privilgios do

    programa atacado. Unindo um shell com a permisso root, teremos em mos os maiores

    privilgios da mquina, o que permitir acesso a todos os seus recursos (ALEPHONE, 1996).

    Shell codes so tipicamente inseridos na memria do computador atacado explorando-

    se falhas de estouros de pilha, de heap ou de strings de formatao. A maneira mais usual

    sobrescrever o endereo de retorno armazenado na pilha de uma funo para que aponte para o

    endereo onde se encontra o shell code a ser injetado. Como resultado, ao invs da subrotina

    retornar para a funo chamadora, retornar para o shell code, e abrir um novo shell. Em um

  • 29

    programa C, shell code ser uma lista de caracteres em hexadecimal que representam os

    comandos assembly que desejamos injetar na mquina alvo (ALEPHONE, 1996).

    2.5.6 Criando um Shell Code

    Veremos os processos necessrios para a criao de um shell code. Basicamente, esse

    processo se resume em 5 passos:

    1. Criar o programa em uma linguagem de alto nvel (como em C) que execute o programa

    que desejamos replicar;

    2. Analisar o cdigo assembly desse programa para filtrar s aqueles comandos

    necessrios para reproduzir o programa original;

    3. Criar um novo programa em assembly que execute os comandos analisados no passo 2;

    4. Descobrir quais so as instrues de mquina (ou opcodes) e operandos que

    correspondem aos comandos do programa assembly criado;

    5. Criar e testar o shell code criado a partir dos opcodes e operandos descobertos.

    Exemplo:

  • 30

    O programa acima simplesmente encerra a sua execuo com o cdigo de sada setado

    para o valor 20. O trecho de cdigo assembly abaixo executa a chamada para a funo exit():

    exit (20);

    : mov1 $0x14, (%eap)

    : call 0x80482f4

    O trecho de cdigo acima executa uma chamada de sistema (ou system call, ou ainda

    syscall). Chamada de sistema o mecanismo utilizado por aplicaes para requisitar um servio

    no sistema operacional. O servio requisitado um ndice de uma tabela, passado pelo

    registrador EAX, e o comando para executar a interrupo int 0x80. Logo, os comandos acima

    executam uma chamada de sistema, requisitando a execuo do servio de ndice 0xfc (252, em

    decimal). Verificando a que servio esse ndice se refere na tabela de syscall (usualmente, uma

    se encontra em /usr/include/asm/unistd_32.h), vimos que o valor 252 se refere ao servio

    _exit_group(). Esse servio, conforme descrito em sua pgina man, anlogo a exit(), porm

    ele encerra a execuo no apenas de thread atual, mas de todas aquelas presentes no grupo de

    threads correntes. Como nosso shell code possuir uma thread nica, esse trecho de cdigo

    assembly desnecessrio.

    : mov $0x1, %eax

    : int $0x80

    O trecho de cdigo acima tambm executa uma chamada de sistema, porm o servio

    requisitado outro. Verificando na tabela de syscall qual servio corresponde ao ndice 1,

    descobrimos que _exit() o correspondente esse ndice. Conforme sua pgina man a execuo

    deste servio encerra um processo, e este efeito que desejamos reproduzir. Logo, esses

    comandos assembly devem constar em nosso shell code.

    Para reproduzir corretamente o efeito da chamada de servio _exit(), devemos:

    1. Copiar o valor de sada para o registrador EBX.

    2. Copiar o valor 0x1 para o registrador EAX referente ao ndice da tabela de syscall para

    o servio _exit();

  • 31

    3. Executar o comando de interrupo int 0x80.

    O seguinte cdigo assembly foi gerado para reproduzir os efeitos acima citados:

    .text

    .glob1 _start

    _start :

    Mov1 $20 %ebx

    Mov1 $1, %eax

    Int $0x80

    Compilamos e lincamos o cdigo acima com os comandos abaixo, respectivamente:

    as o ExitShellcode.o ExitShellcode.s

    ld o ExitShellcode ExitShellcode.o

    Executando os comandos acima, o programa ExitShellcode ser criado. Se estiver

    correto, o programa deve apenas terminar sua execuo, retornando o valor de sada 20. Para

    confirmar que o programa escrito em assembly est realizando o esperado, o executamos

    usando a ferramenta gdb.

    2.5.7 Stack Smashing (Esmagamento de Pilha)

    Denomina-se Stack Smashing a tcnica usada para explorar vulnerabilidades em um

    programa de sobrescrevendo dados escritos na pilha. A primeira referncia existente sobre essa

    tcnica data de 1972, quando Anderson o apontou no artigo Computer Security Technology

    Planning Study: The code performing this function does not Check the source and destination

    adresses properly, permiting portions of the monitor that will permit the user to seize controlo

    f the machine. (1972, p.61). A tcnica de esmagamento de pilha ficou mais conhecida com o

    avano dos computadores pessoais. A primeira explorao documentada que utiliza estouros de

    buffer foi em 1988, que era uma das diversas formas que o vrus Morris Worm usava para se

    propagar pela internet. O programa atingido era um servio UNIX chamado finger. Em 1995,

    Thomas Lopatic redescobriu a tcnica utilizada e a publicou na lista

    De e-mails de segurana Bugtraq. Elias Levy (mais conhecido como Aleph One) publicou em

    1996 o artigo Smashing the Stack for fun and Profit, que descreve detalhadamente o processo

    de explorao dos estouros de buffer (Wikipdia,2009).

    A ideia da tcnica sobrescrever no buffer vulnervel o shell code criado acrescido com

    o endereo do prprio buffer. Entende-se por buffer vulnervel a rea de memria usada em

  • 32

    uma operao insegura, como a cpia de uma string para outra sem checagem de limites de

    buffer. Com isso, espera-se que o endereo de retorno localizado na pilha seja sobrescrito pelo

    endereo de memria onde se encontra o shell code a ser executado (ALEPHONE, 1996).

    Abaixo um esquemtico da pilha antes e depois do ataque que ser realizado.

    Figura 3: esquemtico de um ataque de esmagamento de pilha.

    O objetivo inserir no buffer vulnervel o cdigo shell criado, preencher o restante do buffer

    com dados irrelevantes at chegarmos no ponto onde se encontra o endereo de retorno, para

    finalmente o sobrescrevermos com o endereo de memria onde se encontra o incio do shell

    code. Feito isso, quando a funo encerrar sua execuo, ao invs de devolver o fluxo de

    execuo para a funo chamadora ir setar o EIP para o incio do buffer, onde se encontra o

    shell code injetado.

    Abaixo est um tpico programa vulnervel:

  • 33

    O programa acima descreve uma string de entrada e o copia para a varivel buffer sem realizar

    nenhuma checagem de limites. Isto , se a string passada como parmetro for maior que o

    tamanho do buffer, dados da pilha sero sobrescritos. Para reproduzir uma explorao via

    esmagamento de pilha, necessrio criar um programa que construa uma string conforme o

    esquemtico abaixo tal que, ao ser passada essa string para o programa vulnervel, seja possvel

    abrir um novo shell, e para tal temos trs problemas iniciais:

    Figura 3.1 Esquemtico da funo execve.

    1. Como passar a string para o programa invadido?

    Muitos dos caracteres da string que ser passada como parmetro ao programa,

    incluindo aquelas pertencentes ao shell code, no possuem uma representao em um

    teclado convencional. Logo, para passar a string ao programa vulnervel, devemos usar

    uma outra tcnica. Para facilitar, ser setada em uma varivel de ambiente a string

    gerada por nosso programa, para posteriormente ser ela usada para a explorao;

    2. Como descobrir um buffer vulnervel e o tamanho da entrada para causar o

    estouro?

    Como na maioria dos casos o atacante no tem conhecimento das fontes do programa

    que ele deseja explorar, a descoberta de uma falha de segurana puramente via

    experimentao. O hacker pode tentar alterar o tamanho de diversos parmetros de

    entrada do programa para descobrir uma combinao que gere uma falha. Se a

    vulnerabilidade existir, deve-se descobrir qual o parmetro que causa o erro, e qual

    o tamanho do dado passado que gerou a falha;

  • 34

    3. Como descobrir qual o endereo do buffer onde foi injetada a string?

    Para nosso ataque ter sucesso devemos inserir na string criada o endereo do buffer, que

    o local onde se encontra o shell code. Porm, no possvel saber de antemo que

    endereo esse, pois desconhecido o local exato onde o programa invadido est

    carregado em memria. Contudo normalmente ros sistemas operacionais carregam os

    dados da pilha em um mesmo endereo, e isto implica no fato de que a varivel que foi

    usada para a injeo do shell code deva estar em algum deslocamento a partir do

    endereo inicial. Isso diminui o escopo da busca, porm no a elimina, ainda teremos

    que buscar via fora bruta o endereo exato do buffer para o ataque ter sucesso

    (ALEPHONE, 1996).

    2.5.8 COMO SE PROTEGER CONTRA BUFFER OVERFLOW

    Estouros de buffer tem liderado h algum tempo a lista de ataques mais executados do

    mundo, de acordo com a CISCO. Por isso, diversos mtodos foram criados para implantar

    protees extras contra meios de explorao conhecidos e promover uma maior confiabilidade

    nos sistemas. Existem diversas tcnicas que ajudam a melhorar a segurana dos programas

    criados. A maioria delas se divide em 3 vertentes:

    Melhores prticas de programao.

    A maioria das vulnerabilidades de softwares poderiam ser evitadas com boas

    prticas de desenvolvimento. Um programador consciente das tcnicas usadas para

    explorar um software alheio estar muito melhor preparado para defender seu prprio

    sistema de futuras invases. Ele deve sempre ter em mente que qualquer informao de

    entrada de programa uma possvel tentativa de subverte-lo, logo todos os dados de

    input devem ser devidamente validados;

    Proteo pelo sistema operacional.

    Consiste em oferecer mecanismos de segurana ao nvel de kernel do sistema

    operacional. Como ele possui o total controle sobre os recursos do sistema, est apto a

    fornecer medidas eficientes para combater vulnerabilidades em seus aplicativos. Dentre

    elas, esto a randomizao do espao de endereamento de memria e sua proteo

    contra execues indevidas;

    Proteo pelo computador.

    Sendo ele uma camada entre o cdigo criado pelo desenvolvedor e o programa

    em si, o computador pode adicionar medidas de segurana implicitamente no software

  • 35

    gerado. Tipicamente, essas tcnicas inserem um valor no local da pilha entre o endereo

    de retorno e as variveis automticas, de forma que o seu valor for alterado durante a

    execuo do procedimento, detecta-se um erro e o programa deve ser abortado.

    Existem diversas tcnicas criadas para dificultar a explorao de

    vulnerabilidades em softwares. Mas nenhuma delas provou-se totalmente eficiente sem

    causar um impacto considervel na performance de um sistema. A maneira mais eficaz

    de se evitar falhas que possam ser exploradas desenvolver programas tendo como foco

    a segurana do sistema.

    2.5.9 Stack-Smashing Protector (SSP)

    O Stack-Smashing Protector, tambm conhecido como SSP, uma extenso do GNC

    (GNU Compiler Collection) criada por Hiroaki Etoh que fornece mecanismos de proteo

    contra ataques de esmagamento de pilha, ele fornece uma proteo extra para evitar que

    exploraes baseadas na alterao do endereo de retorno de uma funo tenham sucesso.

    A tcnica tem como objetivo proteger sistemas escritos em C inserindo automaticamente

    cdigo de proteo em uma aplicao em tempo de compilao. Isso realizando inserindo-se

    cdigo que permite a deteco de estouros de buffer (ideia herdada do sistema StackGuard) e

    realizando a reordenao de variveis para evitar a corrupo de ponteiros (ETOH, 2002).em

    sistemas que possuem a proteo do SSP como uma extenso padro, ele pode ser desligado

    usando o flag fno-stack-protector do GCC. Para ativ-lo, basta adicionar a flag fstack-

    protector para protees em array de caracteres ou fstack-protector-all para protees de todos

    os tipos.

    Dentre as suas caractersticas, pode-se citar (ETOH, 2002):

    Deteco de alteraes no endereo de retorno adicionando-se um valor conhecido na

    rea de memria entre o endereo de retorno e as variveis locais da funo (chamado

    de canrio). Se houver alguma alterao nesse valor durante a execuo da funo,

    houve um estouro;

    Reordenao das variveis locais, movendo todos os buffers para a rea de memria

    aps a rea onde se localizam os ponteiros, para evitar a sua corrupo. Esses ponteiros

    ponteiros poderiam ser usados para corromper ainda mais outras reas de memria;

  • 36

    Cpia dos ponteiros referentes aos argumentos da funo para um espao de memria

    anterior aos buffers locais da funo, tambm para evitar a sua corrupo e seu possvel

    uso para corromper ainda mais a integridade do sistema;

    2.6 Mtodo de Proteo

    Para gerar um cdigo com melhores mecanismos de proteo, o SSP ajuda a proteger o

    programa defendido de trs tipos de ataques conhecidos. Esses ataques baseiam-se na mudana

    dos valores das seguintes reas de memria:

    Endereo de retorno: o local mais usado para se explorar falhas de segurana. Atravs

    dele, pode-se desviar o fluxo de execuo de uma funo aps o seu epilogo;

    Variveis locais e argumentos de funo: se uma varivel local ou argumento for um

    ponteiro de funo, possvel alterar o seu valor para que aponte para o shell code

    injetado;

    Ponteiro para o frame anterior: o atacante tambm pode injetar shell code alterando o

    ponteiro para o frame da funo anterior. Isso se realiza criando-se um frame falso que

    execute o cdigo shell, e alterar o valor de frame salvo na pilha para que aponte para o

    indevido.

    2.6.1 Canrios

    Chamam-se canrios os valores conhecidos adicionados para possibilitar a deteco de

    alteraes no endereo de retorno ou frame pointer da funo, causadas por estouros de buffer.

    um valor gerado no prlogo da funo e testado no seu eplogo, posicionando-se na rea de

    memria logo abaixo do frame pointer (no SSP) ou do endereo de retorno (no StackGuard).

    Se houver alguma alterao no seu valor durante a execuo da funo, assume-se que houve

    um estouro de buffer em algum ponto e o programa abruptamente encerrado (COWAN et al,

    1998).

    A sua terminologia foi herdada dos canrios usados em minas de carvo para deteco

    de gases nocivos. Sendo esses pssaros mais sensveis, eles seriam afetados antes dos

    mineradores e forneceriam uma forma de aviso de perigo. A primeira implementao dessa

    tcnica foi em 1998 por Crispin Cowan, a ideia era de criar um mecanismo de proteo

    executado pelo prprio compilador que garantisse uma maior segurana no cdigo gerado, sem

    depender exclusivamente das habilidades dos desenvolvedores. A sua implementao no GCC

    foi disponibilizada, porem posteriormente foi substitudo em favor do SSP.

    Existem trs tipos de canrios atualmente em uso, so eles (GUPTA, SHARMA; 2008):

    Canrios randmicos.

  • 37

    So aqueles cujos valores so gerados aleatoriamente, criados normalmente por um

    gerador de nmeros aleatrios confivel, como o urandom dos sistemas Linux. A ideia

    por tras deste tipo de canrio tornar praticamente impossvel seu valor ser descoberto.

    Valores desconhecidos de canarios so desejados porque impossibilitam um atacante de

    realizar um estouro sobrescrevendo o valor do canrio para burlar a deteco. Esse valor

    normalmente escolhido na inicializao do programa e armazenado em uma rea de

    memria segura, de praticamente impossvel acesso por programas externos, a no ser

    que eles saibam seu endereo exato;

    Canrios XOR randmicos.

    So canrios randmicos embaralhados usando operaes XOR sobre todos os dados de

    controle. Assim, caso haja alguma alterao no canrio ou em algum ponto de rea de

    controle, o estouro detectado. Isso dificulta a descoberta do canrio, pois alm do seu

    valor, tambm necessrio descobrir o algoritmo utilizado e os dados de controle;

    Canrios terminadores.

    So aqueles compostos de caracteres terminadores como 0x0a (line feed), 0x0d

    (carriage return), 0x00 (NULL), e 0xff (end of file). Sua idia baseada na observao

    de que estouros de buffer geralmente so explorados em funes que manipulam strings.

    Um ponto negativo que o valor do canrio conhecido. Assim se houvesse duas

    situaes de estouros de buffer em uma mesma funo, a primeira poderia ser usada

    para alterar o endereo de retorno enquanto que a segunda seria usada para restaurar o

    valor do canrio.

    O StackGuard implementa todos os trs tipos de canrios, enquanto que o SSP

    implementa os canrios randmicos e terminadores.

    2.6.2 Modelo de Funo Segura

    Para garantir que os dados armazenados na pilha estejam seguros contra estouros de

    buffer, o SSP introduz um modelo para gerar funes seguras. Segue abaixo o esquemtico do

    modelo ideal de um frame da pilha proposto por Etoh (2002).

  • 38

    Figura 3.2 Modelo de funo segura do SSP.

    Acima foi esquematizado o modelo ideal de um frame de pilha. Basicamente o modelo

    visa isolar os arrays que podem vir a vazar dados, para que seu estouro no afete as outras

    variveis locais da funo. Isso garante a integridade das variveis automticas no decorrer da

    funo, e evita o seu possvel uso para a injeo de shell code. Analisando o esquemtico, pode

    ser visto que aps o frame pointer adicionado o canrio. Alm disso a rea de memria

    reservada as variveis locais foi dividida em duas partes: os arrays e o restante das variveis

    locais.

    Com esta organizao o modelo garante as seguintes propriedades (ETOH, 2002): A

    rea de memria fora da funo vulnervel no ser danificada quando a funo retornar. A

    regio onde se encontram os buffers o nico ponto vulnervel onde um ataque pode ter incio.

    Danos aos frames de outras funes podem ser detectados pela alterao de valor do canrio,

    pois caso haja um estouro seu valor ser invariavelmente sobrescrito (lembrando que a escrita

    em memria ocorre dos endereos mais baixos aos mais altos). Se o dano ocorrer, a execuo

    do programa ser encerrada prematuramente ao trmino da funo;

    Ataques em ponteiros de funes em um frame da pilha no sero danificados.

    Com a reordenao das variveis locais, um estouro em um array no prejudicar a

    integridade dos dados das outras variveis automticas da funo. Isso garante que, caso

  • 39

    exista algum ponteiro para uma funo, ele no seja sobrescrito e consequentemente

    usado para a injeo de shell code.

    Para alcanar esse novo modelo de organizao da pilha, o SSP necessita introduzir uma

    srie de mudanas no cdigo gerado. A linguagem C no possui restries quanto a reordenao

    das variveis automticas de uma funo, porm no permite a alterao da localizao dos

    argumentos. Para burlar essa restrio, pode-se criar uma nova varivel local, copiar o valor do

    argumento para ela e mudar a referncia do argumento para usar a nova varivel local protegida

    (ETOH, 2002).

    3.0 Defesa contra-ataques de injeo de SQL!

    Sem garantias adequadas, as aplicaes so vulnerveis a diversas formas de ataque

    segurana. Um mtodo particularmente difundido de ataque chamado de injeo de

    SQL(SQLI). Usando este mtodo, um hacker pode passar a entrada sequncia de caracteres

    para uma aplicao com a esperana de obter acesso no autorizado a um banco de dados.

    3.1 O que SQL Injection ou (injeo de SQL) em traduo livre?

    Injeo de SQL uma tcnica que explora maliciosamente aplicativos que usam os

    dados fornecidos pelo cliente em instrues SQL. Os invasores enganam o motor de SQL para

    executar comandos no intencionais atravs do fornecimento de entrada de string ou

    caracteres especiais criados, ganhando assim acesso no autorizado a um banco de dados, a fim

    de exibir ou manipular dados restritos.

    Tcnicas de injeo SQL pode ser diferente, mas todos eles exploram uma nica

    vulnerabilidade na aplicao:

    Observao: strings literais Incorretamente validado ou no validadas esto

    concatenadas em uma instruo SQL dinmica, e interpretado como cdigo pelo motor SQL.

    3.1.1 Utilizao e uso do mtodo SQLI?

    SQL em pginas da web

    Quando o SQL usado para exibir dados em uma pgina web, comum usurios de

    internet deixarem suas prprias entradas de valores de pesquisas. Desde que instrues SQL

    sejam apenas texto, fcil, com um pequeno pedao de cdigo de computador, para alterar

  • 40

    dinamicamente instrues SQL para fornecer ao usurio com os dados selecionados conhecida

    comumente com jargo m higiene:

    Cdigo servidor

    TxtUserId = getRequestString("UserId");

    txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;

    O exemplo acima, cria uma instruo select, adicionando uma varivel (txtUserId) para uma

    cadeia de seleo. A varivel obtida a partir da entrada do usurio (Request) para a pgina.

    3.1.2 SQL Injection com base em 1 = 1 sempre verdadeiro

    Olhe para o exemplo acima, mais uma vez. Vamos dizer que o propsito original do

    cdigo era criar uma instruo SQL para selecionar um usurio com um determinado ID de

    usurio. Se no h nada para impedir que um usurio entrar entrada "errado", o usurio pode

    digitar algumas informaes "inteligente" como este:

    ID do usurio:

    Resultado servidor

    SELECT * FROM Users WHERE UserId = 105 or 1=1

    O SQL acima vlido. Ele ir retornar todas as linhas da tabela de usurios, uma vez que

    1 = 1 sempre verdadeiro.

    Ser que o exemplo acima parece perigoso? O que se a tabela de Usurios contm nomes

    e senhas? A instruo SQL acima o mesmo que isto:

    SELECT UserId, Name, Password FROM Users WHERE UserId = 105 or 1=1

    Um hacker inteligente pode ter acesso a todos os nomes de usurio e senhas em um

    banco de dados, simplesmente inserindo 105 ou 1 = 1 na caixa de entrada, resumindo no houve

    uma boa higienizao de cdigo, no momento de executar o motor SQL.

    3.1.3 Injeo SQL baseado em sempre verdadeira.

    Aqui uma construo comum, usado para verificar login de usurio para um site:

    Nome de usurio:

    Senha:

    105 or 1=1

  • 41

    Cdigo Servidor

    uName = getRequestString("UserName");

    uPass = getRequestString("UserPass");

    sql = "SELECT * FROM Users WHERE Name ='" + uName + "' AND Pass ='" + uPass + "'"

    Um hacker inteligente pode ter acesso aos nomes de usurio e senhas em um banco de

    dados, simplesmente inserindo "ou" = na caixa "" o nome de usurio ou senha texto.

    O cdigo no servidor ir criar uma instruo SQL vlida como este:

    Resultado

    SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""

    O SQL resultado vlido. Ele ir retornar todas as linhas da tabela de usurios,

    desde onde "" = ""sempre verdade.

    3.1.4 SQL Injection com base em instrues SQL em lote

    A maioria dos bancos de dados suportam instruo SQL em lote, separados por ponto e

    vrgula.

    EXEMPLO: SELECT * FROM Users; DROP TABLE Suppliers

    O SQL acima ir retornar todas as linhas na tabela de usurios e, em seguida, elimine a

    tabela chamada Fornecedores.

    Se tivssemos o seguinte cdigo do servidor:

    Cdigo Servidor:

    TxtUserId = getRequestString("UserId");

    txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;

    E a seguinte entrada:

    ID do usurio:

    O cdigo no servidor iria criar uma instruo SQL vlida como este:

    Resultado

    SELECT * FROM Users WHERE UserId = 105; DROP TABLE Suppliers

    3.1.5 Parmetros para a Proteo (Higienizao)

    Alguns desenvolvedores web usar uma "lista negra" de palavras ou caracteres para

    pesquisar na entrada SQL, para evitar ataques de injeo SQL. Esta no uma idia muito

    boa. Muitas destas palavras (like delete or drop) e caracteres (como o ponto e vrgula e aspas),

    so utilizados em linguagem comum, e deve ser permitido em muitos tipos de entrada.

  • 42

    (Na verdade ele deve ser perfeitamente legal para introduzir uma instruo SQL em um campo

    de banco de dados.)

    A nica forma comprovada de proteger um site de ataques de injeo SQL, a utilizao

    de parmetros SQL. Parmetros SQL so valores que so adicionados a uma consulta SQL em

    tempo de execuo, de uma forma controlada.

    3.1.6 ASP.NET Navalha Exemplo

    txtUserId=getRequestString("UserId");

    txtSQL="SELECT * FROM Users WHERE UserId = @0";

    db.Execute(txtSQL,txtUserId);

    Note-se que os parmetros so representados na instruo SQL por um @ marcador.

    O motor SQL verifica cada parmetro para garantir que ele est correto para sua coluna e so

    tratados literalmente, e no como parte do SQL para ser executado.

    Exemplo bsico:

    txtNam=getRequestString("CustomerName");

    txtAdd=getRequestString("Address");

    txtCit=getRequestString("City");

    txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";

    db.Execute(txtSQL,txtNam,txtAdd,txtCit);

    Voc aprendeu apenas para evitar a injeo SQL. Uma das vulnerabilidades de sites de

    topo.

    Exemplos em mais algumas linguagens:

    Os exemplos a seguir mostram como criar consultas parametrizadas em algumas

    linguagens web comuns.

    Instruo select in asp.net:

    txtUserId = getRequestString("UserId");

    sql = "SELECT * FROM Customers WHERE CustomerId = @0";

    command = new SqlCommand(sql);

    command.Parameters.AddWithValue("@0",txtUserID);

    command.ExecuteReader();

  • 43

    INSERT INTO DECLARAO NA ASP.NET:

    txtNam = getRequestString("CustomerName");

    txtAdd = getRequestString("Address");

    txtCit = getRequestString("City");

    txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";

    command = new SqlCommand(txtSQL);

    command.Parameters.AddWithValue("@0",txtNam);

    command.Parameters.AddWithValue("@1",txtAdd);

    command.Parameters.AddWithValue("@2",txtCit);

    command.ExecuteNonQuery();

    3.1.7 INSERT INTO DECLARAO EM PHP:

    $stmt = $dbh->prepare ("INSERT INTO Customers (CustomerName.Address,City)

    VALUES (:nam, :add, :cit)");

    $stmt->bindParam(':nam', $txtNam);

    $stmt->bindParam(':add', $txtAdd);

    $stmt->bindParam(':cit', $txtCit);

    $stmt->execute();

    4.0 Criptografia

    Em grego, cryptos significa secreto, oculto. A criptografia estuda os mtodos para

    codificar uma mensagem de modo que s seu destinatrio legtimo consiga interpret-la. a

    arte dos cdigos secretos.

    O Cdigo de Csar

    Um dos cdigos secretos mais simples consiste em substituir uma letra do alfabeto pela

    seguinte. Por exemplo, a mensagem AMO A OBMEP seria codificada como

    BNPBPCNFQ:

    Um cdigo semelhante a este foi usado, por exemplo, pelo ditador romano Jlio Csar

    para comunicar-se com as legies romanas em combate pela Europa. Este parece ser o primeiro

    exemplo de um cdigo secreto de que se tem notcia.

  • 44

    Figura: Jlio Csar (100-44 a.C.)

    Vejamos como codificar uma mensagem simples. Cdigos como o de Csar padecem

    de um grande problema: so muito fceis de quebrar. Quebrar um cdigo significa ser capaz

    de ler a mensagem, mesmo no sendo seu destinatrio legtimo. Na verdade, qualquer cdigo

    que envolva substituir cada letra sistematicamente por outro smbolo qualquer sofre do mesmo

    problema. Isto ocorre porque a frequncia mdia com que cada letra aparece em um texto de

    uma dada lngua mais ou menos constante. Por exemplo, a frequncia mdia de cada letra na

    lngua portuguesa dada na tabela 1.

    Assim, apenas contando a frequncia de cada smbolo no texto, podemos descobrir a

    que letra correspondem os smbolos mais frequentes. Isto geralmente suficiente para quebrar

    o cdigo e ler toda a mensagem. Observe, entretanto, que este mtodo para quebrar o cdigo s

    funciona bem se a mensagem for longa. fcil escrever uma mensagem curta cuja contagem

    de frequncia seja totalmente diferente da contagem de frequncia mdia do portugus. Por

    exemplo, em Zuza zoou da Zez a letra mais frequente o Z que aparece 5 vezes em um

    texto de 14 letras. Como 5=14 = 0; 35::: a porcentagem do Z no texto acima de cerca de

  • 45

    35%; muito acima dos usuais 0; 47%. J o A aparece uma s vez, o que d uma porcentagem

    de cerca de 7%; portanto, abaixo dos 14% usuais.

    SUMZFI GCSGC SVZFC LZLSJ EZQSL HIFUI JDZQS LTSRF

    SGCSJ UOZSZ OJTZL ZOEEO LHMSE ESDSL IECLU ILHCD

    ZTIFE SZMOJ QCZSU IJPSU OTZZL ZOIFH ZFDST IHFIU SEEIH

    ITSES FZCDI LZDOA ZTIIG CSDIF JZOJB OZBSO EDITI EIEUI

    TOQIE GCSSJ BIMBS LECVE DODCO UZITS MSDFZ EUILI

    IGCSS EDZLIE CDOMO AZJTI HZFZU ITORO UZFSE DZLSJ

    EZQSL JZBSF TZTSZ MQCJE TIEHF OLSOF IEUIL HCDZT

    IFSER IFZLU FOZTIE HFSUO EZLSJ DSHZF ZZNCT ZFZGC

    SVFZFI EUITO QIEES UFSDI ECEZTI EHSMIE ZMSLZSE

    TCFZJDS ZESQC JTZQC SFFZL CJTOZM SJDFS SEDSE SEDZB

    ZIUIM IEEICL UILHC DZTIF UIEJD FCOTI JZOJQ MZDSF

    FZHIF CLZSG COHSM OTSFZ TZHIF ZMZJD CFOJQ CLTIE

    RCJTZ TIFSE TZUILH CDZUZI UOSJDO ROUZ

    Exerccio 1. Ser que voc notou que o pargrafo acima foi codificado?

    Use o mtodo de contagem de frequncia para quebrar o cdigo e poder decodificar e ler o

    pargrafo. Para no simplificar as coisas, foram eliminados espaos, acentos e pontuao.

    Cdigos em Bloco

    Por sorte, existe uma maneira simples de tornar invivel a aplicao de uma contagem

    de frequncia. Para isso, subdividimos a mensagem em blocos de vrias letras e embaralhamos

    estes blocos. Por isso este processo de criptografar uma mensagem conhecido como cdigo

    de bloco. Por exemplo, considere a mensagem AMO A OBMEP. Para codific-la seguiremos

    os seguintes passos:

    Eliminamos os espaos e completamos a mensagem com um A no final, caso tenha uma

    quantidade mpar de letras;

    Subdividimos a mensagem em blocos de duas letras;

    Refletimos cada bloco;

  • 46

    Permutamos os blocos trocando o primeiro com o ltimo, o terceiro com a

    antepenltimo, e assim por diante, mas deixando os outros como esto.

    Aplicando isto, passo a passo, mensagem acima, obtemos primeiro

    AMOAOBMEPA

    depois

    AM-OA-OB-ME-PA

    em seguida

    MA-AO-BO-EM-AP

    e, finalmente,

    AP-AO-BO-EM-MA

    que nos d como mensagem codificada

    APAOBOEMMA.

    Exerccio 2. Discuta as seguintes questes com seus colegas:

    (a) Por que a contagem de frequncia no funciona quando usamos cdigos em bloco?

    (b) Por que escolhemos acrescentar exatamente a letra A quando a mensagem tem quantidade

    mpar de letras, em vez de usar, por exemplo, X ou Y?

    Apesar de cdigos como este serem melhores que o cdigo de Csar, eles apresentam

    uma grande desvantagem quando se trata de aplicaes comerciais da criptografia. Por

    exemplo, digamos que resolvo fazer uma compra via web usando o meu computador, em uma

    loja em que nunca comprei antes. Para isso entro na pgina da loja, escolho os produtos que

    desejo e, quando estou pronto para comprar, escolho ir para o caixa. O pagamento ser feito

    usando o meu carto de crdito. Para isso, preciso informar a loja sobre os dados do meu carto:

    geralmente o nmero e a data de vencimento. Mas isto significa que qualquer outra pessoa que

    tenha estes dados pode fazer compras em meu nome. Para evitar este problema, as informaes

    sobre o meu carto so codificadas pelo meu computador antes de serem enviadas.

    Note, contudo, que meu computador no pode usar um cdigo qualquer para codificar

    estas informaes, porque a loja precisa l-las e, para isso, tem que saber como decodificar a

    mensagem. Na prtica o que ocorre que o meu computador comunica-se com o da loja, que

    lhe informa como deve ser feito o processo de codificao. Isto , meu computador codifica as

    informaes do carto de crdito usando um processo de codificao que enviado pela loja.

    Infelizmente os cdigos de blocos no se prestam a este tipo de aplicao porque o computador

    da loja usa a linha telefnica (ou de banda larga) qual meu computador est interligado para

  • 47

    enviar o processo de codificao a ser utilizado. Como fcil pr uma escuta na linha, uma

    outra pessoa pode facilmente descobrir como meu computador vai codificar as informaes

    sigilosas que sero enviadas loja. Usando a mesma escuta fcil interceptar tambm as

    mensagens que contm os dados do carto. Mas isto basta porque, se sabemos como foi feito o

    embaralhamento dos blocos, podemos facilmente desfaz-lo e ler os dados do carto!

    A nica maneira de contornar este problema ter acesso ao que conhecido como um

    canal seguro: uma maneira secreta de fazer a informao sobre o processo de codificao

    chegar at o computador do usurio da loja. Talvez a loja pudesse mandar, pelo correio

    registrado, um carto especial com os dados a serem usados para a codificao. O problema

    que isto tornaria a transao lenta, j que seria necessrio esperar dias pela chegada do carto

    nesse meio tempo eu talvez preferisse escolher uma loja real, mesmo que fosse longe da minha

    casa. E ainda h outro problema, mais srio. Se o meu computador for invadido por um

    hacker, o processo de codificao ser descoberto e qualquer mensagem enviada com ele

    poder ser lida.

    Cdigos de Chave Pblica

    As dificuldades que relacionamos acima parecem condenar de maneira irremedivel a

    possibilidade de fazer transaes pela web. Afinal, seja qual for o cdigo utilizado, se sabemos

    como fazer a codificao, basta desfaz-la e decodificamos a mensagem. Ou no?

    De fato, isto basicamente verdade; mas h um porm. Acontece que podemos imaginar

    um processo que seja fcil de fazer mas muito difcil de desfazer e, ao utiliz-lo para criptografar

    uma mensagem, estaramos garantindo que quem a interceptasse, mesmo sabendo como foi

    codificada, teria um trabalho enorme em decodific-la. Abusando um pouco da fantasia,

    podemos imaginar que o trabalho de desfazer o processo levasse tanto tempo que ningum

    conseguisse p-lo em prtica. claro que quo difcil ser desfazer o procedimento depende

    dos recursos disponveis a quem interceptou a mensagem.

    Vejamos um exemplo. Voc j viu uma dessas armadilhas usadas para pescar lagostas?

    Elas consistem de uma gaiola com uma porta fechada atrs e uma entrada para a lagosta na

    frente.

  • 48

    O segredo est na entrada, que tem a forma de um funil: larga na parte externa e cada

    vez menor medida que a lagosta vai entrando na gaiola.

    Para uma ilustrao da entrada da armadilha veja a figura.

    Figura: Armadilha lagosta.

    A lagosta fica presa na gaiola porque, para poder sair, teria que encontrar e passar pela

    parte estreita do funil, que um problema complicado demais para uma lagosta, cujo crebro

    tem o tamanho aproximado de uma ervilha. No preciso dizer que uma armadilha desse tipo

    no funcionaria para pegar um macaco, nem mesmo um passarinho. Muito interessante, mas

    que problema matemtico satisfaz esta condio de ser fcil de fazer e difcil de desfazer,

    para que possamos utiliz-lo em criptografia? Isto o que veremos na prxima seo. Por

    enquanto, vamos s observar que tais cdigos so conhecidos como de chave pblica, j que o

    processo (ou chave) de codificao pode ser conhecido de qualquer um sem comprometer a

    segurana do cdigo.

    Criptografia RSA

    O mais conhecido dos mtodos de criptografia de chave pblica o RSA. Este cdigo

    foi inventado em 1977 por R. L. Rivest, A. Shamir e L. Adleman, que na poca trabalhavam no

    Massachussets Institute of Technology (M.I.T.), uma das melhores universidades americanas.

    As letras RSA correspondem s iniciais dos inventores do cdigo. H vrios outros cdigos de

    chave pblica, mas o RSA continua sendo o mais usado em aplicaes comerciais.

    O Mtodo RSA

    A descrio completa do funcionamento do RSA justamente o tema desta apostila.

    Para entender como funciona precisaremos estudar vrias ideias e tcnicas novas de

    matemtica. Nesta seo explicaremos apenas o suficiente sobre o RSA para que voc entenda

  • 49

    como possvel um problema ser fcil de fazer e difcil de desfazer. Isto tambm nos ajudar

    a identificar os problemas matemticos que precisaremos abordar para poder discutir os

    detalhes do funcionamento do RSA.

    Digamos que voc vai criar uma implementao do RSA para uma determinada loja,

    que vai us-lo na codificao de dados de clientes em compras pela internet. Para comear,

    voc precisa escolher dois nmeros primos distintos e multiplic-los, obtendo um nmero

    inteiro n. A loja manter secreta a informao sobre quais so os primos escolhidos, porque

    isto que necessrio para decodificar as mensagens enviadas usando a verso do RSA que voc

    est construindo. J n vai ser enviado para o computador de qualquer pessoa que compre nessa

    loja pela web, porque dele que o computador do usurio necessita para codificar os dados

    sobre o do carto de crdito e envi-los ao computador da loja. Portanto, no caso do RSA, o

    problema fcil de fazer e difcil de desfazer simplesmente multiplicar dois primos.

    J consigo imaginar voc pensando: S isso? Mas para desfazer o problema basta fatorar

    o nmero e achar os primos! verdade, mas h um detalhe que esqueci de contar: estes nmeros

    primos sero muito, muito grandes. Na prtica uma chave segura de RSA gerada a partir de

    nmeros primos de cerca de 100 algarismos cada, de forma que n, que o produto destes

    primos, ter cerca de 200 algarismos. Acontece que, como veremos na pgina 29, podem ser

    necessrios zilhes de anos para fatorar um nmero deste tamanho e achar seus fatores primos

    mesmo se usarmos os mais poderosos computadores existentes atualmente.

    Resumindo:

    Para implementar o RSA escolhemos dois primos distintos muito grandes p e q e

    calculamos o produto n = p q;

    Para codificar uma mensagem usamos n;

    Para decodificar uma mensagem usamos p e q;

    n pode ser tornado pblico;

    p e q precisam ser mantidos em segredo;

    Quebrar o RSA consiste em fatorar n, que leva muito tempo se n for grande.

    Teoria de Nmeros

    O que vimos acima sugere que os principais problemas matemticos relacionados ao RSA

    so: como achar nmeros primos e como fatorar um nmero. A rea da matemtica a que estes

    problemas pertencem conhecida como teoria de nmeros e tem por objetivo geral o estudo

  • 50

    das propriedades dos nmeros inteiros. Entre os problemas que teremos que estudar para

    podermos descrever completamente o RSA tambm esto:

    Como calcular os restos da diviso de uma potncia por um nmero dado;

    Como achar um nmero que deixa restos especificados quando dividido por uma srie

    de nmeros dados;

    Como estabelecer critrios de divisibilidade por nmeros primos.

    H muitos outros problemas que so parte da teoria dos nmeros, mas dos quais no

    trataremos aqui, entre eles:

    1. calcular o mximo divisor comum entre dois nmeros dados;

    2. determinar todos os inteiros a, b e c que satisfazem a2+b2 = c2;

    3. mostrar que se trs inteiros a, b e c satisfazem an + bn = cn, onde n > 2 um inteiro positivo,

    ento a, b ou c tm que ser iguais a zero;

    4. provar que 22n + 1 composto se n > 4;

    5. provar que todo nmero par soma de dois primos mpares;

    6. determinar todos os inteiros consecutivos que so potncias de nmeros inteiros.

    Os problemas acima tm grau de dificuldade muito varivel. A soluo de alguns deles

    conhecida desde a antiguidade, como o caso de (1) e (2). Na verdade, bem provvel que

    voc saiba resolver (1) usando o mtodo descrito por Euclides em seu livro Elementos escrito

    por volta de 300 a.C.; j (2) est relacionado ao Teorema de Pitgoras o que talvez baste para

    lembrar-lhe de algumas solues possveis.

    Todas as outras questes so muito mais difceis. Para comear temos (3), que muito

    parecida com (2), exceto pelo fato do expoente n ter que ser pelo menos 3. Este problema tem

    uma histria muito interessante. Em algum momento entre 1621 e 1636 o francs Pierre de

    Fermat, magistrado da corte de Toulouse, adquiriu uma cpia da recm-publicada traduo

    latina da Aritmtica escrita pelo matemtico grego Diofanto mais de mil anos antes. Fermat,

    que era um matemtico amador, leu o texto de Diofanto, fazendo vrias anotaes na margem

    do texto. Em uma dessas anotaes ele afirmou ter uma demonstrao do fato enunciado em

    (3) mas, segundo ele, o espao disponvel na margem do livro no seria suficiente para conter

    seu argumento. improvvel que a demonstrao de Fermat estivesse correta, j que o resultado

    permaneceu sem demonstrao at 1995. Como este foi o ltimo resultado enunciado por

    Fermat a ser demonstrado, tornou-se conhecido como o ltimo Teorema de Fermat. Para

    complicar, os mtodos usados por A. Wiles em sua prova de (3) so extremamente sofisticados

  • 51

    e sequer existiam h 50 anos atrs. A questo (4) outra que est ligada ao nome de Fermat.

    Na verdade, o nmero F(n) = 22n + 1 conhecido como o n-simo nmero de Fermat porque,

    em uma de suas cartas a um outro matemtico, Fermat props que F(n) seria sempre primo,

    qualquer que fosse o valor de n. De fato, calculando F(n) para n de 0 a 4 obtemos os nmeros

    listados na tabela 2, que so todos primos. Aparentemente, foi nessa tabela que Fermat baseou-

    se para fazer a sua afirmao. Infelizmente, generalizar a partir de alguns casos sempre uma

    prtica perigosa em matemtica e, neste caso, Fermat deu-se realmente mal. Nenhum nmero

    primo da forma F(n) conhecido quando n > 4, da o problema enunciado em (4), que ningum

    at hoje sabe como resolver.

    A questo (5) conhecida como Conjectura de Goldbach, em homenagem a Christian

    Goldbach, um outro matemtico amador, que viveu na mesma poca que Euler, com quem

    trocava frequentes cartas sobre matemtica. Embora se saiba que todo nmero par com menos

    de 18 algarismos seja mesmo a soma de dois primos mpares, ningum at hoje conseguiu

    provar o enunciado de Goldbach. Apesar disso, alguns resultados parciais so conhecidos. Um

    dos mais recentes foi a demonstrao descoberta em 2002 por Roger Heath-Brown e Jan-

    Christoph Schlage-Puchta de que todo nmero par muito grande pode ser escrito como a soma

    de dois primos mpares e exatamente 13 potncias de 2. Se voc tentar descobrir duas potncias

    de inteiros pequenos, que sejam consecutivas, vai logo dar de cara com 8 e 9, que so iguais a

    23 e 32, respectivamente. Por mais que procure, no encontrar outros exemplos. Em vista

    disso, o matemtico belga Eugne Charles Catalan props em 1844 que essas duas potncias

    seriam as nicas solues do problema (5). Isto correto, como foi provado pelo matemtico

    romeno Preda Mihailescu em 2002. Talvez voc tenha percebido que, embora os enunciados

    das cinco questes acima sejam muito fceis de entender, resolv-las pode ser muito difcil: o

    ltimo Teorema de Fermat levou mais de 300 anos para ser provado e o problema proposto por

    Catalan levou 158 anos. Sem falar da conjectura de Goldbach e do problema relativo aos

    nmeros de Fermat, que at hoje ningum sabe resolver.

  • 52

    Pr-codificao

    O que fazemos para codificar uma mensagem no RSA calcular sua potncia mdulo n

    relativamente a um expoente especialmente escolhido. Entretanto, para que isto seja vivel, a

    mensagem deve ser um nmero inteiro. Mas no isto o que ocorre em geral: a maior parte das

    mensagens um texto. Por isso, a primeira coisa a fazer, se desejamos usar o mtodo RSA,

    inventar uma maneira de converter a mensagem em uma sequncia de nmeros. Suponhamos,

    para simplificar, que a mensagem original um texto onde no h nmeros, apenas palavras, e

    no qual todas as letras so maisculas. Portanto, em ltima anlise a mensagem constituda

    pelas letras que formam as palavras e pelos espaos entre palavras. Chamaremos esta primeira

    etapa de pr-codificao, para distingui-la do processo de codificao propriamente dito. Na

    pr-codificao convertemos as letras em nmeros usando a seguinte tabela de converso:

    O espao entre duas palavras ser substitudo pelo nmero 99, quando for feita a converso.

    Por exemplo, a frase AMO A OBMEP convertida no nmero:

    1022249910992411221425

    Observe que precisamos fazer cada letra corresponder a um nmero de, pelo menos, dois

    algarismos para evitar ambiguidades. Se fizssemos A corresponder ao nmero 1, B ao 2, e

    assim por diante, no teramos como saber se 12 representa AB ou L, j que esta ltima a

    dcima segunda letra do alfabeto. Antes de continuar precisamos determinar os parmetros do

    sistema RSA que vamos usar. Estes parmetros so dois primos distintos, que vamos denotar

    por p e q, e cujo resto na diviso por 6 tem que ser 5. Em seguida, ponha n = pq. A ltima fase

    do processo de prcodificao consiste em quebrar em blocos o longo nmero produzido

    anteriormente. Estes blocos devem ser nmeros menores que n. Por exemplo, se escolhermos p

    = 17 e q = 23, ento n = 391. Neste caso, a mensagem, cuja converso numrica foi feita acima,

    pode ser quebrada nos seguintes blocos:

    102-224-99-109-92-41-122-142-5.

    A maneira de escolher os blocos no nica e os blocos no precisam sequer ter o mesmo

    tamanho. Contudo, certos cuidados devem ser tomados. Por exemplo, no permitido escolher

    um bloco que comece por 0 porque isto traria problemas na hora de decodificar, j que, por

  • 53

    exemplo, no temos como distinguir o bloco 071 do bloco 71. Observe que os blocos em que

    quebramos a mensagem no correspondem a nenhuma unidade lingustica, seja ela palavra,

    letra ou qualquer outra. Isto muito bom, porque torna a decodificao por contagem de

    frequncia essencialmente impossvel.

    Codificando e Decodificando uma Mensagem

    Encerramos assim a prcodificao, e podemos passar etapa de codificao

    propriamente dita. Para codificar a mensagem precisamos apenas de n, que o produto dos

    primos. Diremos que n a chave de codificao do sistema RSA que estamos usando. Esta

    chave pode ser tornada pblica; isto , podemos envi-la a qual