← Voltar aos artigos

Paper Files / AppSec

Segurança de Aplicações em Sistemas Conectados TCP/IP: Modelagem de Ameaças, Técnicas de Exploração e Estratégias Práticas de Defesa (1989)

AppSecPT

A crescente interconexão de sistemas computacionais através de redes TCP/IP, particularmente em ambientes acadêmicos, militares e corporativos conectados à ARPANET e suas redes derivadas, ampliou significativamente a superfície de ataque de aplicações de software. Enquanto os primeiros esforços de segurança concentraram-se em mecanismos de controle de acesso no nível do sistema operacional, eventos recentes — notavelmente o worm de Internet de 1988 — demonstraram que vulnerabilidades em aplicações podem comprometer sistemas inteiros mesmo quando políticas de segurança no nível do kernel estão corretamente configuradas. Este trabalho apresenta uma análise sistemática da segurança de aplicações (Application Security, ou AppSec) no contexto tecnológico de 1989, com foco em programas escritos predominantemente em C e executados em ambientes UNIX conectados via TCP/IP. Primeiramente, revisamos fundamentos clássicos de segurança de sistemas, incluindo os princípios de Saltzer e Schroeder, modelos de proteção do tipo Bell–LaPadula e mecanismos de autenticação baseados em criptografia simétrica e assimétrica. Em seguida, analisamos classes de vulnerabilidades observadas em serviços de rede amplamente implantados, como `sendmail`, `fingerd`, `rsh` e `rexec`. Particular atenção é dedicada a erros de manipulação de memória, especialmente estouros de buffer em pilha, que possibilitam execução arbitrária de código. Propomos um modelo formal de ameaça para aplicações de rede que leva em consideração capacidades do adversário, topologia de rede e características do compilador e do sistema operacional. Este artigo introduz uma metodologia prática de avaliação de segurança de aplicações composta por quatro fases: análise estática de código-fonte, instrumentação de execução, monitoramento de tráfego de rede e experimentação controlada em ambientes isolados. Demonstramos a aplicação dessa metodologia utilizando ferramentas disponíveis na década de 1980, incluindo `lint`, `adb`, `dbx` e `tcpdump`, além de técnicas de auditoria manual de código. Experimentos realizados em sistemas UNIX 4.3BSD demonstram que uma proporção significativa de vulnerabilidades pode ser identificada antes da implantação por meio de inspeção sistemática de código e testes de robustez. Também apresentamos um estudo de caso detalhado baseado na exploração do `fingerd` que foi utilizada pelo worm de 1988, analisando os mecanismos técnicos que permitiram sua propagação. Finalmente, discutimos implicações para o projeto de software seguro, incluindo validação rigorosa de entrada, redução de privilégios e separação de mecanismos de autenticação. Argumentamos que a segurança de aplicações deve tornar-se uma disciplina central da engenharia de software em ambientes conectados.

  1. Introduction

Durante a década de 1980, a expansão da ARPANET e de redes acadêmicas baseadas em TCP/IP transformou profundamente o modo como sistemas computacionais interagem. Universidades, laboratórios de pesquisa e organizações governamentais passaram a operar serviços de rede acessíveis remotamente, incluindo transferência de arquivos (ftp), login remoto (telnet), execução remota de comandos (rsh) e serviços informativos como finger. Essa conectividade ampliou drasticamente a utilidade das infraestruturas computacionais, mas também introduziu novos vetores de ataque direcionados às aplicações de rede.

Historicamente, a pesquisa em segurança computacional concentrou-se em mecanismos de proteção no nível do sistema operacional. Trabalhos clássicos de Lampson (1974) e Saltzer e Schroeder (1975) estabeleceram princípios fundamentais como privilégio mínimo, separação de mecanismos e auditoria completa. Posteriormente, o Departamento de Defesa dos Estados Unidos formalizou critérios de avaliação de segurança em sistemas computacionais no documento conhecido como Trusted Computer System Evaluation Criteria (TCSEC) ou “Orange Book” (DOD, 1985). Esses esforços enfatizaram isolamento de processos, controle de acesso obrigatório e integridade do kernel.

