Como implementações não seguras de gRPC podem comprometer APIs e aplicações

As empresas estão se voltando para a arquitetura de microsserviços a fim de construir aplicações voltadas para o futuro. Os microsserviços permitem que as empresas gerenciem a infraestrutura com eficiência, implantem facilmente atualizações ou melhorias e auxiliem as equipes de TI a inovar, falhar e aprender mais rápido. Eles também permitem que as empresas criem aplicações que podem ser facilmente dimensionadas de acordo com a demanda. Além disso, à medida que as empresas mudam de arquitetura — passando do monolítico tradicional para microsserviços — surge a necessidade de comunicação eficiente entre eles. Essa comunicação crítica e complexa entre aplicações de cliente e servidor pode ser tratada pelo gRPC, um framework de chamada de procedimento remoto (RPC) universal que facilita a comunicação transparente e eficiente entre os sistemas conectados. Embora bastante novo (tendo sido desenvolvido pelo Google  apenas em 2015), ele ganhou popularidade e adoção rapidamente.

Neste artigo, discutiremos as armadilhas de segurança que os desenvolvedores podem enfrentar ao mudar para o gRPC e implementá-lo em seus projetos. Como as APIs gRPC seguras desempenham um papel fundamental na segurança geral da aplicação, oferecemos recomendações sobre como proteger as implementações gRPC de ameaças e reduzir os riscos.

 

O que é gRPC?

O gRPC pode ser usado para projetar novos protocolos que exigem precisão, eficiência e independência de idioma, pois oferece suporte a vários idiomas para servidores e clientes. É um projeto de Cloud Native Computing (CNCF) e foi adotado por grandes empresas, como o popular site de streaming de vídeo Netflix, a empresa de serviços financeiros Square e a empresa de Platform as a Service (PaaS) Docker.

O gRPC é comparado a outros frameworks RPC, como SOAP e REST. Embora as APIs RESTful sejam amplamente utilizadas e normalmente usem HTTP para trocar informações entre aplicações ou serviços e o formato de dados JavaScript Object Notation (JSON), elas têm limitações de desempenho e orientação baseada em texto.

Muitas organizações migraram suas APIs de REST para gRPC com o intuito de aproveitar as vantagens do protocolo binário do gRPC, que é mais adequado para comunicações entre serviços. O gRPC usa o HTTP/2, um protocolo baseado em binário, como uma camada inferior por padrão. O HTTP/2 oferece suporte a vários fluxos e solicitações em uma conexão TCP, ao contrário de seu predecessor, HTTP/1.0, que foi projetado para ter um esquema de “solicitação única, resposta única”. O pipelining HTTP solucionou esse problema em HTTP/1.1; no entanto, o HTTP 2.0 ainda tem mais desempenho e suporte.

 

Figura 1. Uma visualização de como o HTTP/1.0 difere do HTTP/2 quando se trata de solicitações e respostas

O gRPC é construído sobre buffers de protocolo (ou protobuf), o mecanismo de plataforma e linguagem neutra do Google para serializar dados estruturados. A serialização é um processo de conversão de objetos na memória em um fluxo de bytes que pode ser facilmente salvo em um arquivo ou transmitido pela rede para outras aplicações. Os desenvolvedores descrevem a interface de dados uma vez e, em seguida, compilam-na usando um compilador de buffer de protocolo para um idioma escolhido. No caso do gRPC, os buffers de protocolo também são utilizados para definir a interface RPC.

Figura 2. Uma ilustração de como a estrutura gRPC funciona em uma aplicação de varejo online que tem o produto e os serviços de pagamento interagindo por meio de APIs

Figura 3. Um exemplo de demonstração gRPC “HelloWorld” enviando uma mensagem de string

Crédito da imagem: gRPC Quick Start

Potenciais Ameaças e Riscos para gRPC

Vulnerabilidades

