Aikido

As 10 Principais Vulnerabilidades de Segurança em Python que Desenvolvedores Devem Evitar

Ruben CamerlynckRuben Camerlynck
|
#
#

Principais Vulnerabilidades de Segurança em Python

Nos pipelines de desenvolvimento acelerados de hoje, código Python inseguro pode introduzir riscos sérios. Python é amado por sua simplicidade, mas essa mesma flexibilidade pode se tornar perigosa se as práticas de codificação segura forem negligenciadas. De armadilhas de injeção de código a bibliotecas de terceiros vulneráveis, mesmo um pequeno descuido pode abrir a porta para atacantes. Estudos recentes mostram milhões de credenciais e chaves de API vazadas acidentalmente em código – um lembrete claro de que a segurança não pode ser uma reflexão tardia. Neste artigo, vamos detalhar algumas das principais vulnerabilidades de segurança em nível de linguagem Python (além de problemas de frameworks web), ilustrar seu impacto com exemplos reais (incluindo CVEs em bibliotecas populares) e oferecer dicas para mitigar cada risco. Também destacaremos como a integração de ferramentas de segurança (como SAST, varredura de segredos e verificações de dependência da Aikido) no início do seu fluxo de trabalho pode ajudar a detectar esses problemas antes que causem estragos.

As 10 Principais Vulnerabilidades de Segurança em Python

Abaixo estão dez das vulnerabilidades de segurança mais comuns e perigosas em aplicações Python. Para cada uma, explicamos como a vulnerabilidade surge, o impacto potencial e como corrigi-la ou preveni-la – com um destaque especial para como as ferramentas de segurança modernas podem ajudar.

1. Execução de Código Arbitrário via eval() e exec()

O `eval` do Python eval() (e seu primo exec()`exec`) permite a execução dinâmica de código Python a partir de strings. Usado de forma imprudente, eval o `eval` pode transformar um script simples em uma bomba-relógio. Se um invasor puder influenciar a string passada para eval()`eval`, ele pode executar qualquer código que desejar – desde imprimir dados até excluir arquivos ou pior. Como um desenvolvedor colocou, “O problema com eval `eval` é que ele corre o risco de permitir que invasores criem entradas maliciosas... que enganam seu programa para executar código prejudicial”. Em outras palavras, uma chamada a `eval` eval(user_input) pode funcionar hoje com entradas seguras, mas uma entrada habilmente elaborada amanhã (como __import__('os').system('rm -rf \/')`__import__('os').system('rm -rf \/')`) poderia limpar seu servidor.

Impacto: . A execução de código arbitrário é tão grave quanto parece – significa um comprometimento completo da aplicação. Invasores podem roubar dados, modificá-los ou assumir o controle do host. Este não é um caso de borda teórico: violações reais ocorreram devido ao uso inseguro de `eval`. evalMesmo que seu uso de eval `eval` seja “seguo” hoje (por exemplo, apenas avaliando expressões matemáticas), ele cria uma vulnerabilidade latente que futuras alterações podem acidentalmente acionar.

Mitigação: Nunca use `eval` ou `exec` em entradas não confiáveis. Na verdade, evite-os completamente, a menos que seja absolutamente necessário. Python oferece alternativas mais seguras para a maioria dos casos de uso (por exemplo, use avaliação literal via ast.literal_eval `ast.literal_eval` para ler estruturas de dados, ou tabelas de despacho para chamar funções em vez de construir uma string para eval). Sempre valide ou sanitize entradas rigorosamente se a execução dinâmica for necessária.

Destaque da Aikido Security: Uma boa ferramenta de análise estática (SAST) pode detectar o uso de funções perigosas. A varredura de código da Aikido, por exemplo, pode sinalizar instâncias de eval() ou exec() em seu código. Isso ajuda a identificar caminhos de código arriscados durante a revisão de código ou CI – antes antes que cheguem à produção. Ao integrar essa varredura em seu pipeline, você será alertado sempre que um novo uso de eval surgir, para que possa ser refatorado ou examinado imediatamente.

2. Injeção de Comando de SO via subprocess ou os.system

Avançando no tema de injeção de código, outra armadilha crítica é a injeção de comando de SO. Isso ocorre quando um programa Python passa entrada do usuário para comandos de shell do sistema sem a sanitização adequada. Funções como os.system(), subprocess.run() (com shell=True), ou até mesmo o uso de backticks/popen podem executar comandos de shell. Se dados controlados pelo usuário forem concatenados nesses comandos, um invasor pode injetar comandos maliciosos. Por exemplo:

# Vulnerable snippet:filename = input("Enter the filename to delete: ")os.system(f"rm -f {filename}")

Um invasor poderia inserir file.txt; shutdown -h now e de repente nosso script inocente executa rm -f file.txt; shutdown -h now. Em um incidente real, invasores exploraram uma vulnerabilidade do MLflow que resultou da passagem de dados não sanitizados para uma chamada de os.system dentro de uma função de previsão. Como observam os pesquisadores de segurança da Snyk, a injeção de comando permite a execução não autorizada de comandos, levando a violações de dados, comprometimento do sistema e outras atividades maliciosas.