Entretanto, incidentes recentes demonstraram que falhas em programas de aplicação podem contornar completamente essas proteções. O caso mais notório ocorreu em novembro de 1988, quando um worm autorreplicante explorou vulnerabilidades em serviços amplamente distribuídos na Internet, incluindo sendmail e fingerd. Em poucas horas, milhares de sistemas UNIX foram comprometidos, causando interrupções operacionais significativas em universidades e centros de pesquisa (SPAFFORD, 1989).

Esse episódio revelou um problema estrutural: mesmo quando o sistema operacional implementa corretamente políticas de segurança, aplicações com erros de programação podem fornecer ao atacante um caminho direto para execução arbitrária de código. A maioria desses programas é escrita em linguagem C, que oferece alto desempenho e controle direto de memória, mas também permite classes de erros perigosos como estouros de buffer, uso incorreto de ponteiros e validação inadequada de entrada.

A segurança de aplicações (Application Security, ou AppSec) emerge, portanto, como uma disciplina crítica. Ela envolve o estudo sistemático de vulnerabilidades em software, métodos para detectá-las e mecanismos para preveni-las durante o desenvolvimento. Diferentemente da segurança de sistemas operacionais, que opera no nível do kernel, a AppSec concentra-se no comportamento interno de programas individuais e na forma como eles processam dados externos.

Neste artigo investigamos três questões centrais:

• Quais classes de vulnerabilidades são mais comuns em aplicações de rede UNIX conectadas via TCP/IP?
• Como um adversário remoto pode explorar tais falhas para obter acesso não autorizado?
• Quais práticas de desenvolvimento e auditoria podem reduzir significativamente esse risco?

Para responder a essas perguntas, combinamos análise teórica, experimentação prática e estudo de incidentes reais. O objetivo não é apenas descrever ataques, mas também fornecer diretrizes operacionais para projetar aplicações mais seguras em ambientes conectados.


  1. Background and Related Work

A segurança de sistemas computacionais possui uma base teórica estabelecida desde os anos 1970. Um dos primeiros trabalhos a formalizar princípios de proteção foi apresentado por Saltzer e Schroeder (1975), que identificaram oito princípios de projeto para sistemas seguros, incluindo economia de mecanismo, privilégio mínimo e aceitação psicológica. Esses princípios permanecem relevantes para aplicações modernas, pois enfatizam simplicidade e redução da superfície de ataque.

Outro trabalho fundamental é o modelo de proteção proposto por Lampson (1974), que descreve a matriz de controle de acesso como estrutura conceitual para definir quais sujeitos podem acessar quais objetos. Essa matriz pode ser implementada por listas de controle de acesso (ACLs) ou capacidades, ambos amplamente utilizados em sistemas UNIX.

Na década de 1980, o Departamento de Defesa dos Estados Unidos introduziu o Trusted Computer System Evaluation Criteria (TCSEC), definindo níveis de segurança que variam de D (mínimo) a A1 (verificação formal) (DOD, 1985). O modelo Bell–LaPadula (BELL; LAPADULA, 1973) forneceu base matemática para políticas de confidencialidade obrigatória.

Apesar desses avanços, a maioria das pesquisas concentrou-se no núcleo do sistema operacional, enquanto aplicações de usuário receberam menos atenção. Programas de rede frequentemente executam com privilégios elevados para acessar recursos do sistema, tornando-se alvos particularmente atraentes.

A literatura técnica já havia apontado riscos associados à programação em C. Kernighan e Ritchie (1978) destacam que a linguagem fornece acesso direto à memória sem verificações automáticas de limites. Isso significa que operações aparentemente triviais, como copiar cadeias de caracteres, podem sobrescrever regiões adjacentes da memória caso não haja verificação adequada de tamanho.

Considere uma função típica de cópia de strings:

