Além do C

Ecossistema F5 | 07 de fevereiro de 2023

Por décadas, C e seus descendentes diretos têm sido as linguagens de programação preferidas para a programação de sistemas. No início da década de 1970, quando C foi desenvolvida, ela representou um avanço importante em relação à linguagem assembly. Cinquenta anos depois, podemos fazer melhor.

A segurança da computação não estava no radar da maioria das pessoas em 1970, nem por muitos anos depois disso. A primeira grande vulnerabilidade de segurança na internet surgiu muitos anos mais tarde, em 1988. Ela ficou conhecida como o worm da internet e explorava um estouro de buffer, no qual um array na memória era acessado por meio de um índice fora de seus limites.

Na família de linguagens C, que inclui C++, os limites dos arrays não são verificados. Cabe ao programador garantir que o array seja acessado corretamente. Por isso, erros de estouro de buffer são comuns. Pior ainda, é fácil provocar deliberadamente um estouro de buffer e, assim, acessar áreas da memória às quais não se deveria ter acesso.

O estouro de buffer é apenas um exemplo de insegurança de memória. Outros exemplos relacionados incluem aritmética de ponteiros e ponteiros pendentes (também conhecidos como falhas de uso após liberação). Hoje, temos muitas linguagens de programação que empregam diversas técnicas para garantir que qualquer programa escrito nessas linguagens esteja livre de problemas de segurança de memória. A família de linguagens C não oferece essa garantia; a segurança de memória nunca foi um objetivo de projeto dessas linguagens.

Cerca de 70% das vulnerabilidades de segurança são causadas por violações da segurança de memória. Essa afirmação é respaldada por uma quantidade esmagadora de dados. A segurança de memória é responsável por:

  • 67% das vulnerabilidades exploradas, divulgadas e detectadas em ambientes reais (de acordo com a estimativa do Google Project Zero 2021).
  • 90% das vulnerabilidades do Android (segundo o Google). Embora esse número tenha diminuído recentemente devido ao uso de Rust, 89% das vulnerabilidades exploráveis remotamente ainda estão relacionadas à segurança de memória.
  • 70% das vulnerabilidades da Microsoft (segundo a Microsoft).
  • A maioria das correções recentes de vulnerabilidades da Apple (no Catalina, Big Sur, Monterey, Safari, iOS, tvOS, watchOS).

Em julho de 2022, 5/6 das vulnerabilidades corrigidas no Chrome 103.0.5060.134 eram problemas de segurança de memória. Claramente, eliminar falhas de segurança de memória seria extremamente útil. Há muitos anos, o setor sabe como fazer isso: usar linguagens de programação com segurança de memória. Historicamente, o problema sempre foi o custo associado em termos de desempenho. Devido à importância da segurança de memória, novas estratégias vêm sendo desenvolvidas para alcançá-la sem a sobrecarga tradicional. Hoje, sabemos como eliminar erros de segurança de memória com pouco ou nenhum custo em tempo de execução. Linguagens como Rust usam inovações no design de sistemas de tipos para garantir a segurança de memória sem a necessidade de um suporte oneroso em tempo de execução.

Isso leva a uma conclusão inevitável: pare de escrever novos códigos de sistema em C/C++ (ou, de modo mais geral, em linguagens que não oferecem segurança de memória).

Este não é um apelo para reescrever de forma indiscriminada e em larga escala o código existente. Substituir software existente é caro e não está isento de riscos. No entanto, o setor precisa parar de agravar o problema adicionando mais código sem segurança de memória às bases de código existentes. No caso do código existente, deve-se priorizar a reescrita dos componentes mais sensíveis: aqueles responsáveis por validar ou processar entradas de usuários não confiáveis, aqueles executados em um contexto privilegiado, aqueles executados fora de uma sandbox etc.