Impacto: A injeção de comando de SO pode ser devastadora. Invasores podem encadear comandos para roubar arquivos sensíveis (por exemplo, ler configurações de aplicação ou credenciais), criar contas de usuário backdoor ou aprofundar-se na rede. Como esses comandos são executados com os mesmos privilégios do seu processo Python, o impacto pode variar desde o despejo de um banco de dados até a tomada completa do servidor. Violações possibilitadas por injeções de comando frequentemente resultam em graves danos financeiros e de reputação.

Mitigação: Nunca concatene diretamente a entrada do usuário em comandos de shell. Se precisar chamar programas externos, use as APIs mais seguras: o módulo do Python subprocess permite passar argumentos como uma lista (o que evita invocar um shell real). Por exemplo, use subprocess.run(["rm", "-f", filename]) em vez de os.system("rm -f " + filename). Se o uso de subprocess com shell=True for inevitável, garanta que a entrada seja estritamente validada ou sanitizada (por exemplo, permita apenas nomes de arquivo alfanuméricos esperados). Além disso, considere usar bibliotecas de alto nível para tarefas de OS (por exemplo, use o tratamento de arquivos do Python em vez de rm para excluir um arquivo).

Destaque da Aikido Security: A análise estática de código do Aikido inclui regras para detectar padrões de injeção de comando. Ele o alertará se vir algo como os.system(user_input) ou subprocess.Popen(..., shell=True) com entrada variável. Na prática, isso significa que seu pipeline de CI pode falhar uma build se um uso perigoso for introduzido. Ao detectar isso durante o desenvolvimento, você evita aquele momento de “ops” em que um trecho de depuração esquecido ou uma chamada de shell rápida e suja se torna uma porta aberta para atacantes.

3. Secrets Hardcoded no Código

Hardcodar Secrets – como chaves de API, credenciais, tokens ou chaves privadas – no código-fonte é uma prática difundida e perigosa. É fácil de fazer (“apenas coloque a chave AWS aqui por enquanto…”), mas difícil de desfazer, já que os Secrets podem permanecer no histórico de commits mesmo após a remoção. Secrets expostos são uma mina de ouro para atacantes. De fato, os vazamentos de Secrets explodiram recentemente: em 2022, uma análise de repositórios públicos do GitHub encontrou 10 milhões de Secrets expostos em apenas 1 ano (um aumento de 67% em relação ao ano anterior). Isso não é cometido apenas por desenvolvedores juniores – acontece em todos os níveis. Uma vez vazados, os Secrets foram usados em grandes violações (por exemplo, um atacante usou credenciais de administrador hardcoded no código para violar os sistemas internos da Uber).

Impacto: Se um atacante encontrar um Secret (em um repositório público, um backup vazado, uma imagem Docker, etc.), ele pode frequentemente pivotar diretamente para seus sistemas. Imagine uma senha de banco de dados hardcoded – se vazada, um atacante poderia fazer login em seu banco de dados e extrair dados do usuário. Chaves de API Cloud hardcoded são ainda piores: provedores Cloud relatam que credenciais expostas são tipicamente exploradas em minutos após a descoberta por bots que escaneiam repositórios. O raio de explosão pode incluir comprometimento total do ambiente Cloud, contas Cloud pesadas para mineradores de criptomoedas ou acesso não autorizado a serviços sensíveis. Secrets são verdadeiramente “as chaves do reino”, então vazá-los é como deixar sua porta da frente destrancada para ladrões.

Mitigação: Nunca comite Secrets reais no código. Use arquivos de configuração, variáveis de ambiente ou serviços de gerenciamento de Secrets (como HashiCorp Vault, AWS Secrets Manager, etc.) para injetar Secrets em tempo de execução. Se você precisar incluir uma credencial padrão ou de exemplo no código, certifique-se de que seja um placeholder de não produção. Conduza varreduras regulares de Secrets em sua base de código e histórico; se um Secret escapar, rotacione-o imediatamente (ou seja, invalide-o e substitua-o) e purgue o commit, se possível. Empregue o princípio do menor privilégio – mesmo que um Secret vaze, um token somente leitura é menos prejudicial do que uma chave de administrador completa.

Destaque da Aikido Security: É aqui que as ferramentas de detecção de Secrets brilham. A varredura de Secrets da Aikido (inspirada em GitGuardian e outros) buscará automaticamente padrões como chaves de API, credenciais, certificados e muito mais em seus repositórios. Ela pode alertá-lo no momento em que um desenvolvedor comete acidentalmente um Secret. Integrar uma ferramenta como essa em seu CI/CD (ou até mesmo em pre-commit hooks) significa que uma chave AWS hardcoded é sinalizada antes de chegar ao GitHub. A plataforma da Aikido ainda oferece remediação automatizada – por exemplo, revogando a credencial exposta e orientando o desenvolvedor a usar um método de armazenamento seguro.

4. Desserialização Insegura (Abuso de Pickle)

O módulo pickle do Python oferece uma maneira de serializar e desserializar objetos complexos. No entanto, o pickle é notoriamente inseguro por design. Desserializar dados de uma fonte não confiável pode executar código arbitrário durante o processo de desserialização. A própria documentação do Python é cristalina sobre isso: “O módulo pickle não se destina a ser seguro contra dados maliciosos. Nunca desserialize dados recebidos de uma fonte não confiável ou não autenticada. Na prática, isso significa que se um atacante puder alimentar sua aplicação com um pickle (por exemplo, um cookie forjado ou um objeto em cache), ele poderá executar qualquer código Python em seu servidor – essencialmente uma vulnerabilidade de RCE (Execução Remota de Código) pré-autenticação.