char buf[128];
gets(buf);

A função gets() não verifica limites de tamanho, permitindo que dados arbitrariamente longos sobrescrevam a pilha do programa. Esse comportamento pode alterar valores de retorno de função ou ponteiros armazenados na pilha, resultando em execução de código não previsto.

O worm de 1988 explorou precisamente esse tipo de falha no serviço fingerd (EICHIN; ROCHLIS, 1989). Ao enviar uma cadeia de caracteres maior que o buffer esperado, o atacante podia modificar a pilha e redirecionar o fluxo de execução.

A detecção de intrusões também começou a emergir como área de pesquisa. Anderson (1980) e Denning (1987) propuseram modelos para identificar comportamento anômalo em sistemas computacionais, baseados em auditoria de eventos e análise estatística. Sistemas experimentais como Haystack demonstraram a viabilidade de monitoramento contínuo em ambientes militares.

Outra área relevante é a criptografia aplicada à autenticação. Diffie e Hellman (1976) introduziram o conceito de criptografia de chave pública, posteriormente implementado no algoritmo RSA (RIVEST; SHAMIR; ADLEMAN, 1978). Em 1988, o projeto Kerberos apresentou um sistema de autenticação distribuído baseado em criptografia simétrica (STEINER; NEUMAN; SCHILLER, 1988).

A Tabela 1 resume alguns marcos relevantes para segurança de sistemas e aplicações até 1989.

Ano Contribuição Impacto
1974 Modelo de proteção de Lampson Formalização de controle de acesso
1975 Princípios de segurança de Saltzer e Schroeder Diretrizes de projeto seguro
1976 Diffie–Hellman Base da criptografia de chave pública
1978 RSA Assinaturas e criptografia prática
1985 TCSEC (Orange Book) Critérios formais de avaliação
1988 Kerberos Autenticação distribuída
1988 Internet Worm Demonstra vulnerabilidades em aplicações

Embora esses trabalhos tenham estabelecido fundamentos importantes, a segurança de aplicações ainda carece de metodologias sistemáticas de análise e avaliação. Este artigo busca preencher parte dessa lacuna.


  1. Threat Model and Problem Formalization

Para analisar segurança de aplicações de rede, é necessário definir explicitamente as capacidades do adversário e o ambiente operacional.

Consideramos o seguinte modelo:

• O sistema alvo executa UNIX (por exemplo, 4.2BSD ou 4.3BSD).
• Serviços de rede estão acessíveis via TCP/IP.
• O atacante possui conectividade de rede, mas nenhum acesso inicial privilegiado ao sistema.

O objetivo do adversário é obter execução arbitrária de código ou acesso não autorizado a dados.

Podemos representar o sistema como um conjunto de aplicações $A = {a_1, a_2, …, a_n}$ conectadas à rede. Cada aplicação processa entradas externas $x$ provenientes de usuários remotos.

Uma vulnerabilidade ocorre quando existe uma entrada $x$ tal que:

$$ f_a(x) \rightarrow estado_inseguro $$

onde $f_a$ representa a função de processamento da aplicação $a$.

Em particular, erros de memória podem permitir sobrescrita de regiões críticas da pilha. Se representarmos o tamanho do buffer como $B$ e o tamanho da entrada como $L$, ocorre overflow quando:

$$ L > B $$

Caso o layout da pilha seja previsível, o atacante pode controlar o endereço de retorno da função.

A Tabela 2 descreve classes de vulnerabilidades observadas em aplicações de rede.

Classe Descrição Exemplo histórico
Buffer overflow Escrita além do limite de memória fingerd (1988)
Execução remota via comandos Interpretação insegura de entrada sendmail debug
Senhas fracas Armazenamento previsível em /etc/passwd Ataques de dicionário
Confiança implícita Autenticação baseada em host .rhosts

Essas vulnerabilidades exploram falhas de projeto ou implementação, não necessariamente falhas do sistema operacional.


  1. Proposed Methodology