O gRPC oferece suporte a várias linguagens de programação. Existem dois tipos de implementações usadas nas linguagens suportadas: a) implementação usando a própria linguagem e b) wrappers em torno do código escrito gRPC C-core. Esses wrappers permitem a tradução de chamadas escritas em diferentes idiomas suportados em chamadas C. Embora as implementações da linguagem C geralmente tenham um bom desempenho, há uma chance maior de que um desenvolvedor introduza uma vulnerabilidade no sistema, pois é necessário implementar mais funcionalidades junto com recursos de gerenciamento de memória. Por outro lado, o uso de linguagens como Java ou Go, que já possuem muitas funcionalidades implementadas e também cuidam das questões de gerenciamento de memória, reduz as chances de um desenvolvedor introduzir bugs de alto impacto no sistema. Notavelmente, a importância de escolher os idiomas adequados pode desempenhar um papel significativo em manter os sistemas mais seguros.

* É possível ter uma implementação puramente C# ou um wrapper C# em torno de C

** Implementação puramente JavaScript, bem como ligações ao gRPC C-core (usando um complemento C++)

 

Canais de transmissão de dados inseguros e credenciais de canal

É altamente provável que, durante uma chamada de procedimento remoto, os dados sejam transferidos para o servidor de destino. É por isso que os desenvolvedores devem priorizar a criação de canais seguros para transmissão de dados. Isso não apenas evita vazamentos de dados, mas também limita os ataques Man-in-the-Middle (MiTM), pois invasores habilidosos podem vazar dados de serviço ou injetar dados maliciosos na conexão que irão interferir no servidor.

Um vazamento de dados pode revelar detalhes de implementação sobre seu serviço ou infraestrutura que podem permitir outros ataques e até mesmo levar ao comprometimento do serviço ou infraestrutura. Aqui está um exemplo de captura de pacote de uma chamada gRPC insegura:

Figura 4. Um exemplo de captura de pacote de uma chamada gRPC não segura

O gRPC oferece suporte a TLS em todo o protocolo HTTP/2 subjacente, bem como em vários mecanismos de autenticação. É responsabilidade do desenvolvedor escolher uma implementação segura. Copiar e colar padrões com palavras-chave como “InsecureChannelCredentials” deve ser evitado por motivos óbvios.

Realizamos uma pesquisa de código no Github.com para a palavra-chave “InsecureChannelCredentials” junto com uma limitação de linguagem C++ (que é comum no uso de gRPC). A pesquisa gerou mais de 11.000 resultados de código. Acreditamos que o número significativo de ocorrências de pesquisa está associado a demos e exemplos. No entanto, ainda existem alguns projetos que os utilizam.

Figura 5. Resultados da pesquisa de código “InsecureChannelCredentials”

 

Questões de implementação de procedimento

Da mesma forma, para funções do AWS Lambda, a maior superfície de vulnerabilidades está oculta dentro da implementação real do procedimento remoto. Como o gRPC oferece suporte a vários idiomas, sugerimos que os desenvolvedores novatos usem linguagens de memória segura para evitar bugs de gerenciamento de memória de alto impacto, como overflow do buffer ou bugs de uso após livre (UaF) que levam à execução remota de código (RCE).

Entretanto, o uso de linguagens seguras para a memória ainda não será capaz de mitigar os bugs lógicos que podem aparecer no código. Para isso, os desenvolvedores devem definir um alto padrão para processos de desenvolvimento, seguir consistentemente as práticas recomendadas de desenvolvimento de software seguro e implementar controles proativos usando as recomendações dos 10 principais Controles Proativos do OWASP nas Práticas de Codificação Segura OWASP.

Ter um mecanismo de autenticação centralizado para partes críticas do sistema é altamente recomendado, mesmo dentro de redes isoladas ou nuvens privadas. No caso de configurações incorretas, a exploração da vulnerabilidade dentro do ambiente pode servir como um ponto de entrada para acesso não autorizado que pode interferir significativamente com o serviço gRPC.

Também sugerimos não codificar ou comprometer detalhes de autenticação gRPC para sistemas de gerenciamento de cadeia de suprimentos (SCM), especialmente aqueles voltados ao público. Assim como qualquer outra informação de credencial, essas devem ser armazenadas em um local seguro e acessadas somente quando necessário. Aqui está um exemplo de vazamento de credencial gRPC que encontramos apenas pesquisando no GitHub:

Figura 6. Um exemplo de credenciais de serviço gRPC encontradas no GitHub

 

Ataques de negação de serviço

Por último, gostaríamos de discutir nossas descobertas de ataques de negação de serviço (DoS). O gRPC pode servir como um serviço de mensagens “oculto” dentro de um ambiente isolado, bem como uma substituição de API para serviços de API REST voltados ao público usando o formato JSON.