Exemplo do mundo real: Um desenvolvedor pode usar pickle.loads() em dados recebidos por uma rede (talvez pensando que é apenas uma maneira conveniente de transmitir objetos Python). Atacantes podem criar um payload de pickle que, quando desserializado, executa comandos do sistema. Pesquisadores de segurança demonstraram exploits triviais onde a desserialização de um objeto aparentemente inócuo aciona um reverse shell para o atacante. Em um caso, um exploit de 15 linhas usando pickle foi suficiente para gerar um shell, porque a aplicação confiava cegamente nos dados de pickle pela rede.

Impacto: A desserialização insegura é uma questão crítica – tipicamente levando à execução remota de código completa. Como o pickle pode invocar qualquer classe e método durante o carregamento, um atacante pode abusá-lo para realizar ações como excluir arquivos, instalar malware ou pivotar para outros serviços internos. Ao contrário de algumas vulnerabilidades que “apenas” vazam dados, isso concede controle direto ao atacante. O impacto é limitado apenas pelas permissões da aplicação em execução (e frequentemente aplicações Python são executadas com muitos privilégios).

Mitigação: Não use pickle (ou serialização similar como marshal) em dados de fontes não confiáveis. Se você precisa trocar dados entre sistemas, use formatos seguros como JSON ou XML – e mesmo assim, seja cauteloso (valide as entradas). Para casos de uso específicos de Python (compartilhamento de objetos), considere jsonpickle em modo seguro ou outros serializadores mais seguros, mas sempre assuma que a entrada pode ser hostil. Se você absolutamente precisa aceitar dados serializados com pickle (por exemplo, para compatibilidade), trate-os como código: exija autenticação, use assinaturas digitais para garantir que venham de uma fonte confiável, ou execute a desserialização em um sandbox com privilégios restritos. O conselho mais simples é geralmente o melhor: evite a desserialização dinâmica de entrada do usuário por completo.

Destaque da Aikido Security: Scanners de código modernos podem detectar o uso de APIs perigosas como pickle.loads ou pickle.load em dados potencialmente externos. O motor SAST da Aikido, por exemplo, possui verificações para desserialização insegura – ele sabe que qualquer invocação de pickle é um sinal de alerta, a menos que se prove o contrário. Ele destacará esses pontos durante as revisões de código. Além disso, o scanner de dependências da Aikido rastreia CVEs de desserialização conhecidas. Por exemplo, algumas bibliotecas (ou frameworks) tiveram falhas de desserialização (não apenas pickle – até mesmo coisas como XML ou YAML, que abordaremos a seguir). A Aikido irá alertá-lo se você estiver usando uma versão vulnerável de tal biblioteca e sugerir atualizações ou patches.

5. Carregamento Inseguro de YAML (Vulnerabilidade PyYAML)

Problemas de serialização não se limitam ao pickle. YAML, um formato de dados amigável para humanos, também pode causar problemas se usado de forma insegura. A popular biblioteca PyYAML tinha uma falha bem conhecida: usar yaml.load() em entrada não confiável poderia executar objetos Python arbitrários. Na verdade, o load() do PyYAML era basicamente tão poderoso quanto o pickle. CVE-2017-18342 foi atribuído a este problema – "No PyYAML antes da versão 5.1, a API yaml.load() poderia executar código arbitrário se usada com dados não confiáveis." A correção foi introduzir uma função safe_load e fazer com que load() seja o padrão para o modo seguro em versões mais recentes. Mas muitas aplicações ainda podem, inadvertidamente, usar o antigo yaml.load (ou uma versão mais antiga do PyYAML), pensando que estão apenas analisando uma configuração, quando na realidade um atacante poderia criar um YAML que executa código.

Impacto: Similar ao pickle, o impacto é a execução remota de código. Por exemplo, um arquivo YAML pode incorporar um objeto Python de um tipo que, ao ser construído, executa uma chamada de sistema. Atacantes que exploram isso podem fazer com que sua aplicação execute comandos do sistema operacional no momento em que tenta analisar um YAML malicioso. Isso pode ser explorado através de qualquer funcionalidade que analise YAML fornecido pelo usuário (cenários comuns incluem importadores de configuração, templating Kubernetes em CI/CD, ou aplicações web que aceitam entrada YAML). O CVE acima foi marcado como Crítico (CVSS 9.8) precisamente pela facilidade com que poderia ser acionado e pela gravidade do resultado.

Mitigação: Sempre use carregamento seguro métodos para formatos de dados. No PyYAML, use yaml.safe_load() for any content that is not fully trusted. This mode only parses basic YAML types (strings, ints, lists, dicts) and will refuse to instantiate custom objects. If you are on PyYAML < 5.1, upgrade the library – the old load() é totalmente inseguro. Da mesma forma, tenha cuidado com outros formatos de serialização: use json.loads (JSON não possui execução de código por design, o que é bom), ou se estiver usando similar a pickle alternativas, certifique-se de que elas tenham um modo seguro. Uma ideia de defesa em profundidade: execute a análise em um ambiente de baixo privilégio ou sandbox, se possível (assim, mesmo que o código seja executado, ele não poderá causar muitos danos).