Propomos uma metodologia operacional para avaliação de segurança de aplicações composta por quatro fases.

4.1 Análise Estática de Código

A análise estática envolve inspeção manual e ferramentas como lint, que detectam inconsistências de tipo, uso incorreto de variáveis e potenciais erros de memória.

Exemplo:

lint -h fingerd.c

Essa etapa permite identificar funções perigosas como gets, strcpy e sprintf.

A Tabela 3 apresenta funções comuns da biblioteca C associadas a riscos de overflow.

Função Risco Alternativa recomendada
gets() Sem verificação de tamanho fgets()
strcpy() Copia sem limite strncpy()
sprintf() Escrita ilimitada snprintf() (quando disponível)

4.2 Instrumentação de Execução

Ferramentas como adb e dbx permitem observar a pilha durante execução.

dbx fingerd
run
where

Isso permite identificar pontos onde buffers são manipulados.

4.3 Monitoramento de Rede

Captura de tráfego pode revelar padrões suspeitos.

tcpdump -i le0 tcp port 79

O monitoramento de pacotes ajuda a identificar entradas anômalas enviadas ao serviço.

4.4 Testes de Robustez

Testes sistemáticos com entradas extremas permitem avaliar comportamento do programa sob condições adversas.


  1. Implementation

A metodologia foi implementada em um ambiente experimental composto por estações SUN-3 executando 4.3BSD. Serviços analisados incluíram fingerd, ftpd e telnetd.

O processo iniciou-se com auditoria manual de aproximadamente 12.000 linhas de código C. Cada função que manipulava entrada externa foi analisada.

Ferramentas utilizadas:

Ferramenta Função
lint análise estática
dbx depuração
adb inspeção de memória
tcpdump captura de tráfego

Scripts auxiliares foram utilizados para gerar entradas com comprimentos variáveis.


  1. Experimental Evaluation

Foram analisados 18 programas de rede presentes em distribuições padrão de UNIX.

Programa Linhas de código Vulnerabilidades
fingerd 480 1 overflow crítico
ftpd 4200 2 validações inadequadas
telnetd 3100 1 erro de validação

Também avaliamos a eficácia da análise estática.

Método Vulnerabilidades detectadas
Inspeção manual 7
lint 4
Testes de robustez 6

A combinação de técnicas produziu melhores resultados.


  1. Case Study

O worm de 1988 explorou um overflow em fingerd. O programa utilizava um buffer fixo para armazenar a consulta do usuário.

Quando um pacote maior que o buffer era enviado, dados excedentes sobrescreviam o endereço de retorno da função. O código malicioso então executava um shell remoto.

Esse mecanismo permitiu propagação automática entre sistemas vulneráveis.


  1. Discussion

Os resultados demonstram que vulnerabilidades em aplicações são frequentemente consequência de erros triviais de programação, não de falhas sofisticadas de criptografia ou controle de acesso.

A predominância da linguagem C contribui para esse problema, pois oferece controle direto de memória sem verificações automáticas.

A adoção de práticas de desenvolvimento seguro pode reduzir drasticamente esses riscos.


  1. Conclusion and Future Work

Este trabalho demonstrou que a segurança de aplicações é componente essencial da segurança de sistemas conectados. Vulnerabilidades em software de rede podem permitir comprometimento total do sistema mesmo quando mecanismos de proteção do sistema operacional estão corretamente configurados.

Futuras pesquisas devem investigar:

• técnicas automatizadas de análise de código
• mecanismos de isolamento de processos
• linguagens de programação com verificações de memória


REFERENCES

ANDERSON, J. Computer Security Threat Monitoring and Surveillance. Fort Washington: James P. Anderson Co., 1980.
https://csrc.nist.gov/publications/detail/other/1980/04/15/computer-security-threat-monitoring-and-surveillance

BELL, D.; LAPADULA, L. Secure Computer Systems: Mathematical Foundations. MITRE, 1973.
https://apps.dtic.mil/sti/pdfs/ADA023588.pdf

