Em novembro de 2022, a Agência de Segurança Nacional dos EUA (NSA, na sigla em inglês) emitiu um boletim sobre a segurança do manuseio de RAM. Se você observar outros boletins da NSA sobre o assunto, notará que eles se concentram principalmente na criptografia de dados ou na proteção do loop de produção e em outras questões organizacionais. Abordar os desenvolvedores de software diretamente é um movimento bastante incomum para a agência. Mas, considerando que foi feito, é porque claramente trata-se de um tema particularmente importante. De forma geral, a NSA está sugerindo fortemente aos desenvolvedores de software que mudem para linguagens de programação cuja arquitetura implique maior segurança ao trabalhar com memória. E, de fato, parem de usar C e C++. Caso contrário, é recomendável que um conjunto de medidas seja implementado para testar os softwares quanto a vulnerabilidades e evitar sua exploração.
Para os programadores, essas são coisas bastante óbvias, e o alerta da NSA não é dirigido a eles, mas sim às gerências ou aos representantes comerciais. Foi elaborado em linguagem didática para as empresas. Vamos tentar analisar os argumentos apresentados sem ser muito técnicos.
Segurança da memória
Vamos abrir nosso último relatório sobre a evolução das ameaças para o terceiro trimestre de 2022 e dar uma olhada nas vulnerabilidades mais usadas em ciberataques. Na primeira linha ainda está a vulnerabilidade CVE-2018-0802 no componente Equation Editor do Microsoft Office, descoberta em 2018. É causada pelo processamento incorreto de dados na RAM, como resultado da abertura de um documento malicioso do Microsoft Word levar ao lançamento de código arbitrário. Outra vulnerabilidade popular entre os criminosos é a CVE-2022-2294 no componente WebRTC do navegador Google Chrome. Isso leva à execução de código arbitrário como resultado de um erro de estouro de buffer. Outra vulnerabilidade – CVE-2022-2624 – contida na ferramenta de visualização de PDF do Chrome, também pode levar ao estouro do buffer.
Obviamente, nem todas as vulnerabilidades de software são causadas pelo uso inseguro da RAM, mas muitas delas são. O NSA Bulletin cita as estatísticas da Microsoft de que os erros de manipulação de memória causam 70% das vulnerabilidades descobertas.
Por que isso acontece? Se a questão dos vazamentos de memória é tão séria, por que não podemos de alguma forma “parar” de escrever código vulnerável? A raiz do problema é o uso das linguagens de programação C e C++. Sua arquitetura dá aos desenvolvedores muita liberdade para trabalhar com RAM. Mas junto com a liberdade vem a responsabilidade. Os programadores de C/C++ precisam implementar mecanismos para a escrita e leitura segura de dados. Ao mesmo tempo, linguagens de programação de alto nível como C#, Rust, Go e outras já cuidam disso. O ponto é que, ao compilar o código-fonte do programa, os meios de manipulação segura da memória são introduzidos automaticamente e os desenvolvedores não precisam perder tempo com isso. Rust usa ainda mais meios para melhorar a segurança, até restringir a compilação de códigos potencialmente perigosos, enquanto exibe um erro para o programador.
É claro que simplesmente desistir de usar C/C++ não é viável enquanto essas linguagens permanecerem indispensáveis para certas tarefas, como quando o código é necessário para MCUs ou outros dispositivos com sérias limitações de poder de computação e tamanho de memória. Outras coisas sendo iguais, linguagens de programação de alto nível podem levar à criação de programas com uso intensivo de recursos. Mas as estatísticas de ameaças comuns nos mostram que os ataques visam com mais frequência software de usuário comum (como navegadores e editores de texto), que são executados em computadores muito poderosos (em comparação com MCUs, é claro).
Você não pode simplesmente mudar a linguagem de programação
A NSA está bem ciente disso. Um enorme banco de dados de software escrito em linguagens de programação “inseguras” não pode ser transferido para outra linguagem da noite para o dia. Mesmo se estivermos falando sobre escrever um produto de software do zero, pode haver uma equipe estabelecida, infraestrutura e métodos de desenvolvimento em torno de uma linguagem de programação específica.
Se você quiser uma analogia, imagine ser convidado a sair de sua casa só porque ela foi construída há muito tempo. Você sabe que a estrutura está perfeitamente sólida, e que só iria desabar com um grande terremoto e, além disso, você está acostumado a morar lá. A equipe de desenvolvedores do Google Chrome tem uma postagem que afirma explicitamente que eles não podem agora mudar para outra linguagem de programação (neste caso, Rust) na qual a segurança está incorporada à arquitetura. Pode ser possível no futuro. Mas, por agora, eles precisam de outras soluções.
A mesma publicação dos desenvolvedores do Google Chrome também explica os motivos pelos quais você não pode alterar fundamentalmente a segurança do código C/C++. Essas linguagens de programação simplesmente não foram projetadas para resolver todos os problemas de compilação de uma só vez. É por isso que o boletim da NSA menciona dois conjuntos de medidas como alternativa:
- Teste de código para possíveis vulnerabilidades com técnicas de análise dinâmica e estática;
- Uso de recursos que impedem a exploração de um erro de código, mesmo que já exista.
Desafios de transição
Os especialistas técnicos concordam, de um modo geral, com a opinião da NSA. Os especialistas podem ter opiniões variadas sobre como exatamente podemos mudar para linguagens de programação de alto nível nos casos em que a necessidade surge, entre outras coisas, de requisitos de segurança. Em primeiro lugar, é importante entender que, se tal movimento ocorrer, levará muitos anos. Em segundo lugar, uma evolução como essa tem um preço – nem todas as empresas estão dispostas a pagar. O problema do manuseio inseguro de memória em linguagens de programação com baixo nível de abstração é um problema sistêmico. Chamar por uma solução radical é necessário, mas não espere que todos mudem amanhã para desenvolver em C#, Go, Java, Ruby, Rust ou Swift. Assim como você dificilmente poderia fazer uma cidade ou país inteiro mudar para se adequar a, por exemplo, o veganismo ou alguma outra mudança extrema da noite para o dia.
Por fim, o problema do manuseio inseguro da memória pode ser enorme, mas está longe de ser o único problema relacionado à segurança do software. Nas várias décadas de existência da indústria de TI, nunca foi possível criar um sistema universal e completamente seguro para todas as tarefas (exceto soluções altamente especializadas). Do ponto de vista empresarial, faz sentido investir tanto em novas tecnologias (desenvolvendo competências correspondentes e contratando especialistas com experiência) como na proteção máxima das tecnologias existentes. Para desenvolvimento de software, podem ser novas linguagens de programação e tecnologias para testar o código existente. Para qualquer outro negócio, podemos falar em investir em novas tecnologias para proteção contra ciberataques, bem como testar constantemente a força da infraestrutura existente. Em outras palavras, uma abordagem abrangente de segurança é ideal e assim permanecerá por muito tempo.