Destaque da Aikido Security: análise de dependências is key here. Aikido’s dependency analyzer would flag that you have PyYAML <5.1 in your requirements, warning you of CVE-2017-18342 and advising an upgrade. On the code side, Aikido’s SAST can also catch usage of yaml.load(...) e sugira o uso de safe_load em vez disso. Trata-se de identificar o problema em dois níveis: certificar-se de que você está usando uma versão segura da biblioteca e garantir que está chamando as funções seguras. Ao integrar essas verificações, você seria notificado durante o desenvolvimento de que “epa, esta chamada de parsing YAML é insegura” com orientações para corrigi-la.

6. Directory Traversal via Operações de Arquivo Inseguras (Extração de Tarfile)

O tratamento de arquivos é comum em Python (por exemplo, descompactar arquivos enviados por usuários). Mas operações de arquivo ingênuas podem introduzir vulnerabilidades de path traversal. Um exemplo proeminente é o módulo embutido do Python tarfile . Foi revelado que, por mais de 15 anos, tarfile.extractall() era vulnerável a um ataque de path traversal (apelidado de “vulnerabilidade de 15 anos” quando redescoberta). Se um arquivo tar malicioso contiver entradas de arquivo com ../ em seus nomes, extractall escreveria alegremente arquivos fora do diretório pretendido, potencialmente sobrescrevendo arquivos críticos do sistema. Isso é rastreado como CVE-2007-4559. Embora seja uma CVE antiga, permanece sem correção na biblioteca padrão do Python até o momento, e pesquisas em 2022 mostraram centenas de milhares de repositórios ainda estão utilizando tarfile de forma vulnerável.

Um atacante poderia fazer upload ou fornecer um arquivo tar especialmente elaborado de modo que, quando seu código o extrair, ele insere um payload (por exemplo, um web shell ou uma configuração sobrescrita) em um local ao qual o atacante não deveria ter acesso. Em uma demonstração, pesquisadores exploraram isso para obter execução de código sobrescrevendo o próprio código de um pacote Python após a extração.

Não são apenas arquivos tar – problemas semelhantes podem ocorrer com arquivos zip (vulnerabilidade zip slip) ou qualquer operação de arquivo onde você constrói caminhos a partir de entrada externa. Sem as verificações adequadas, uma entrada de arquivo nomeada ../../../../../etc/passwd escreverá em /etc/passwd na extração.

Impacto: A travessia de diretórios (path traversal) pode levar a escrita arbitrária de arquivos (ou leitura, em alguns casos) no servidor. Escrever arquivos no local errado pode escalar para execução de código – por exemplo, sobrescrevendo a configuração de um aplicativo para apontar para código controlado pelo atacante, ou soltando um binário Trojan no PATH. Mesmo que não leve imediatamente a RCE, sobrescrever arquivos críticos pode sabotar a integridade do sistema ou facilitar ataques posteriores. Considere as consequências de um atacante sobrescrever o arquivo .env da sua aplicação ou um script que é executado – eles poderiam inserir comandos maliciosos. No caso da CVE-2007-4559, a comunidade aumentou sua gravidade quando foi demonstrado que a execução de código é frequentemente uma consequência direta da exploração da sobrescrita de arquivos.

Mitigação: Nunca extraia arquivos de fontes não confiáveis sem validação. Para tarfile, use tarfile.extractall(path, members=...) e filtre manualmente os membros. Você pode implementar uma verificação para garantir que o caminho de nenhum membro esteja fora do diretório de destino (por exemplo, resolvendo caminhos absolutos e verificando padrões de travessia). A documentação do Python agora inclui um trecho de código para fazer isso com segurança – essencialmente rejeitando qualquer arquivo com .. ou prefixos de unidade. Alternativamente, considere usar bibliotecas de terceiros que realizam extração segura. Para arquivos zip, inspecione nomes de forma semelhante antes de escrever, ou use bibliotecas que mitigam o zip slip. Sempre com o mínimo privilégio: se possível, execute a extração em um sandbox ou em um diretório com permissões limitadas. Dessa forma, mesmo que um exploit tente escapar, ele não poderá atingir arquivos críticos do sistema.

Destaque da Aikido Security: A análise estática do Aikido pode detectar padrões perigosos como tarfile.extractall() o uso sem filtragem segura de membros. Ele conhece a CVE-2007-4559 e pode sinalizar instâncias em seu código onde você chama extractall ou extract sem precauções. Isso serve como um lembrete para implementar as verificações adequadas. Além disso, o feed de inteligência de vulnerabilidades do Aikido (sua pesquisa interna) rastreia esses problemas “ocultos” tanto em bibliotecas padrão quanto em pacotes populares. Ao escanear seu código e dependências, ele emitirá um aviso como “Potencial travessia de diretórios no uso de tarfile – considere validar o conteúdo do arquivo”, com um link para orientações de melhores práticas. Em resumo, ele ajuda os desenvolvedores a detectar um bug de 15 anos que, de outra forma, poderia passar despercebido em seu código.

7. Usando Bibliotecas Desatualizadas com Vulnerabilidades Conhecidas (Requests, urllib3, etc.)

