Atps-Desenvolvimento de Software Seguro
-
Upload
juvenal-f-batista -
Category
Documents
-
view
82 -
download
44
description
Transcript of Atps-Desenvolvimento de Software Seguro
-
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