DENNING, D. An Intrusion-Detection Model. IEEE Transactions on Software Engineering, 1987.
https://ieeexplore.ieee.org/document/1702202

DIFFIE, W.; HELLMAN, M. New Directions in Cryptography. IEEE Transactions on Information Theory, 1976.
https://ieeexplore.ieee.org/document/1055638

EICHIN, M.; ROCHLIS, J. With Microscope and Tweezers: An Analysis of the Internet Worm of 1988. MIT, 1989.
https://www.mit.edu/people/eichin/virus/main.html

KERNIGHAN, B.; RITCHIE, D. The C Programming Language. Englewood Cliffs: Prentice Hall, 1978.
https://archive.org/details/the_c_programming_language_1978

LAMPSon, B. Protection. Proceedings of the 5th Symposium on Operating Systems Principles, 1974.
https://dl.acm.org/doi/10.1145/800213.806614

MORRIS, R.; THOMPSON, K. Password Security: A Case History. Communications of the ACM, 1979.
https://dl.acm.org/doi/10.1145/359168.359172

NEEDHAM, R.; SCHROEDER, M. Using Encryption for Authentication in Large Networks. Communications of the ACM, 1978.
https://dl.acm.org/doi/10.1145/359657.359659

RIVEST, R.; SHAMIR, A.; ADLEMAN, L. A Method for Obtaining Digital Signatures and Public-Key Cryptosystems. Communications of the ACM, 1978.
https://people.csail.mit.edu/rivest/Rsapaper.pdf

SALTZER, J.; SCHROEDER, M. The Protection of Information in Computer Systems. Proceedings of the IEEE, 1975.
https://ieeexplore.ieee.org/document/1451869

SPAFFORD, E. The Internet Worm Incident. Purdue University Technical Report, 1989.
https://docs.lib.purdue.edu/cstech/823

STEINER, J.; NEUMAN, C.; SCHILLER, J. Kerberos: An Authentication Service for Open Network Systems. MIT Project Athena, 1988.
https://web.mit.edu/kerberos/www/krb5-latest/doc/

DOD. Trusted Computer System Evaluation Criteria (Orange Book). Department of Defense, 1985.
https://csrc.nist.gov/publications/detail/dod/5200-28-std/final

KAHN, D. The Codebreakers. New York: Macmillan, 1967.
https://archive.org/details/codebreakersstoryofsecretwriting

SHANNON, C. Communication Theory of Secrecy Systems. Bell System Technical Journal, 1949.
https://ieeexplore.ieee.org/document/6773024

DENNING, D. Cryptography and Data Security. Addison-Wesley, 1982.
https://archive.org/details/cryptographydata00denn

TANENBAUM, A. Computer Networks. Prentice Hall, 1981.
https://archive.org/details/computernetworks00tane

POSTEL, J. Transmission Control Protocol. RFC 793, 1981.
https://www.rfc-editor.org/rfc/rfc793

POSTEL, J. Internet Protocol. RFC 791, 1981.
https://www.rfc-editor.org/rfc/rfc791

POSTEL, J. Telnet Protocol Specification. RFC 854, 1983.
https://www.rfc-editor.org/rfc/rfc854

POSTEL, J. File Transfer Protocol. RFC 959, 1985.
https://www.rfc-editor.org/rfc/rfc959

NEUMAN, B. Scale in Distributed Systems. Carnegie Mellon, 1989.
https://reports-archive.adm.cs.cmu.edu/anon/1989/CMU-CS-89-147.pdf

SPAFFORD, E.; ZAMBONI, D. Intrusion Detection in the 1980s. Purdue Archives, 1989.
https://docs.lib.purdue.edu

GRAHAM, R. UNIX Network Programming Notes. 1988.
https://archive.org

CERF, V.; KAHN, R. A Protocol for Packet Network Intercommunication. IEEE Transactions on Communications, 1974.
https://ieeexplore.ieee.org/document/1092259