O rico ecossistema de pacotes do Python é uma de suas forças – mas cada dependência que você inclui também pode introduzir vulnerabilidades se não for mantida atualizada. Bibliotecas Python de alto perfil tiveram sua parcela de CVEs. Por exemplo, a amplamente utilizada biblioteca HTTP Requests teve bugs como:

  • CVE-2023-32681 – onde o Requests vazaria credenciais de Proxy HTTP em certos cenários de redirecionamento, enviando Proxy-Authorization cabeçalhos para servidores de destino e potencialmente expondo dados sensíveis informações. (Isso foi corrigido no Requests 2.31.0.)
  • CVE-2024-35195 – uma falha lógica onde, se a verificação de certificado SSL fosse desabilitada uma vez em uma Sessão, o Requests ignoraria persistentemente a verificação para requisições subsequentes ao mesmo host, mesmo que se tentasse reativá-la. Essencialmente, uma vez quebrado, sempre quebrado – uma surpresa desagradável que poderia deixar as conexões inseguras silenciosamente. Corrigido na versão 2.32.0.
  • Injeção de CRLF no urllib3 – o urllib3 (usado pelo Requests internamente) tinha uma vulnerabilidade que permitia a injeção de CRLF em cabeçalhos HTTP se um atacante controlasse parte da URL ou método da requisição (por exemplo, caracteres de nova linha poderiam ser inseridos em um cabeçalho). Isso poderia ser abusado para contrabandear cabeçalhos ou dividir respostas, potencialmente levando a sequestro de sessão ou manipulação de caches web. (Múltiplos CVEs, por exemplo, CVE-2019-9740 para o urllib embutido do Python, foram atribuídos a tais problemas.)

Estes são apenas alguns exemplos. Outros exemplos notáveis incluem vulnerabilidades em análise de URL (por exemplo, CVE-2023-24329, um problema em urllib.parse que permitia a atacantes contornar blocklists de URL usando uma URL "complicada" que começava com um espaço ou caractere de controle), e problemas em gerenciamento de pacotes ferramentas (como a vulnerabilidade passada do pip CVE-2018-20225 que permitia que um download malicioso sobrescrevesse arquivos arbitrários). Mesmo bibliotecas de dados populares (Pandas, NumPy) ocasionalmente recebem correções de segurança (frequentemente problemas de DoS ou corrupção de memória).

Impacto: Vulnerabilidades conhecidas em bibliotecas podem ter uma ampla gama de impactos – desde vazamento de informações e negação de serviço até comprometimento total – dependendo do bug. O ponto chave é que atacantes escaneiam ativamente por aplicações usando versões desatualizadas. Se você estiver executando um Requests antigo e sua aplicação fizer chamadas de rede, um atacante pode explorar o vazamento de autenticação de proxy para roubar credenciais. Ou se você tiver um urllib3 desatualizado, eles podem explorar a injeção de CRLF para envenenar suas interações HTTP. Como essas vulnerabilidades são públicas, os atacantes sabem exatamente o que procurar. Falhar em atualizar as dependências é como deixar buracos conhecidos sem correção em sua aplicação.

Mitigação: Mantenha-se atualizado sobre as atualizações de dependências e avisos de segurança. Use ferramentas para verificar CVEs conhecidos em suas dependências (pip-tools, Dependabot do GitHub, ou ferramentas SCA comerciais). Quando um novo CVE crítico é anunciado (por exemplo, um bug grave em Django, Flask, Requests, etc.), priorize a atualização para uma versão corrigida. Sempre que possível, fixe suas dependências em versões comprovadamente seguras e revise os changelogs das atualizações. Considere também fixar versões mínimas: por exemplo, exija requests>=2.31.0 se você souber que as versões mais antigas são vulneráveis. Além disso, empregue defesa em profundidade: por exemplo, mesmo que o Requests tivesse um bug de verificação de certificado, você poderia adicionar uma camada de segurança de rede (como interceptação TLS ou fixação adicional de certificado) para mitigar o risco. Mas o mais simples é: mantenha seus pacotes atualizados.

Destaque da Aikido Security: É aqui que a análise de composição de software (SCA) na Aikido entra em jogo. O scanner de dependências da Aikido verifica continuamente os requisitos do seu projeto (e até mesmo suas dependências transitivas) em relação a um banco de dados de vulnerabilidades conhecidas. Ele irá alertá-lo: “A biblioteca X versão Y é vulnerável a CVE-2023-32681”, frequentemente fornecendo detalhes e uma versão corrigida recomendada. Melhor ainda, a plataforma da Aikido pode realizar correções automatizadas – por exemplo, abrindo um pull request para atualizar uma versão. Ao integrar isso ao seu CI/CD, você garante que não está implantando contêineres ou aplicações com bibliotecas desatualizadas. Em resumo, ferramentas como Aikido ajudam você a detectar CVEs conhecidas e até mesmo remediá-las automaticamente, complementando scanners open-source com regras personalizadas e inteligência atualizada.

8. Desabilitando Recursos de Segurança (por exemplo, Ignorando a Validação de Certificado SSL)

Às vezes, durante o desenvolvimento ou testes, engenheiros desativam verificações de segurança importantes – e então o código é enviado para produção dessa forma. Um exemplo clássico em Python é fazer requisições HTTP com verificação SSL desabilitada. A biblioteca Requests (e outras como urllib3) permitem um verify=False flag para ignorar erros de certificado SSL. Isso é conveniente ao lidar com certificados autoassinados em um ambiente de desenvolvimento, mas se chegar à produção, isso expõe você a ataques man-in-the-middle (MitM). A documentação do Requests avisa explicitamente: quando verify=False, o cliente aceitará qualquer qualquer certificado – ignorando incompatibilidades de nome de host ou certificados expirados/autoassinados – tornando sua aplicação vulnerável a ataques MITM. Essencialmente, você não confirma mais que está se comunicando com o servidor real. Um atacante pode interceptar seu tráfego (especialmente se puder falsificar DNS ou estiver na mesma rede) e apresentar qualquer certificado para sequestrar a conexão.