Gostaríamos de alertar os usuários do C/C++ gRPC sobre um bug já conhecido, mas ainda não corrigido, que nega efetivamente as chamadas de serviço até que o serviço seja reiniciado. O bug é acionado quando um número maior de conexões é aberto em um curto período de tempo. Na verdade, isso se deve à limitação do número de descritores de arquivo abertos em sistemas Linux.

Figura 7. Um exemplo de ataque DoS dentro de uma implementação C/C++ de uma biblioteca gRPC

Com base em nossa pesquisa, o bug é acionado quando as conexões de soquete são abertas em um curto período de tempo e mesmo após o soquete aberto ter sido fechado. Testamos essa implementação em outras linguagens que não são agrupadas em C, como Java e Go, e descobrimos que elas não são afetadas por esse problema.

Propomos as seguintes soluções alternativas para ajudar a mitigar o risco de ataques DoS, caso a mudança de uma plataforma para outra não seja uma opção:

  •         Aumente o limite dos descritores de arquivo executando “sudo ulimit -n increasedNumber”.
  •         Use um balanceador de carga externo e service watchdogs para reduzir a carga de uma única instância e ficar de olho no status do serviço.

Recomendações de segurança para gRPC

Como o número de empresas usando a estrutura gRPC continua a aumentar devido à confiabilidade e escalabilidade dos serviços, deve haver uma consciência mais ampla de como o protocolo deve ser mantido protegido contra riscos e ameaças.

Embora o gRPC permita a comunicação eficiente entre os sistemas, deve-se enfatizar que é responsabilidade do desenvolvedor garantir que as comunicações entre esses sistemas sejam mantidas seguras. O gRPC tem um guia abrangente sobre os mecanismos de autenticação compatíveis que funcionarão com o protocolo, como SSL/TLS com ou sem autenticação baseada em tokens do Google, que os desenvolvedores devem seguir. Os desenvolvedores também têm a opção de conectar seu próprio sistema de autenticação por meio da API do plug-in Credentials.

Os desenvolvedores também devem usar soluções de segurança que validem o conteúdo, garantindo que nenhum payload malicioso seja capaz de se infiltrar no sistema através das mensagens que são transferidas do cliente para o servidor e vice-versa.

Soluções que irão garantir que dados críticos sejam mantidos seguros em trânsito, ficar de olho no status de um serviço e impor autenticação e autorização para manter os dados seguros também serão vitais para as empresas.

A estrutura gRPC é uma ferramenta eficaz para desenvolvedores e empresas criarem APIs, aplicações e microsserviços. Mas, como seus antecessores, também não é imune a riscos e ameaças — portanto, a necessidade de soluções, verificações e controles de segurança deve ser destacada.

 

Soluções Trend Micro

A plataforma de serviços de segurança Trend Micro Cloud One™, que faz parte Trend Micro™ Hybrid Cloud Security, permite que os desenvolvedores de software criem e executem aplicações à sua maneira. Ele tem controles de segurança que funcionam em toda a infraestrutura existente ou fluxos de código modernos, conjuntos de ferramentas de desenvolvimento e requisitos multiplataforma.

O Application Security, que é oferecido pela Cloud One, fornece detalhes completos de diagnóstico sobre vulnerabilidades de código e proteção de tempo de execução contra ataques automatizados e as ameaças mais comuns, como injeção de SQL e RCE. Ele também oferece cobertura e relatórios completos de cada instância de ataque, bem como informações sobre a identidade de um invasor e metodologia de ataque.

A Cloud One também oferece as seguintes tecnologias de segurança em nuvem para ajudar ainda mais os desenvolvedores a identificar e resolver problemas de segurança mais cedo e melhorar o tempo de entrega para as equipes de DevOps:

  •       Workload Security: proteção de tempo de execução para workloads
  •       Container Security: varredura automatizada de imagem de contêiner e de registro 
  •       File Storage Security: segurança para serviços de armazenamento de arquivos e objetos em nuvem
  •       Network Security: segurança IPS da camada de rede em nuvem
  •       Conformity: segurança em tempo real para infraestrutura em nuvem — proteja, otimize, cumpra