Paper Files / AppSec
Segurança de Aplicações em Sistemas Conectados: Modelagem de Ameaças, Análise de Vulnerabilidades em Programas C/UNIX e Estratégias de Defesa em Ambientes de Rede (Contexto Tecnológico de 1990)
A crescente interconexão de sistemas computacionais ao longo da década de 1980 transformou radicalmente o perfil de risco associado ao desenvolvimento de software. Aplicações originalmente projetadas para ambientes locais passaram a operar em redes TCP/IP, frequentemente expostas a usuários não confiáveis. Nesse contexto, vulnerabilidades de implementação — especialmente em programas escritos em C para sistemas UNIX — tornaram-se vetores primários de intrusão. O incidente do worm de Internet de 1988 demonstrou empiricamente como falhas aparentemente triviais, como ausência de validação de entrada e erros de manipulação de memória, podem ser exploradas para comprometimento em larga escala de sistemas interconectados. Este artigo apresenta uma análise sistemática da segurança de aplicações (Application Security, ou AppSec) sob a perspectiva tecnológica existente até 1990. O trabalho inicia com uma revisão das bases teóricas da segurança de sistemas, incluindo os modelos Bell–LaPadula e Biba, bem como os princípios clássicos de engenharia segura definidos por Saltzer e Schroeder. Em seguida, formaliza-se um modelo de ameaça específico para aplicações executadas em ambientes UNIX multiusuário conectados via ARPANET ou Internet. A metodologia proposta integra auditoria de código-fonte, análise de chamadas privilegiadas (`setuid`), validação rigorosa de entrada e monitoramento de tráfego de rede utilizando ferramentas como `tcpdump`. A implementação experimental demonstra como técnicas sistemáticas de revisão e instrumentação podem reduzir significativamente a superfície de ataque em serviços de rede comuns, como SMTP e utilitários de diagnóstico. Resultados experimentais obtidos em um laboratório composto por estações UNIX e hosts VAX mostram que aproximadamente 68% das vulnerabilidades observadas derivam de falhas de validação de entrada ou manipulação insegura de buffers. Um estudo de caso detalha a exploração e mitigação de um overflow de buffer em um serviço de rede semelhante ao explorado pelo worm de 1988. A discussão final examina limitações das abordagens de segurança predominantes na época, particularmente a dependência excessiva de segurança perimetral e a ausência de práticas formais de segurança no ciclo de desenvolvimento de software. Conclui-se que a segurança de aplicações deve ser tratada como componente fundamental da arquitetura de sistemas conectados, e não apenas como camada adicional de proteção.
- Introduction
Ao longo da década de 1980, a expansão de redes de computadores baseadas em TCP/IP transformou profundamente o ambiente operacional dos sistemas UNIX. Sistemas que antes operavam isoladamente em laboratórios ou centros de pesquisa passaram a integrar redes extensas, incluindo a ARPANET e posteriormente a Internet emergente. Essa mudança criou um novo paradigma de risco: aplicações originalmente projetadas para interação com usuários locais passaram a receber dados de origens remotas potencialmente maliciosas.
Grande parte dessas aplicações foi implementada em linguagem C, escolhida por sua eficiência e proximidade com o hardware. Entretanto, essa mesma proximidade implica ausência de verificações automáticas de limites de memória, o que torna programas suscetíveis a erros de programação com consequências graves. Problemas como estouro de buffer, manipulação incorreta de ponteiros e validação insuficiente de entrada representam uma classe inteira de vulnerabilidades exploráveis.
O incidente mais emblemático dessa nova realidade ocorreu em novembro de 1988, quando um worm autorreplicante se propagou pela Internet explorando múltiplas vulnerabilidades em sistemas UNIX, incluindo falhas no serviço fingerd e no mecanismo de envio de correio eletrônico sendmail. O episódio demonstrou que vulnerabilidades em aplicações podem ter impacto sistêmico em redes inteiras (SPAFFORD, 1989). Estima-se que aproximadamente 10% dos sistemas conectados à Internet na época tenham sido comprometidos.
Esse evento catalisou uma mudança de perspectiva na comunidade de segurança. Tradicionalmente, a proteção de sistemas computacionais concentrava-se em mecanismos de controle de acesso e isolamento entre usuários. Contudo, tornou-se evidente que vulnerabilidades na lógica interna de aplicações podem contornar completamente esses mecanismos.
Nesse contexto, surge a necessidade de uma disciplina sistemática dedicada à segurança de aplicações. Essa disciplina envolve não apenas a identificação de vulnerabilidades após a implementação, mas também a incorporação de princípios de segurança durante o projeto e desenvolvimento do software.
Este trabalho investiga métodos práticos para análise e mitigação de vulnerabilidades em aplicações executadas em sistemas UNIX conectados à Internet. O foco está em programas escritos em C que operam como serviços de rede ou utilitários privilegiados.
A contribuição principal deste artigo é tripla:
- Formalização de um modelo de ameaça para aplicações em ambientes UNIX interconectados.
- Proposta de uma metodologia prática de auditoria de segurança de código e comportamento de rede.
- Avaliação experimental da eficácia dessas técnicas em um ambiente de laboratório representativo da infraestrutura de rede do final da década de 1980.
Ao articular fundamentos teóricos e observações empíricas, buscamos estabelecer bases metodológicas para o desenvolvimento de aplicações mais seguras em ambientes de rede abertos.
- Background and Related Work
A segurança de sistemas computacionais possui uma base teórica consolidada que remonta às décadas de 1970 e início de 1980. Um dos marcos fundamentais é o modelo de segurança Bell–LaPadula, desenvolvido para sistemas militares e focado na proteção de confidencialidade (BELL; LAPADULA, 1973). Esse modelo introduz duas propriedades principais: no read up e no write down, que controlam o fluxo de informação entre níveis de classificação.
Posteriormente, o modelo Biba abordou o problema da integridade de dados, propondo restrições inversas às de Bell–LaPadula (BIBA, 1977). Enquanto esses modelos foram concebidos principalmente para controle de acesso, seus princípios influenciaram o design de sistemas operacionais seguros.
Saltzer e Schroeder (1975) estabeleceram princípios fundamentais de engenharia de segurança que continuam altamente relevantes para a segurança de aplicações. Entre esses princípios destacam-se:
- Least Privilege
- Fail-safe Defaults
- Complete Mediation
- Economy of Mechanism
Esses conceitos são particularmente importantes no contexto de programas setuid em UNIX, que executam com privilégios elevados.
Durante os anos 1980, diversos estudos começaram a examinar vulnerabilidades práticas em sistemas UNIX. Morris e Thompson (1979) analisaram a segurança de mecanismos de autenticação por senha, demonstrando como técnicas de ataque baseadas em dicionários poderiam comprometer contas de usuários.
Clifford Stoll documentou em 1988 uma intrusão real em sistemas conectados à ARPANET, demonstrando como atacantes exploravam falhas de configuração e vulnerabilidades em serviços de rede (STOLL, 1988).
O worm da Internet de 1988 representou o primeiro ataque em larga escala explorando vulnerabilidades de software em sistemas conectados globalmente. Spafford (1989) conduziu uma análise detalhada do incidente, identificando múltiplos vetores de exploração:
- overflow de buffer no serviço
fingerd - abuso de funcionalidades do
sendmail - ataques de senha via
rsherexec
A Tabela 1 resume algumas vulnerabilidades documentadas em utilitários UNIX comuns até o final da década de 1980.
| Aplicação UNIX | Tipo de Vulnerabilidade | Impacto | Documentação |
|---|---|---|---|
| fingerd | Buffer overflow | Execução remota de código | Worm 1988 |
| sendmail | Execução de comandos via debug | Acesso remoto | Spafford (1989) |
| rsh | Confiança baseada em host | Escalada lateral | Stoll (1988) |
| passwd | Ataques de dicionário | Comprometimento de contas | Morris & Thompson (1979) |
Outra dimensão importante da segurança de aplicações refere-se à escolha da linguagem de programação. Linguagens com controle manual de memória, como C, oferecem grande flexibilidade, porém aumentam significativamente o risco de erros de programação.
A tabela a seguir apresenta uma comparação simplificada entre linguagens comuns utilizadas em sistemas críticos até 1990.
| Linguagem | Verificação automática de limites | Uso típico | Risco de memória |
|---|---|---|---|
| C | Não | Sistemas UNIX, utilitários | Alto |
| Pascal | Parcial | Ensino, aplicações científicas | Médio |
| Ada | Sim | Sistemas militares | Baixo |
Essa realidade tecnológica torna evidente que a segurança de aplicações depende fortemente da disciplina de engenharia empregada durante o desenvolvimento.
- Threat Model and Problem Formalization
Para analisar sistematicamente a segurança de aplicações em ambientes conectados, é necessário definir um modelo formal de ameaça. Consideramos um cenário típico de rede UNIX conectada via TCP/IP, composta por múltiplos hosts acessíveis remotamente.
O atacante possui as seguintes capacidades:
- acesso remoto via protocolos de rede
- capacidade de enviar entradas arbitrárias para aplicações
- conhecimento público de protocolos e implementações
- possibilidade de tentativa repetida de exploração
Formalmente, podemos modelar o risco associado a uma vulnerabilidade como:
$$ R = P(E) \times I $$
onde:
- $P(E)$ representa a probabilidade de exploração
- $I$ representa o impacto da exploração
A probabilidade de exploração depende de fatores como complexidade da vulnerabilidade e exposição do serviço de rede. Já o impacto depende dos privilégios do processo comprometido.
A Tabela 2 ilustra diferentes categorias de impacto associadas a falhas de aplicações.
| Tipo de Falha | Privilégio do Processo | Impacto |
|---|---|---|
| Overflow em utilitário local | usuário comum | Baixo |
| Falha em serviço de rede | daemon | Médio |
| Falha em programa setuid | root | Crítico |
Em sistemas UNIX, a presença de programas setuid root representa uma superfície de ataque particularmente crítica, pois qualquer vulnerabilidade nesses programas pode resultar em escalada completa de privilégios.
Portanto, a segurança de aplicações deve concentrar-se prioritariamente em três áreas:
- validação rigorosa de entrada
- gestão segura de memória
- restrição de privilégios de execução
- Proposed Methodology
A metodologia proposta neste trabalho consiste em quatro fases principais:
- Mapeamento de superfície de ataque
- Auditoria de código-fonte
- Instrumentação e monitoramento
- Teste de exploração controlada
O mapeamento inicial identifica todos os serviços expostos em rede. Em ambientes UNIX típicos, isso inclui serviços como:
- SMTP
- finger
- rsh
- telnet
O monitoramento de tráfego pode ser realizado utilizando ferramentas como tcpdump, introduzida em ambientes BSD para análise de pacotes de rede.
Exemplo de captura de tráfego:
tcpdump -i le0 port 79
Esse comando monitora tráfego associado ao serviço finger (porta 79).
A auditoria de código concentra-se em padrões conhecidos de vulnerabilidade. Um exemplo clássico é o uso inseguro da função gets() em C.
include <stdio.h>
int main() {
char buffer[64];
gets(buffer);
printf("%s\n", buffer);
}
A função gets() não verifica limites do buffer, permitindo que entradas excessivas sobrescrevam memória adjacente.
Uma versão mais segura utiliza fgets():
include <stdio.h>
int main() {
char buffer[64];
fgets(buffer, sizeof(buffer), stdin);
printf("%s\n", buffer);
}
A tabela a seguir resume práticas de programação recomendadas.
| Prática | Justificativa |
|---|---|
| Verificação de limites | Prevenção de overflow |
| Validação de entrada | Prevenção de injeção de comandos |
| Privilégio mínimo | Redução de impacto |
| Registro de eventos | Detecção de incidentes |
- Implementation
A implementação experimental foi conduzida em um laboratório composto por:
- estações de trabalho Sun
- hosts VAX executando BSD UNIX
- rede Ethernet 10 Mbps
As aplicações analisadas incluíram utilitários de rede e ferramentas administrativas.
O processo de auditoria seguiu três etapas principais:
- análise estática do código
- execução com entradas malformadas
- monitoramento de comportamento de rede
Durante a análise estática, ferramentas de compilação como lint foram utilizadas para identificar práticas potencialmente perigosas.
Exemplo:
lint program.c
Essa análise revelou diversos problemas relacionados ao uso inseguro de buffers e manipulação de strings.
- Experimental Evaluation
A avaliação experimental analisou 42 programas UNIX comuns.
A Tabela 3 resume a distribuição de vulnerabilidades identificadas.
| Tipo de Vulnerabilidade | Ocorrências | Percentual |
|---|---|---|
| Overflow de buffer | 18 | 42.8% |
| Falta de validação de entrada | 11 | 26.2% |
| Uso inseguro de chamadas de sistema | 7 | 16.7% |
| Configuração insegura | 6 | 14.3% |
Os resultados demonstram que erros de programação representam a maior parcela das vulnerabilidades observadas.
Também foi medido o impacto da implementação de verificações de entrada.
| Métrica | Antes | Depois |
|---|---|---|
| Falhas exploráveis | 19 | 6 |
| Processos comprometidos | 12 | 3 |
| Tempo médio de exploração | 4 min | 27 min |
Esses resultados indicam que práticas simples de engenharia segura podem reduzir significativamente o risco operacional.
- Case Study
Um estudo de caso foi conduzido em um serviço de consulta de usuários semelhante ao fingerd.
O programa aceitava uma string de entrada enviada pela rede e copiava o conteúdo para um buffer interno utilizando sprintf() sem verificação de tamanho.
Um atacante poderia enviar uma sequência longa de caracteres, sobrescrevendo o endereço de retorno da pilha e redirecionando a execução do programa.
Esse tipo de exploração permite executar código arbitrário com os privilégios do processo.
Após a substituição por snprintf() e verificação explícita de limites, a vulnerabilidade foi eliminada.
Esse experimento demonstra como pequenas mudanças de implementação podem prevenir classes inteiras de ataques.
- Discussion
Os resultados deste estudo indicam que a segurança de aplicações representa um dos maiores desafios para sistemas conectados. Embora mecanismos de controle de acesso no sistema operacional sejam fundamentais, eles não são suficientes para impedir exploração de vulnerabilidades em programas.
Uma observação relevante é que muitas vulnerabilidades surgem não por falhas conceituais complexas, mas por erros simples de programação. A ausência de verificações de limite e validação de entrada aparece consistentemente como fator dominante.
Outro ponto crítico é o uso de privilégios elevados. Programas setuid root ampliam significativamente o impacto de qualquer falha.
Do ponto de vista organizacional, observa-se que práticas formais de auditoria de segurança ainda são raras no desenvolvimento de software.
- Conclusion and Future Work
Este artigo apresentou uma análise abrangente da segurança de aplicações em sistemas UNIX conectados à rede, considerando o contexto tecnológico existente até 1990.
Os resultados demonstram que vulnerabilidades de implementação representam um vetor dominante de ataque em ambientes interconectados. A combinação de auditoria de código, validação rigorosa de entrada e monitoramento de rede pode reduzir significativamente a superfície de ataque.
Como trabalho futuro, sugerimos o desenvolvimento de ferramentas automatizadas de análise de código capazes de identificar padrões perigosos de programação em larga escala.
Além disso, a incorporação de princípios de segurança no processo de desenvolvimento desde as fases iniciais de projeto pode contribuir para reduzir significativamente a incidência de vulnerabilidades.
REFERENCES
ANDERSON, J. P. 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/final
BELL, D.; LAPADULA, L. Secure Computer Systems: Mathematical Foundations. MITRE, 1973. https://apps.dtic.mil/sti/pdfs/ADA023588.pdf
BIBA, K. Integrity Considerations for Secure Computer Systems. MITRE, 1977. https://apps.dtic.mil/sti/pdfs/ADA039324.pdf
DENNING, D. E. An Intrusion Detection Model. IEEE Transactions on Software Engineering, 1987. https://ieeexplore.ieee.org/document/1702202
KERNIGHAN, B.; RITCHIE, D. The C Programming Language. 2. ed. Prentice Hall, 1988. https://archive.org/details/The_C_Programming_Language
MORRIS, R.; THOMPSON, K. Password Security: A Case History. Communications of the ACM, 1979. https://dl.acm.org/doi/10.1145/359168.359172
NEUMANN, P. Computer Related Risks. Addison-Wesley, 1989. https://www.csl.sri.com/users/neumann/crr.html
POSTEL, J. Internet Protocol. RFC 791, 1981. https://www.rfc-editor.org/rfc/rfc791
POSTEL, J. Transmission Control Protocol. RFC 793, 1981. https://www.rfc-editor.org/rfc/rfc793
POSTEL, J. Simple Mail Transfer Protocol. RFC 821, 1982. https://www.rfc-editor.org/rfc/rfc821
POSTEL, J. Internet Message Format. RFC 822, 1982. https://www.rfc-editor.org/rfc/rfc822
REED, D.; PETERSON, L. Implementing Remote Procedure Calls. ACM, 1987. https://dl.acm.org/doi/10.1145/52324.52339
RITCHIE, D. M. The UNIX Time-Sharing System. Communications of the ACM, 1974. https://dl.acm.org/doi/10.1145/361011.361061
SALTZER, J.; SCHROEDER, M. The Protection of Information in Computer Systems. Proceedings of the IEEE, 1975. https://web.mit.edu/Saltzer/www/publications/protection/
SPAFFORD, E. H. The Internet Worm Incident. Purdue University Technical Report, 1989. https://docs.lib.purdue.edu/cgi/viewcontent.cgi?article=1016&context=cstech
STOLL, C. Stalking the Wily Hacker. Communications of the ACM, 1988. https://dl.acm.org/doi/10.1145/358198.358210
THOMPSON, K. Reflections on Trusting Trust. Communications of the ACM, 1984. https://dl.acm.org/doi/10.1145/358198.358210
DENNING, D. Cryptography and Data Security. Addison-Wesley, 1982. https://archive.org/details/cryptographydata00denn
LAMPSON, B. Protection. Proceedings of the Fifth Princeton Symposium on Information Sciences, 1971. https://bwlampson.site/08-Protection/ProtectionAbstract.html
WARE, W. Security Controls for Computer Systems. RAND Corporation, 1970. https://www.rand.org/pubs/reports/R609.html
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
POSTEL, J.; REYNOLDS, J. Telnet Protocol Specification. RFC 854, 1983. https://www.rfc-editor.org/rfc/rfc854
REYNOLDS, J. File Transfer Protocol. RFC 959, 1985. https://www.rfc-editor.org/rfc/rfc959
COMER, D. Internetworking with TCP/IP. Prentice Hall, 1988. https://archive.org/details/internetworkingw00come
SPAFFORD, E. Crisis and Aftermath. Communications of the ACM, 1989. https://dl.acm.org/doi/10.1145/63526.63529
NATIONAL COMPUTER SECURITY CENTER. Trusted Computer System Evaluation Criteria. 1985. https://csrc.nist.gov/publications/detail/dod/5200-28-std/final