Como o Runtime Radar Ajuda a Detectar Ataques à Cadeia de Suprimentos: O Caso LiteLLM
Este artigo explora como a ferramenta de segurança Runtime Radar da Positive Technologies pode detectar ataques à cadeia de suprimentos, usando o recente comprometimento da biblioteca LiteLLM como estudo de caso. Ele detalha as etapas da exploração, desde a execução de scripts maliciosos até o movimento lateral em um ambiente Kubernetes, e demonstra como o Runtime Radar identifica atividades suspeitas, como a leitura de arquivos confidenciais e a exfiltração de dados.
MundiX News·12 de maio de 2026·8 min de leitura·👁 5 views
Como o Runtime Radar Ajuda a Detectar Ataques à Cadeia de Suprimentos: O Caso LiteLLM
Olá a todos! Sou Sergey Zyukin, desenvolvedor de expertise do runtime-radar, um produto de código aberto que garante a segurança do ambiente de tempo de execução de contêineres. Preparei um artigo para você, no qual contarei como é possível detectar um infostealer embutido na biblioteca LiteLLM como resultado de seu recente comprometimento. Além disso, é claro, também consideraremos a movimentação lateral dentro da infraestrutura Kubernetes, que ocorre se o script do infostealer for executado em um pod com privilégios suficientes.
Não conseguimos resistir e verificamos o que o Runtime Radar pode detectar ao implementar tal ataque. Mas, primeiro, vamos por partes.
Visão geral do ataque
Como muitos pesquisadores já analisaram em detalhes tanto o ataque em si quanto os antecedentes, não vou me aprofundar nisso e me limitarei a uma breve visão geral para facilitar a compreensão do contexto da detecção.
Se decompusermos o ataque em etapas, o seguinte acontece:
Ao iniciar, litellm_init.pth decodifica a carga útil (um script Python comum) de Base64 e a executa.
O primeiro script executa o infostealer e envia os dados coletados para o servidor C2 do invasor.
O infostealer coleta dados confidenciais e, se possível, se fixa por meio de um serviço systemd, deixando um backdoor para controle remoto.
Se o infostealer, durante a operação, encontrar um token de acesso Kubernetes, ele o usa para iniciar um contêiner malicioso em cada nó disponível do cluster.
O pod em si, por sua vez, é criado com acesso máximo ao sistema operacional do nó (privileged, hostPID, hostNetwork) e com o diretório raiz do nó do cluster montado, no qual foi executado.
Ao iniciar, ele se fixa no nó usando um backdoor e um serviço systemd.
O infostealer é implementado com base no princípio da matrioska - consiste em vários scripts Python ofuscados em Base64 e executados sequencialmente.
Portanto, dividi o trabalho de detecção em duas etapas:
Na fase de lançamento do script infostealer.
Na fase de movimentação no cluster Kubernetes.
Para cada etapa, demonstrarei os resultados do trabalho de expertise da versão atual do Runtime Radar e também darei algumas recomendações sobre como procurar ameaças usando nossa ferramenta de código aberto. Vamos lá.
Características de inicialização em um ambiente de teste e demonstração do script
Descreverei algumas nuances da execução do script, caso alguém queira repetir e estudar de forma independente os resultados do trabalho do Runtime Radar.
Creio que vale a pena mencionar que tudo o que está descrito abaixo deve ser feito apenas em um ambiente de teste isolado.
Simplifiquei um pouco o processo de reprodução (que o leitor me perdoe) e executei o primeiro script manualmente. Acredito que isso, em geral, não afeta nada, pois o mais interessante ainda acontece nos outros dois scripts.
E também fiz pequenas alterações em diferentes partes da matrioska de script - principalmente para minha própria conveniência e segurança:
Substituí o endpoint de conexão para enviar o arquivo final pelo meu interno;
Alterei o endpoint para receber comandos no script backdoor;
Modifiquei um pouco os comandos para fixar o backdoor no nó do cluster Kubernetes.
Para iniciar, usei python3.11 normal com módulos "prontos para uso", sem qualquer configuração adicional.
Para que o script possa se mover no Kubernetes, ele precisa de direitos para criar pods no cluster atual, então preparei uma conta de serviço com os direitos necessários e executei um pod em seu nome.
Se você quiser repetir, pode usar os seguintes manifestos:
Quanto aos parâmetros do próprio Runtime Radar, usei a versão que está atualmente disponível no GitHub sem quaisquer modificações ou atualizações adicionais de expertise. Assim, todos podem se certificar de forma independente dos resultados do trabalho.
Configurando políticas de coleta no Runtime Radar
Agora você pode iniciar e ver como tudo está pegando fogo verificar o funcionamento do script.
Abaixo estão algumas capturas de tela demonstrando os resultados de uma exploração bem-sucedida.
Pod que concluiu o trabalho no namespace kube-system, que foi iniciado pelo script e iniciou a fixação no nível do nó do cluster
Diretórios (/root/.config/sysmon e /root/.config/systemd) criados para fixar o backdoor
Vemos que a fuga do contêiner para o nó do cluster Kubernetes foi realizada.
Conexões ao meu endpoint da web, iniciadas pelo infostealer para enviar dados
Vamos agora ver o que nossa ferramenta detectou.
Detecção na fase de lançamento do infostealer
Após o lançamento, o infostealer começa a pesquisar e coletar muitos dados confidenciais diferentes, e o faz com ousadia e em voz alta.
Nossos detectores de atividade anômala demonstram isso perfeitamente: é possível observar vários disparos, sinalizando o lançamento suspeito do shell de comando (CS_RT_SUSP_SHELL) e a leitura de dados (CS_RT_SUSP_FILE_READ), o lançamento de conexões a vários endpoints (CS_RT_HACK_TOOLS_EXT, CS_RT_DOWNLOAD_TOOLS), vários lançamentos de env, whoami.
Leitura de arquivos confidenciais pelo script de coleta
Lançamento do shell de comando com comandos para pesquisar dados confidenciais, coleta de dados sobre o ambiente
O que vale a pena prestar atenção ao procurar ameaças e investigar incidentes semelhantes ao caso de comprometimento do LiteLLM. Como sempre, a atenção aos detalhes é a melhor amiga de qualquer especialista em busca de ameaças. Não é o fato de lançar o shell de comando que é alarmante, mas COMO isso acontece. Vemos:
Várias tentativas de lançamento em um curto período de tempo;
Um pai de processo suspeito do shell de comando.
Os filtros nos ajudarão a selecionar o detector necessário e ver toda a atividade como um todo. Como confirmação do fato de ilegitimidade, são usados argumentos preenchidos com vários comandos e modelos para pesquisar dados confidenciais.
Nos parâmetros do filtro, incluiremos a exibição de eventos nos quais ameaças foram detectadas (Events with threats only), especificaremos o detector CS_RT_SUSP_SHELL e aplicaremos as alterações.
Configurando o filtro para pesquisar eventos
O detector CS_RT_SUSP_SHELL rastreia o pai do processo do shell de comando, pois, neste caso, o processo pai é /usr/bin/python3, ele destaca essa atividade como uma ameaça.
Página de eventos da seleção anterior (disponível clicando no evento), onde você pode ver claramente o arquivo executável do processo pai
Há poucos aplicativos legítimos que usam Python para iniciar o shell de comando, e quando isso acontece várias vezes seguidas em um ambiente de produção, vale a pena ficar alarmado.
Também podemos estudar o comportamento do processo pai e ver quais ações suspeitas foram detectadas durante sua inicialização. Deixe-me lembrá-lo de que, em nossa matrioska, esse pai será o segundo script Python.
Vamos pegar qualquer evento da seleção anterior e, no menu de contexto, selecionar Parent context.
Pesquisando eventos relacionados ao processo pai do evento selecionado
Para exibir eventos, você precisa remover a filtragem por um detector específico.
Redefinindo a filtragem por um detector específico
É aqui que as coisas ficam interessantes: vemos os disparos de nossos detectores, relacionados ao acesso do processo pai a arquivos confidenciais (função security_file_permission). Observe que, para isso, o script não iniciou nenhum processo filho - isso foi feito durante a operação do código.
É nesses casos que nossa telemetria baseada em eBPF ajuda, o que permite rastrear o acesso a arquivos em um nível inferior, evitando a substituição e o rastreamento de chamadas de sistema específicas.
Entre os arquivos lidos, vemos o arquivo com hashes de senha de contas Linux (/etc/shadow) e o token da conta Kubernetes (aquela que criamos especialmente com direitos elevados para que a movimentação no cluster funcionasse).
Vamos agora ver o que aconteceu depois disso. Deixe-me lembrá-lo de que o script principal de nossa matrioska (aquele que é executado primeiro) ainda deve enviar dados para um servidor C2 externo. Para visualizar esses eventos, usaremos outro filtro de contexto - selecionaremos o parâmetro Same process.
Pesquisando eventos com o mesmo processo que o evento selecionado
Vemos os detectores disparados, que indicam a criação e exfiltração do arquivo de dados coletados.
Além disso, os eventos também contêm um dos indicadores de comprometimento (IoC) mais importantes - o endereço e a porta do servidor C2 final.
Como resultado, o Runtime Radar conseguiu detectar:
Pesquisa e coleta de dados confidenciais,
Exfiltração dos dados recebidos,
Endereço do servidor C2 do invasor.
Parece que já descobrimos passos suficientes aqui. Agora vamos para a etapa de movimentação no cluster Kubernetes e fuga do contêiner.
Detecção na fase de movimentação no cluster Kubernetes
Então, para se fixar no nó do cluster, o script inicia um pod no namespace kube-system, que monta o diretório raiz do nó e se fixa no nível do serviço systemd. Os parâmetros de coleta de eventos no Runtime Radar foram configurados para monitoramento parcial do kube-system, portanto, os eventos podem ser obtidos usando um filtro simples. Na captura de tela abaixo, vemos como, usando o Runtime Radar, filtramos eventos por namespace kube-system, também para melhor legibilidade, deixamos apenas eventos do tipo exec, excluindo eventos de conclusão do processo e kprobe.
Filtragem de eventos de segurança da informação na interface do produto
Os filtros nos ajudam a ver uma sequência clara de comandos executados no contêiner para implementar a fuga e a fixação no nó do cluster usando o serviço systemd. Além disso, o Runtime Radar nos permite entender que os comandos foram executados em um pod com o máximo de recursos (CAP_SYS_ADMIN). O CS_RT_BASE64_DECODE_RUN foi acionado a partir dos detectores, que detecta o uso de ferramentas para descriptografar a sequência Base64.
Lista de eventos do pod executado pelo invasor no kube-system
Nesses casos, você sempre deve prestar atenção a qualquer atividade suspeita no espaço kube-system, pois os invasores costumam usá-lo para mascarar suas atividades como legítimas.
Parece que perdemos mais uma etapa, a saber, o acesso à API Kubernetes para iniciar um pod privilegiado. Não há detectores para essas conexões na expertise atual da ferramenta (aguardamos seus PRs 🙂), mas os eventos definitivamente devem estar lá.
Então, vamos supor que não conhecemos a implementação específica desta etapa, mas sabemos com certeza que o script que iniciou a coleta de segredos iniciou um pod malicioso. Então, vamos tentar ver todas as conexões de rede que foram estabelecidas como parte do trabalho do script. Nos filtros do produto, selecionamos o contexto filho e a função tcp_connect, que é usada para inicializar conexões TCP.
Configurando filtros para obter eventos sobre conexões tcp
Para fazer isso, primeiro vamos ver as conexões de rede de eventos filhos. Não há nenhum, o que significa que o script não usou utilitários de terceiros para acessar a API Kubernetes. Então, é lógico supor que esse acesso foi implementado no código do script Python. Vamos alterar ligeiramente o filtro, selecionando o parâmetro Same process e verificar os eventos.
Pesquisando eventos com o mesmo processo que o evento selecionado
E, de fato, vemos eventos relacionados à conexão com os endpoints Kubernetes padrão disponíveis dentro do contêiner.
No total, detectamos:
Conexões de rede com a API Kubernetes;
Lançamento de um pod malicioso;
Fixação no nó por meio de comandos no pod.
Principais conclusões
O caso LiteLLM prova a necessidade de garantir a proteção e o monitoramento do ambiente de tempo de execução como parte do processo de desenvolvimento seguro. Isso é especialmente valioso quando seu shift left ainda não está maduro o suficiente ou emperrou no processo de integração. E para implementar essa proteção, a expertise básica de nosso produto é mais do que suficiente, e isso, apesar do fato de que o caso não demonstra todas as suas capacidades.
Aproveitando a oportunidade, convido todos os que não são indiferentes a participar do desenvolvimento de regras de detecção ainda mais avançadas para o runtime-radar. Tenho certeza de que juntos podemos tornar o produto ainda mais eficaz e a expertise mais precisa e ampla.
🛡️⚡
Pare de pesquisar. Comece a hackear.
O MundiX é seu copiloto de pentest com IA: comandos exatos, análise de outputs e próximo passo na kill chain — em segundos.
Sem cartão para começar · Planos a partir de R$49/mês
Como o Runtime Radar Ajuda a Detectar Ataques à Cadeia de Suprimentos: O Caso LiteLLM
Olá a todos! Sou Sergey Zyukin, desenvolvedor de expertise do runtime-radar, um produto de código aberto que garante a segurança do ambiente de tempo de execução de contêineres. Preparei um artigo para você, no qual contarei como é possível detectar um infostealer embutido na biblioteca LiteLLM como resultado de seu recente comprometimento. Além disso, é claro, também consideraremos a movimentação lateral dentro da infraestrutura Kubernetes, que ocorre se o script do infostealer for executado em um pod com privilégios suficientes.
Não conseguimos resistir e verificamos o que o Runtime Radar pode detectar ao implementar tal ataque. Mas, primeiro, vamos por partes.
Visão geral do ataque
Como muitos pesquisadores já analisaram em detalhes tanto o ataque em si quanto os antecedentes, não vou me aprofundar nisso e me limitarei a uma breve visão geral para facilitar a compreensão do contexto da detecção.
Se decompusermos o ataque em etapas, o seguinte acontece:
Ao iniciar, litellm_init.pth decodifica a carga útil (um script Python comum) de Base64 e a executa.
O primeiro script executa o infostealer e envia os dados coletados para o servidor C2 do invasor.
O infostealer coleta dados confidenciais e, se possível, se fixa por meio de um serviço systemd, deixando um backdoor para controle remoto.
Se o infostealer, durante a operação, encontrar um token de acesso Kubernetes, ele o usa para iniciar um contêiner malicioso em cada nó disponível do cluster.
O pod em si, por sua vez, é criado com acesso máximo ao sistema operacional do nó (privileged, hostPID, hostNetwork) e com o diretório raiz do nó do cluster montado, no qual foi executado.
Ao iniciar, ele se fixa no nó usando um backdoor e um serviço systemd.
O infostealer é implementado com base no princípio da matrioska - consiste em vários scripts Python ofuscados em Base64 e executados sequencialmente.
Portanto, dividi o trabalho de detecção em duas etapas:
Na fase de lançamento do script infostealer.
Na fase de movimentação no cluster Kubernetes.
Para cada etapa, demonstrarei os resultados do trabalho de expertise da versão atual do Runtime Radar e também darei algumas recomendações sobre como procurar ameaças usando nossa ferramenta de código aberto. Vamos lá.
Características de inicialização em um ambiente de teste e demonstração do script
Descreverei algumas nuances da execução do script, caso alguém queira repetir e estudar de forma independente os resultados do trabalho do Runtime Radar.
Creio que vale a pena mencionar que tudo o que está descrito abaixo deve ser feito apenas em um ambiente de teste isolado.
Simplifiquei um pouco o processo de reprodução (que o leitor me perdoe) e executei o primeiro script manualmente. Acredito que isso, em geral, não afeta nada, pois o mais interessante ainda acontece nos outros dois scripts.
E também fiz pequenas alterações em diferentes partes da matrioska de script - principalmente para minha própria conveniência e segurança:
Substituí o endpoint de conexão para enviar o arquivo final pelo meu interno;
Alterei o endpoint para receber comandos no script backdoor;
Modifiquei um pouco os comandos para fixar o backdoor no nó do cluster Kubernetes.
Para iniciar, usei python3.11 normal com módulos "prontos para uso", sem qualquer configuração adicional.
Para que o script possa se mover no Kubernetes, ele precisa de direitos para criar pods no cluster atual, então preparei uma conta de serviço com os direitos necessários e executei um pod em seu nome.
Se você quiser repetir, pode usar os seguintes manifestos:
Quanto aos parâmetros do próprio Runtime Radar, usei a versão que está atualmente disponível no GitHub sem quaisquer modificações ou atualizações adicionais de expertise. Assim, todos podem se certificar de forma independente dos resultados do trabalho.
Configurando políticas de coleta no Runtime Radar
Agora você pode iniciar e ver como tudo está pegando fogo verificar o funcionamento do script.
Abaixo estão algumas capturas de tela demonstrando os resultados de uma exploração bem-sucedida.
Pod que concluiu o trabalho no namespace kube-system, que foi iniciado pelo script e iniciou a fixação no nível do nó do cluster
Diretórios (/root/.config/sysmon e /root/.config/systemd) criados para fixar o backdoor
Vemos que a fuga do contêiner para o nó do cluster Kubernetes foi realizada.
Conexões ao meu endpoint da web, iniciadas pelo infostealer para enviar dados
Vamos agora ver o que nossa ferramenta detectou.
Detecção na fase de lançamento do infostealer
Após o lançamento, o infostealer começa a pesquisar e coletar muitos dados confidenciais diferentes, e o faz com ousadia e em voz alta.
Nossos detectores de atividade anômala demonstram isso perfeitamente: é possível observar vários disparos, sinalizando o lançamento suspeito do shell de comando (CS_RT_SUSP_SHELL) e a leitura de dados (CS_RT_SUSP_FILE_READ), o lançamento de conexões a vários endpoints (CS_RT_HACK_TOOLS_EXT, CS_RT_DOWNLOAD_TOOLS), vários lançamentos de env, whoami.
Leitura de arquivos confidenciais pelo script de coleta
Lançamento do shell de comando com comandos para pesquisar dados confidenciais, coleta de dados sobre o ambiente
O que vale a pena prestar atenção ao procurar ameaças e investigar incidentes semelhantes ao caso de comprometimento do LiteLLM. Como sempre, a atenção aos detalhes é a melhor amiga de qualquer especialista em busca de ameaças. Não é o fato de lançar o shell de comando que é alarmante, mas COMO isso acontece. Vemos:
Várias tentativas de lançamento em um curto período de tempo;
Um pai de processo suspeito do shell de comando.
Os filtros nos ajudarão a selecionar o detector necessário e ver toda a atividade como um todo. Como confirmação do fato de ilegitimidade, são usados argumentos preenchidos com vários comandos e modelos para pesquisar dados confidenciais.
Nos parâmetros do filtro, incluiremos a exibição de eventos nos quais ameaças foram detectadas (Events with threats only), especificaremos o detector CS_RT_SUSP_SHELL e aplicaremos as alterações.
Configurando o filtro para pesquisar eventos
O detector CS_RT_SUSP_SHELL rastreia o pai do processo do shell de comando, pois, neste caso, o processo pai é /usr/bin/python3, ele destaca essa atividade como uma ameaça.
Página de eventos da seleção anterior (disponível clicando no evento), onde você pode ver claramente o arquivo executável do processo pai
Há poucos aplicativos legítimos que usam Python para iniciar o shell de comando, e quando isso acontece várias vezes seguidas em um ambiente de produção, vale a pena ficar alarmado.
Também podemos estudar o comportamento do processo pai e ver quais ações suspeitas foram detectadas durante sua inicialização. Deixe-me lembrá-lo de que, em nossa matrioska, esse pai será o segundo script Python.
Vamos pegar qualquer evento da seleção anterior e, no menu de contexto, selecionar Parent context.
Pesquisando eventos relacionados ao processo pai do evento selecionado
Para exibir eventos, você precisa remover a filtragem por um detector específico.
Redefinindo a filtragem por um detector específico
É aqui que as coisas ficam interessantes: vemos os disparos de nossos detectores, relacionados ao acesso do processo pai a arquivos confidenciais (função security_file_permission). Observe que, para isso, o script não iniciou nenhum processo filho - isso foi feito durante a operação do código.
É nesses casos que nossa telemetria baseada em eBPF ajuda, o que permite rastrear o acesso a arquivos em um nível inferior, evitando a substituição e o rastreamento de chamadas de sistema específicas.
Entre os arquivos lidos, vemos o arquivo com hashes de senha de contas Linux (/etc/shadow) e o token da conta Kubernetes (aquela que criamos especialmente com direitos elevados para que a movimentação no cluster funcionasse).
Vamos agora ver o que aconteceu depois disso. Deixe-me lembrá-lo de que o script principal de nossa matrioska (aquele que é executado primeiro) ainda deve enviar dados para um servidor C2 externo. Para visualizar esses eventos, usaremos outro filtro de contexto - selecionaremos o parâmetro Same process.
Pesquisando eventos com o mesmo processo que o evento selecionado
Vemos os detectores disparados, que indicam a criação e exfiltração do arquivo de dados coletados.
Além disso, os eventos também contêm um dos indicadores de comprometimento (IoC) mais importantes - o endereço e a porta do servidor C2 final.
Como resultado, o Runtime Radar conseguiu detectar:
Pesquisa e coleta de dados confidenciais,
Exfiltração dos dados recebidos,
Endereço do servidor C2 do invasor.
Parece que já descobrimos passos suficientes aqui. Agora vamos para a etapa de movimentação no cluster Kubernetes e fuga do contêiner.
Detecção na fase de movimentação no cluster Kubernetes
Então, para se fixar no nó do cluster, o script inicia um pod no namespace kube-system, que monta o diretório raiz do nó e se fixa no nível do serviço systemd. Os parâmetros de coleta de eventos no Runtime Radar foram configurados para monitoramento parcial do kube-system, portanto, os eventos podem ser obtidos usando um filtro simples. Na captura de tela abaixo, vemos como, usando o Runtime Radar, filtramos eventos por namespace kube-system, também para melhor legibilidade, deixamos apenas eventos do tipo exec, excluindo eventos de conclusão do processo e kprobe.
Filtragem de eventos de segurança da informação na interface do produto
Os filtros nos ajudam a ver uma sequência clara de comandos executados no contêiner para implementar a fuga e a fixação no nó do cluster usando o serviço systemd. Além disso, o Runtime Radar nos permite entender que os comandos foram executados em um pod com o máximo de recursos (CAP_SYS_ADMIN). O CS_RT_BASE64_DECODE_RUN foi acionado a partir dos detectores, que detecta o uso de ferramentas para descriptografar a sequência Base64.
Lista de eventos do pod executado pelo invasor no kube-system
Nesses casos, você sempre deve prestar atenção a qualquer atividade suspeita no espaço kube-system, pois os invasores costumam usá-lo para mascarar suas atividades como legítimas.
Parece que perdemos mais uma etapa, a saber, o acesso à API Kubernetes para iniciar um pod privilegiado. Não há detectores para essas conexões na expertise atual da ferramenta (aguardamos seus PRs 🙂), mas os eventos definitivamente devem estar lá.
Então, vamos supor que não conhecemos a implementação específica desta etapa, mas sabemos com certeza que o script que iniciou a coleta de segredos iniciou um pod malicioso. Então, vamos tentar ver todas as conexões de rede que foram estabelecidas como parte do trabalho do script. Nos filtros do produto, selecionamos o contexto filho e a função tcp_connect, que é usada para inicializar conexões TCP.
Configurando filtros para obter eventos sobre conexões tcp
Para fazer isso, primeiro vamos ver as conexões de rede de eventos filhos. Não há nenhum, o que significa que o script não usou utilitários de terceiros para acessar a API Kubernetes. Então, é lógico supor que esse acesso foi implementado no código do script Python. Vamos alterar ligeiramente o filtro, selecionando o parâmetro Same process e verificar os eventos.
Pesquisando eventos com o mesmo processo que o evento selecionado
E, de fato, vemos eventos relacionados à conexão com os endpoints Kubernetes padrão disponíveis dentro do contêiner.
No total, detectamos:
Conexões de rede com a API Kubernetes;
Lançamento de um pod malicioso;
Fixação no nó por meio de comandos no pod.
Principais conclusões
O caso LiteLLM prova a necessidade de garantir a proteção e o monitoramento do ambiente de tempo de execução como parte do processo de desenvolvimento seguro. Isso é especialmente valioso quando seu shift left ainda não está maduro o suficiente ou emperrou no processo de integração. E para implementar essa proteção, a expertise básica de nosso produto é mais do que suficiente, e isso, apesar do fato de que o caso não demonstra todas as suas capacidades.
Aproveitando a oportunidade, convido todos os que não são indiferentes a participar do desenvolvimento de regras de detecção ainda mais avançadas para o runtime-radar. Tenho certeza de que juntos podemos tornar o produto ainda mais eficaz e a expertise mais precisa e ampla.
📤 Compartilhar & Baixar
🧰 Ferramentas recomendadas
Divulgação: alguns links são patrocinados. Podemos receber comissão se você comprar — sem custo extra para você. Só indicamos o que faz sentido para a comunidade.