Além da verificação SSL, outras funcionalidades desabilitadas também podem causar problemas: por exemplo, usar HTTP em vez de HTTPS para comunicação sensível, desativar manualmente a verificação de nome de host TLS ou desabilitar as redes de segurança integradas do Python (como executar o interpretador com asserções desativadas se essas asserções estivessem protegendo uma verificação crítica de segurança).

Impacto: Se um atacante conseguir se posicionar no meio do seu tráfego (o que é mais fácil do que muitos pensam, especialmente em redes Cloud ou Container, ou Wi-Fi público, etc.), ele pode descriptografar e modificar dados em trânsito quando a verificação de certificado está desativada. Isso pode significar que um atacante rouba tokens de API, injeta respostas maliciosas ou se passa por serviços. Em uma arquitetura de microsserviços, um serviço comprometido ou um ponto de apoio na rede pode permitir a movimentação lateral interceptando chamadas de um serviço para outro se essas chamadas não forem devidamente verificadas. Também vimos cenários em que desativar a verificação SSL em uma biblioteca cliente de API permitiu que atacantes servissem malware de um servidor de atualização que deveria ser confiável, simplesmente usando um certificado autoassinado em um domínio falsificado. As consequências podem ser dados roubados, tomada de conta ou injeção de dados/comandos maliciosos no funcionamento do seu aplicativo.

Mitigação: Nunca desative a verificação SSL em código de produção. Se você realmente precisar (por exemplo, conectar-se a um serviço interno com um certificado autoassinado), então pelo menos fixe o certificado ou thumbprint para não confiar cegamente em qualquer certificado. Melhor ainda, use uma CA privada e torne seus certificados internos confiáveis fornecendo o pacote de CA. Durante o desenvolvimento, se você usar verify=False, seja extremamente cauteloso para removê-lo antes de fazer o commit ou use a configuração para desativá-lo apenas em ambientes não-produtivos. As revisões de código devem tratar verify=False como um grande sinal de alerta. Além disso, considere usar ferramentas como linters para proibir este flag em código comitado. O mesmo vale para outros atalhos – por exemplo, não capture e ignore exceções de segurança, não desative autenticação ou CSRF em depuração e esqueça de reativar, etc.

Destaque da Aikido Security: Os scanners do Aikido podem detectar o uso de configurações arriscadas como verify=False em requisições. Na verdade, ele pode impor políticas (semelhante a como as políticas do Prisma/Checkov funcionam) para garantir que nenhum código esteja desativando as verificações de certificado. Se tal padrão for encontrado, o Aikido o apontará nos resultados da varredura, tratando-o como uma vulnerabilidade. Pode dizer “Verificação de certificado SSL desativada aqui – isso não deve ser usado em produção” com um link para a linha de código. Ao integrar isso na CI, você efetivamente previne o cenário de “deixei um flag de depuração ligado”. Além disso, a análise de dependências mencionada anteriormente também o alertará sobre bugs como o CVE-2024-35195, onde mesmo a desativação não intencional persiste – destacando que você precisa atualizar sua biblioteca para restaurar totalmente a segurança.

9. Pacotes Maliciosos ou Comprometidos (Ataques à Supply Chain de Software)

Nem todas as ameaças vêm de erros no seu próprio código – às vezes o código que você baixou do PyPI em si é o ataque. ataques à Supply chain por meio de pacotes Python maliciosos aumentaram nos últimos anos. Atacantes publicam pacotes com typosquatting ou totalmente falsos no PyPI, nomeando-os de forma semelhante a bibliotecas populares (por exemplo, reqeusts em vez de requests) ou nomes atraentes como free-net-vpn. Desenvolvedores desavisados os instalam, e o código malicioso é executado durante a instalação (em setup.py) ou na importação. Por exemplo, em 2022, dez pacotes PyPI maliciosos foram descobertos que personificavam bibliotecas comuns e injetavam malware de roubo de informações nos sistemas dos desenvolvedores. Um pacote, imitando um conhecido, foi projetado para buscar credenciais AWS e enviá-las a um atacante via um webhook do Discord. Outro chamado WINRPCexploit afirmava ser uma ferramenta de exploit, mas na verdade exfiltrava todas as variáveis de ambiente (muitas vezes contendo Secrets) para o atacante.

Mesmo pacotes legítimos podem ser comprometidos se um atacante obtiver acesso à conta do mantenedor (como aconteceu com o event-stream no Node.js, e também já ocorreu em Python). Houve casos em que pacotes amplamente utilizados foram brevemente sequestrados para incluir código malicioso em novas versões. Por exemplo, um pacote pode de repente começar a enviar telemetria de uso (espionagem) ou incluir um backdoor acionado sob certas condições.