Essa posição, embora amplamente aceita, ainda é controversa para alguns. A seguir, apresentamos alguns dos argumentos mais comuns em favor da manutenção do status quo e nossas respostas a eles.

  • Bugs não são exclusivos das linguagens de programação.
    • A maioria das vulnerabilidades resulta de falhas de segurança de memória. Linguagens com segurança de memória, como Rust, não estão sujeitas a esse tipo de falha. Portanto, usar uma linguagem com segurança de memória evitará que a maioria das vulnerabilidades seja criada desde o início.
  • As revisões de código detectarão bugs.
    • Estudos mostram que, embora as revisões de código possam trazer melhorias, elas muitas vezes deixam passar diversos problemas; certamente não detectam tudo.
  • Módulos inseguros tornam toda a questão irrelevante.
    • O código inseguro é explicitamente delimitado em seções muito pequenas do código, permitindo que os recursos sejam concentrados em sua validação.
  • A implementação de uma linguagem com segurança de memória pode conter bugs.
    • De fato, mas as probabilidades são muito menores. Os compiladores são relativamente pequenos e rigorosamente testados. Além disso, corrigir um compilador corrigirá automaticamente todos os programas compilados com ele, ao contrário de corrigir um bug em um único programa.
  • Somente programadores iniciantes ou incompetentes cometem esses erros.
    • Pelo contrário, os dados acima foram extraídos de grandes projetos de sistemas, como o navegador Chrome e os sistemas operacionais Windows e macOS. Esses projetos contam com alguns dos desenvolvedores mais competentes e experientes do setor e, ainda assim, continuam apresentando problemas de segurança de memória.
  • Esses problemas podem ser evitados seguindo as práticas recomendadas.
    • Veja acima. As equipes mencionadas seguem práticas muito rigorosas e utilizam as melhores ferramentas disponíveis.
  • É inviável reescrever todo o código.
    • Ninguém está defendendo uma reescrita completa de todo o código. Em vez disso, recomenda-se uma abordagem que priorize os principais elementos (privilégios elevados, ampla superfície de ataque e elementos essenciais para as garantias de segurança), além da escrita de novos códigos em uma linguagem com segurança de memória.
  • O desempenho é inadequado.
    • O desempenho do Rust é praticamente equivalente ao de C/C++. Pequenas diferenças não justificam os riscos de segurança. Também há situações em que programas em Rust podem ser mais rápidos.
  • Linguagens de programação de sistemas com segurança de memória, como Rust, são recentes demais.
  • Existem outras soluções, como análise estática, fuzzing e sandboxing.

Consulte Quantificação da insegurança de memória e das reações a ela para uma discussão detalhada dos pontos acima.

Apesar das objeções, o apoio às mudanças necessárias está crescendo. Por exemplo, grandes investimentos estão sendo feitos na Open Source Software Security Foundation (apoiada pela Linux Foundation). A segurança de memória tem sido discutida em relatórios do Senado dos EUA e pela NSA. A Consumer Reports também busca identificar os diversos incentivos que poderiam acelerar esse movimento, oferecendo uma série de recomendações para empresas e órgãos estaduais.

Em resumo:

A importância da computação para a sociedade cresceu enormemente nos últimos cinquenta anos. O cenário de ameaças à nossa infraestrutura computacional também mudou radicalmente nas últimas décadas. No entanto, as linguagens de programação que usamos para desenvolver nossos sistemas computacionais não evoluíram na mesma proporção. A falta de segurança de memória é, isoladamente, a maior fonte de vulnerabilidades de segurança em software. Isso não é uma particularidade de nenhum tipo específico de software: onde quer que linguagens sem segurança de memória sejam usadas, os problemas relacionados à segurança de memória são abundantes. E, em termos quantitativos, nenhuma outra classe de vulnerabilidade chega perto.

Agora temos os meios para enfrentar esse problema crescente, e é fundamental que nós, como setor, façamos isso. Felizmente, o reconhecimento dessa situação está se disseminando, mas o problema é urgente e não há tempo a perder.

Compartilhar

Sobre o autor

Publicações relacionadas no blog

O estado da maturidade digital empresarial: a transformação digital ainda não terminou
Ecossistema F5 | 31/07/2024

O estado da maturidade digital empresarial: a transformação digital ainda não terminou

Explore como a IA impacta as empresas, as aplicações da IA generativa, as estratégias para modernizar as operações de TI e os benefícios da maturidade digital com a F5.

Como a IA generativa acelera a transformação digital
Ecossistema F5 | 26/03/2024

Como a IA generativa acelera a transformação digital

Veja como a IA generativa impulsiona a transformação digital nas empresas, acelerando tendências como a integração de APIs, os desafios dos modelos operacionais de TI híbrida e a adoção de AIOps.

Seis capacidades técnicas para acelerar a transformação digital
Ecossistema F5 | 05/01/2023

Seis capacidades técnicas para acelerar a transformação digital

As arquiteturas empresariais atuais carecem dos fatores necessários de agilidade, escalabilidade, segurança e observabilidade, essenciais para impulsionar a mudança tecnológica. No entanto, estas seis capacidades fundamentais ajudarão as empresas a gerenciar riscos e desafios ao longo de sua transformação digital.

Inverter a API é a transformação digital de que as empresas precisam para participar e competir em uma economia de APIs
Ecossistema F5 | 18/10/2022

Inverter a API é a transformação digital de que as empresas precisam para participar e competir em uma economia de APIs

As organizações detêm um valor latente — na forma de APIs internas — que precisam explorar para competir em uma economia de APIs. Embora os desafios técnicos e de segurança possam desestimular algumas delas, as empresas precisam reconhecer que inverter suas APIs permitirá liberar o valor da organização como plataforma.

A modernização da TI começa pela infraestrutura
Ecossistema F5 | 08/09/2022

A modernização da TI começa pela infraestrutura

O hardware e o software evoluíram rapidamente desde os primórdios da internet, mas, para aproveitar ao máximo os benefícios resultantes dessa evolução, as organizações precisam avaliar e modernizar sua infraestrutura e a entrega de aplicativos. Acelere os esforços de modernização com a nova F5 rSeries.