Impacto: O impacto de pacotes maliciosos pode ser severo e de longo alcance. Como esses pacotes frequentemente executam código no momento da instalação (via scripts de setup) ou quando importados, eles podem fazer tudo o que seu usuário pode fazer: roubar credenciais (de arquivos de configuração, variáveis de ambiente, configuração do AWS CLI, etc.), instalar trojans, criptografar arquivos (ransomware) ou abrir reverse shells. E como eles frequentemente são executados com os privilégios do desenvolvedor, isso pode comprometer não apenas o aplicativo, mas todo o sistema ou as credenciais que o desenvolvedor possui. Em um pipeline de CI, um pacote envenenado poderia exfiltrar Secrets do seu ambiente de CI. Em um ambiente de produção, uma dependência maliciosa poderia se tornar um backdoor para atacantes explorarem continuamente. ataques à Supply chain são particularmente insidiosos porque minam a confiança nas próprias ferramentas que usamos.

Mitigação: Avalie e monitore cuidadosamente suas dependências. Algumas boas práticas: Fixe as dependências em versões específicas (para que você não puxe automaticamente uma atualização adulterada). Verifique checksums ou assinaturas de pacotes (o PyPI agora suporta assinatura GPG e similares, embora nem todos os pacotes a utilizem). Use ferramentas como pip install --no-build-isolation --only-binary=:all: para wheels conhecidas e seguras, a fim de evitar a execução de setup.py de pacotes desconhecidos. Considere empregar um proxy ou mirror local do PyPI e permita apenas pacotes verificados. Sempre leia os detalhes do pacote: se requests tem 100 milhões de downloads e de repente surge um novo reqeusts pacote – isso é suspeito. Os recursos de segurança do PyPI (como 2FA para mantenedores) estão melhorando, mas a responsabilidade também é dos usuários: não instale pacotes aleatórios sem escrutínio. Se possível, revise a fonte de novas dependências (pelo menos uma varredura rápida em busca de padrões maliciosos óbvios como os.system('curl ...')).

Destaque da Aikido Security: A plataforma Aikido aborda os riscos da Supply chain de várias maneiras. Primeiro, seu análise de dependências irá sinalizar pacotes que são conhecidos como malware ou que apresentam comportamento suspeito. Aikido ingere continuamente Threat Intelligence (indicadores de pacotes maliciosos) e pode avisá-lo, “O Pacote X é relatado como malicioso – não o utilize.” Em segundo lugar, o Aikido SafeChain (uma ferramenta de código aberto da Aikido) pode impedir a instalação de pacotes não confiáveis. Ele essencialmente bloqueia pacotes que não têm tempo de vida suficiente ou que aparecem subitamente na sua árvore de dependências, mitigando ataques de typosquatting ao exigir um período de “quarentena” (por exemplo, instalar apenas pacotes que existam há mais de 24 horas, para evitar malware recém-publicado). Ao integrar essas defesas, você adiciona um watchdog automatizado sempre que você pip install. Na prática, o Aikido ajuda a garantir que as bibliotecas das quais você depende não o estejam traindo – identificando atores maliciosos conhecidos e aplicando políticas para dificultar a entrada de novos.

10. Práticas Criptográficas Fracas (Aleatoriedade Insuficiente e Uso Inadequado de Criptografia)

Criptografia é difícil, e usá-la incorretamente pode comprometer a segurança tanto quanto um bug explícito. Em Python, um erro comum é usar o gerador de números aleatórios errado para contextos sensíveis à segurança. Por exemplo, desenvolvedores podem usar random.random() ou random.randrange() para gerar um token de redefinição de senha ou um ID de sessão. No entanto, o módulo padrão random random não é criptograficamente seguro – ele usa algoritmos previsíveis não adequados para a geração de segredos. O Python introduziu o módulo `secrets` secrets por esta razão, afirmando que secrets `secrets.SystemRandom` deve ser usado para aleatoriedade crítica de segurança em preferência ao gerador de números pseudoaleatórios padrão no módulo random random random que é projetado para modelagem e simulação, não para segurança ou criptografia. Se você usar `random` para tokens, um atacante pode ser capaz de prever valores (dadas observações suficientes ou conhecimento da seed).

Outra prática fraca é usar algoritmos desatualizados ou fracos. Por exemplo, usar MD5 ou SHA1 para hash de senhas (ambos são considerados quebrados para este propósito) ou não adicionar salt às senhas. Ou criar sua própria “criptografia” (por exemplo, um esquema XOR caseiro) em vez de usar bibliotecas comprovadas. Essas fraquezas podem não se manifestar como uma CVE em seu código, mas elas diminuem significativamente a barreira para atacantes. Um exemplo real: se as senhas são armazenadas sem salt com SHA-1, um atacante que rouba o banco de dados de hashes pode quebrar a maioria das senhas rapidamente usando tabelas rainbow pré-computadas.

Impacto: Aleatoriedade insegura pode levar a sequestro de conta ou falsificação de token. Imagine um atacante adivinhando cookies de sessão porque foram derivados de uma saída PRNG previsível – isso não é apenas teoria, já aconteceu em sistemas mal projetados. Hashing ou criptografia fraca significa que, se um atacante violar uma camada (por exemplo, obtiver acesso de leitura a um banco de dados ou interceptar tráfego criptografado), ele pode facilmente descriptografar ou quebrar os dados supostamente protegidos. No geral, criptografia fraca dá uma falsa sensação de segurança; atacantes podem não precisar de um “exploit” quando podem simplesmente forçar ou prever o que precisam.

Mitigação: Siga as atuais melhores práticas criptográficas. Use o módulo `secrets` secrets ou os.urandom() `os.urandom()` para gerar quaisquer tokens secretos, chaves ou nonces. Use bibliotecas de alto nível para criptografia (como Fernet na biblioteca cryptography `cryptography`) em vez de escrever sua própria criptografia. Para armazenamento de senhas, use KDFs estabelecidos (bcrypt, Argon2, PBKDF2 com iterações adequadas) – nunca hashes simples sem salt. Mantenha os algoritmos atualizados; por exemplo, SHA-256 é bom para integridade, mas para senhas você ainda desejaria um hash lento como bcrypt. E sempre habilite TLS para comunicação de rede, usando protocolos modernos (TLS 1.2+). Essencialmente, prefira implementações bem avaliadas em vez de abordagens personalizadas ou legadas. Além disso, esteja ciente das depreciações: se uma configuração ou cifra SSL/TLS não for mais recomendada (o módulo ssl do Python geralmente atualiza os padrões, mas esteja atento se você substituir as configurações).

Destaque da Aikido Security: O SAST do Aikido pode ajudar a identificar algumas práticas criptográficas inadequadas – por exemplo, ele pode alertar se vir o random módulo sendo usado onde secrets seria apropriado, ou se encontrar MD5 sendo usado em um contexto de segurança. Além disso, a inteligência de vulnerabilidades do Aikido o alertará se você estiver usando um algoritmo fraco conhecido em um contexto que teve CVEs anteriores (por exemplo, se uma biblioteca que você usa padronizar para um modo inseguro, o Aikido pode apontar isso). Embora a supervisão humana seja crucial em criptografia, ter uma ferramenta automatizada para verificar novamente não faz mal. É como um linter para segurança: se você cometer inadvertidamente token = random.random(), uma ferramenta pode dizer “Tem certeza? Isso não é criptograficamente seguro.” Esse tipo de feedback precoce pode direcionar os desenvolvedores para os módulos corretos (talvez até sugerindo: import Secrets e Secrets.token_hex() como alternativa). Em suma, o Aikido ajuda a impor a higiene criptográfica, capturando padrões fracos óbvios e mantendo você informado sobre vulnerabilidades relacionadas à criptografia no ecossistema.

Conclusão: Proteja Seu Código Python Desde o Início

A flexibilidade e o rico ecossistema do Python podem ser uma faca de dois gumes – poderosos nas mãos dos desenvolvedores, mas oferecendo muitas avenidas para atacantes se o devido cuidado não for tomado. Exploramos como coisas como execução dinâmica de código, vulnerabilidades de injeção, Secrets vazados, dependências desatualizadas e outras armadilhas podem minar a segurança de suas aplicações Python. A boa notícia é que cada uma dessas falhas é evitável com uma combinação de melhores práticas e as ferramentas certas:

  • Adote práticas de codificação seguras: valide as entradas, evite funções perigosas e use padrões seguros (por exemplo, loaders seguros, random seguro, algoritmos atualizados).
  • Mantenha suas dependências atualizadas e verificadas: não deixe CVEs conhecidos persistirem em seus requisitos e seja cauteloso com o que você instala.
  • Integre a segurança em seu pipeline de desenvolvimento: isso significa executar análise estática, varredura de segredos e auditorias de dependência enquanto você codifica e durante a CI, não após um incidente.

Plataformas DevSecOps modernas como Aikido podem tornar esse processo muito mais fácil, automatizando a detecção desses problemas – desde a captura de uma senha hardcoded antes que ela saia do seu laptop, até o bloqueio de um pacote vulnerável de ser implantado, e o alerta sobre uma falha recém-divulgada em uma de suas bibliotecas. Como observado no relatório de segurança de contêineres da Red Hat, quase metade das equipes perde o sono com a segurança de contêineres (e, por extensão, de software) – o mesmo provavelmente se aplica à segurança de aplicações Python. Ao shifting security left – ou seja, abordá-la cedo no desenvolvimento – você pode reduzir significativamente as chances de uma emergência noturna causada por um bug Python evitável.

Em resumo, manter-se informado e proativo é fundamental. Continue aprendendo sobre codificação segura (o Guia de Segurança Python e os recursos OWASP são ótimos), incentive revisões de código com a segurança em mente e aproveite as ferramentas automatizadas como sua rede de segurança. Desenvolvedores Python que incorporam a segurança desde o início economizarão tempo, dinheiro e reputação para suas organizações a longo prazo. Vamos escrever código que não seja apenas inteligente e limpo, mas também seguro e protegido. Seu eu futuro (e seus usuários) agradecerão por isso.

Continue lendo:
Top 9  Vulnerabilidades de segurança de contêineres Docker    
Top 7 Vulnerabilidades de segurança na nuvem    
Top 10 Vulnerabilidades de segurança de aplicações web que toda equipe deve conhecer    
Top 9 Vulnerabilidades e configurações incorretas de segurança Kubernetes    
Principais vulnerabilidades de segurança de código encontradas em aplicações modernas    Principais vulnerabilidades de segurança JavaScript em aplicações web modernas    
Top 9 Vulnerabilidades de segurança da supply chain de software explicadas

4.7/5

Proteja seu software agora

Comece Gratuitamente
Não é necessário cc
Agendar uma demonstração
Seus dados não serão compartilhados · Acesso somente leitura · Não é necessário cartão de crédito

Fique seguro agora

Proteja seu código, Cloud e runtime em um único sistema centralizado.
Encontre e corrija vulnerabilidades rapidamente de forma automática.

Não é necessário cartão de crédito | Resultados da varredura em 32 segundos.