LLMJacking: como credenciais comprometidas geram custos inesperados com LLMs
Uma aplicação pode continuar saudável enquanto outra pessoa utiliza suas credenciais para consumir modelos de linguagem diretamente no provedor. O tráfego indevido não precisa atravessar seu Ingress, sua API ou seu gateway: a identidade comprometida pode ser suficiente para autorizar inferências faturadas na sua conta. Esse é o problema central do LLMJacking documentado pela equipe de pesquisa da Sysdig. (sysdig.com)
Para equipes de plataforma, a pergunta operacional deixa de ser apenas quanto custa cada resposta. Também é necessário perguntar quem pode autorizar esse gasto, de onde essa identidade pode ser utilizada e quanto tempo leva para interromper seu consumo.
Este artigo propõe uma arquitetura defensiva com Amazon Bedrock e Amazon Elastic Kubernetes Service, o Amazon EKS. O recorte é comprometimento de identidade, detecção de consumo fora do caminho autorizado e contenção financeira. Para políticas de conteúdo e remoção de dados sensíveis, consulte o artigo complementar sobre proxy de IA e redação de dados sensíveis.
O que é LLMJacking
LLMJacking é o uso não autorizado de serviços de grandes modelos de linguagem, ou Large Language Models (LLMs), por meio de acesso comprometido. Na pesquisa publicada em 6 de maio de 2024, a Sysdig descreveu credenciais cloud roubadas, descoberta de serviços utilizáveis e indícios de revenda de acesso. A vítima arcava com o consumo. (sysdig.com)
O mecanismo é diferente de manipular instruções de um modelo: neste recorte, o atacante utiliza uma identidade válida para obter capacidade de inferência. Não é necessário que ele altere o modelo ou comprometa o provedor. (sysdig.com)
Uma sequência de ameaça útil para análise é:
Aplicação vulnerável → credencial exposta → descoberta de permissões → inferência não autorizada → cobrança
Esse fluxo sintetiza o incidente descrito pela Sysdig; não significa que toda ocorrência seguirá exatamente as mesmas etapas. (sysdig.com)
Para o threat model da sua organização, considere também chaves em pipelines de integração e entrega contínuas, CI/CD, estações de desenvolvimento e workloads comprometidos. Trate essas possibilidades como hipóteses a validar no inventário, não como evidência automática de invasão.
Os controles que não devem ser confundidos
| Controle | Pergunta que deve responder |
|---|---|
| Identidade | Quem está fazendo a chamada? |
| Autorização | Quais operações, modelos e recursos essa identidade pode utilizar? |
| Quota técnica | Qual volume o serviço permite processar? |
| Limite financeiro de admissão | Quanto a plataforma aceita comprometer antes de bloquear novas chamadas? |
| Auditoria | Quem utilizou o serviço, quando e por qual caminho? |
| Contenção | Como impedir novas autorizações após detectar comprometimento? |
Use essa separação como modelo de projeto. Não atribua a uma camada uma garantia que pertence a outra.
No Bedrock, quotas podem ser específicas por modelo e endpoint; elas não devem ser interpretadas automaticamente como um orçamento monetário global. Consulte as quotas efetivas da conta e inventarie todos os caminhos de inferência habilitados. (docs.aws.amazon.com)
Da mesma forma, uma notificação do AWS Budgets não é um bloqueio síncrono por requisição. A AWS documenta atrasos entre consumo, contabilização e notificação, durante os quais novos custos podem ocorrer. (docs.aws.amazon.com)
Como estimar a exposição financeira
Para um exercício simplificado de inferência textual, use:
custo estimado = tokens de entrada / 1.000.000 × preço de entrada + tokens de saída / 1.000.000 × preço de saída
Considere valores exclusivamente hipotéticos, sem associação a uma tabela comercial:
- 10.000 chamadas por hora;
- 8.000 tokens de entrada por chamada;
- 2.000 tokens de saída por chamada;
- US$ 2 por milhão de tokens de entrada;
- US$ 8 por milhão de tokens de saída.
Nesse exercício, a entrada custa US$ 160/h e a saída US$ 160/h. O total é US$ 320/h, ou US$ 7.680 em 24 horas de consumo constante.
Não se trata de preço atual, benchmark ou previsão de incidente. O objetivo é dimensionar o efeito do tempo de resposta. Para planejamento, use também:
exposição aproximada = taxa de gasto × tempo até contenção efetiva + consumo já admitido
Essa expressão não é um teto garantido: a taxa pode variar. No seu cálculo, inclua os componentes faturáveis efetivos do contrato e uma margem para requisições em andamento, processamento assíncrono e incerteza de medição.
Arquitetura: impedir o desvio do caminho autorizado
Proponho o seguinte caminho para chamadas legítimas:
Cliente autenticado → aplicação → admissão financeira → executor de inferência → Bedrock
Em paralelo:
Auditoria cloud + métricas do provedor + registros da plataforma → correlação → resposta a incidentes
A regra arquitetural é manter a permissão de inferência apenas no executor autorizado. Frontends e serviços que apenas encaminham solicitações não devem receber a mesma identidade cloud.
Centralizar chamadas não resolve sozinho o roubo da identidade do executor. O próprio executor precisa de permissões restritas e controles adicionais de origem. Para conectividade privada, o Bedrock oferece endpoints de interface com AWS PrivateLink e políticas de endpoint. (docs.aws.amazon.com)
Entretanto, disponibilizar um endpoint privado não obriga uma credencial roubada a utilizá-lo. Para impor esse requisito, avalie controles de perímetro com condições como aws:SourceVpce, considerando exceções de serviços e integrações legítimas. Teste chamadas pelo caminho aprovado e por um caminho não autorizado antes de promover a política. (docs.aws.amazon.com)
Para isolamento de rede entre workloads, mantenha a política de rede como uma camada separada; o desenho de egress está no artigo sobre rede para sandboxes de agentes em Kubernetes.
Implementação: identidade dedicada no EKS
1. Criar Namespace e ServiceAccount
O manifesto abaixo é completo para os objetos declarados. Ele não instala um gateway nem configura a associação IAM:
apiVersion: v1
kind: Namespace
metadata:
name: llm-runtime
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: llm-inference
namespace: llm-runtime
automountServiceAccountToken: falseO Namespace separa os objetos da aplicação. O ServiceAccount identifica o workload. automountServiceAccountToken: false desabilita a montagem automática do token padrão de acesso à API Kubernetes; o campo pode ser sobrescrito no Pod. (kubernetes.io)
Configure serviceAccountName: llm-inference no template do workload autorizado. Adapte os nomes à sua convenção e não crie um RoleBinding apenas para permitir chamadas AWS: autorização Kubernetes e autorização cloud são controles distintos.
Restrinja, por controle de acesso baseado em papéis, ou RBAC, quem pode criar Pods nesse Namespace, alterar workloads ou acessar Secrets. A capacidade de criar workloads pode permitir utilizar identidades e credenciais disponíveis no Namespace. (kubernetes.io)
2. Associar uma role com EKS Pod Identity
Com o EKS Pod Identity Agent instalado nos nós compatíveis, uma role IAM preparada e um SDK AWS compatível, crie a associação:
aws eks create-pod-identity-association \
--cluster-name production-eks \
--namespace llm-runtime \
--service-account llm-inference \
--role-arn arn:aws:iam::111122223333:role/llm-inference-runtimeSubstitua cluster, conta e role. A relação é administrada pelo EKS, sem annotation no ServiceAccount. A trust policy da role deve autorizar pods.eks.amazonaws.com com sts:AssumeRole e sts:TagSession; restrinja também o contexto de confiança conforme seu ambiente. (docs.aws.amazon.com)
O Pod Identity utiliza seu próprio token projetado e disponibiliza credenciais temporárias para SDKs compatíveis. Desabilitar o token padrão Kubernetes não significa eliminar esse mecanismo. Valide a identidade efetiva e remova credenciais estáticas que possam ser selecionadas pela cadeia de credenciais da aplicação. (docs.aws.amazon.com)
Credenciais temporárias ainda exigem proteção: se forem expostas, podem precisar de revogação antes da expiração. (docs.aws.amazon.com)
3. Autorizar somente os recursos necessários
Este Terraform cria uma política inline em uma role existente. O exemplo se limita a inferência direta em um foundation model:
variable "runtime_role_name" {
type = string
}
variable "approved_model_arn" {
type = string
}
resource "aws_iam_role_policy" "llm_inference" {
name = "approved-llm-inference"
role = var.runtime_role_name
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Sid = "InvokeApprovedModel"
Effect = "Allow"
Action = [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream"
]
Resource = var.approved_model_arn
}]
})
}Forneça o Amazon Resource Name, ARN, real do modelo aprovado. Valide suporte a inferência direta na região escolhida. A API Converse exige bedrock:InvokeModel; ConverseStream exige bedrock:InvokeModelWithResponseStream. (docs.aws.amazon.com)
Esse exemplo não é uma política universal para inference profiles, inferência cross-region ou outros endpoints. Revise os recursos exigidos pelo caminho escolhido. Além disso, um Allow restrito não remove permissões concedidas por outras políticas: revise a identidade completa e os controles organizacionais. (docs.aws.amazon.com)
Admissão financeira: antes de enviar, reservar
Para produção, recomendo implementar um controle explícito de admissão:
- Autenticar o chamador e derivar seu tenant no servidor.
- Validar modelo, tamanho da entrada, saída máxima e concorrência.
- Calcular uma reserva conservadora para a chamada.
- Reservar saldo atomicamente antes de encaminhar a inferência.
- Reconciliar a reserva com o consumo observado.
- Manter reserva pendente quando o resultado financeiro for desconhecido.
Não implemente o saldo como um contador independente em cada réplica. Projete um ledger compartilhado, operações idempotentes e recuperação após falha. PostgreSQL transacional é uma opção de projeto; Redis pode ajudar em limites de taxa, mas um contador volátil isolado não deve ser a única evidência financeira.
Para evitar confusão entre custo e capacidade, lembre que o Bedrock pode reservar quota considerando entrada e saída máxima, enquanto a cobrança considera o uso efetivo. Ajustar o máximo de saída influencia também a concorrência disponível. (docs.aws.amazon.com)
Defina limites por tenant, workload, modelo e ambiente. Dimensione também o teto global: a soma de vários limites locais pode ultrapassar a exposição aceita pela organização.
Esse desenho controla o tráfego admitido pela plataforma. Ele não limita chamadas que utilizem credenciais roubadas diretamente no provedor; por isso IAM, perímetro e reconciliação externa continuam obrigatórios.
Cenário próximo de produção
Problema: uma empresa hipotética executa workers de resumo documental no EKS. O desenho inicial compartilha uma chave entre desenvolvimento e produção e permite chamadas diretas ao provedor.
Solução: separar ambientes, substituir a chave por identidade dedicada e implantar admissão financeira com reconciliação.
Implementação proposta:
- Executor com múltiplas réplicas distribuídas entre zonas.
- Requests e limits definidos por testes de carga, sem confundi-los com limites de gasto.
- Readiness para retirar réplicas indisponíveis e liveness restrita à saúde local.
- Ledger com alta disponibilidade, backup e teste de restauração.
- Limites globais preservados durante autoscaling.
- Concorrência e retries limitados, com backoff e orçamento de tentativas.
- Bloqueio de novas inferências quando não for possível reservar saldo com segurança.
- Degradação funcional, como adiar resumos, em vez de desviar silenciosamente para uma credencial alternativa.
Resultado esperado: reduzir o alcance de uma credencial comprometida e tornar a contenção testável. Não se atribuem métricas a esse cenário fictício.
O trade-off é deliberado: falhar fechado protege o orçamento, mas pode indisponibilizar funcionalidades. Defina esse comportamento com o negócio e estabeleça um objetivo de nível de serviço, ou SLO, específico para a função assistida por LLM.
Observabilidade: detectar consumo fora da aplicação
Organize a investigação em três planos:
Auditoria de identidade
No Bedrock, operações como InvokeModel, InvokeModelWithResponseStream, Converse e ConverseStream são registradas pelo CloudTrail como eventos de gerenciamento. Outras operações exigem cobertura de eventos de dados. Não presuma que uma única configuração cobre todo o inventário. Em streaming, eventos adicionais de conclusão também exigem cuidado para não contar uma chamada duas vezes. (docs.aws.amazon.com)
Consumo do provedor
Para bedrock-runtime, acompanhe Invocations, InputTokenCount, OutputTokenCount, InvocationLatency e InvocationThrottles no CloudWatch. Observe as dimensões para não somar séries sobrepostas. Essas métricas não substituem a atribuição por tenant feita pela plataforma. (docs.aws.amazon.com)
Registros da plataforma
Proponho registrar identidade interna, modelo, identificador da requisição, reserva, consumo reconciliado e decisão de admissão. Correlacione isso com logs e traces, sem inserir prompts ou credenciais em atributos por padrão.
O model invocation logging do Bedrock é uma configuração separada e pode registrar entradas e saídas. Antes de habilitá-lo, defina retenção, criptografia, acesso e tratamento de dados sensíveis. (docs.aws.amazon.com)
Como regra de detecção, procure consumo no provedor sem chamadas correspondentes na plataforma, considerando atraso, retries, chamadas administrativas e diferenças de cobertura. Essa divergência é um sinal para investigação, não prova isolada de LLMJacking.
Defina alertas para gasto estimado por minuto, identidades inesperadas, modelos fora do inventário, backlog, falhas de reconciliação e perda de telemetria. Use orçamento faturado como confirmação posterior, não como único sensor operacional.
Resposta a incidentes: conter sem perder o controle
Prepare um runbook aprovado antes do incidente:
- Preservar evidências em paralelo à contenção: identidades, horários, eventos e alterações recentes.
- Bloquear a identidade comprometida: desativar chaves e aplicar o procedimento apropriado para sessões temporárias.
- Impedir a renovação do acesso: corrigir o ponto de entrada e revisar confiança, pipelines e permissões.
- Inventariar trabalho já iniciado: não presumir que novas negativas cancelam inferências ou jobs em andamento.
- Restaurar com identidade limpa: validar permissões e reintroduzir tráfego gradualmente.
- Reconciliar consumo e impacto: registrar a cronologia e acionar o suporte do provedor quando necessário, sem pressupor ressarcimento.
Para uma role exclusiva do executor comprometido, uma política emergencial deliberadamente abrangente é:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "IncidentContainment",
"Effect": "Deny",
"Action": "*",
"Resource": "*"
}
]
}Essa política bloqueia todas as ações AWS autorizadas por aquela role, não apenas inferência. É uma medida disruptiva, não uma configuração permanente. A AWS utiliza políticas de negação também no mecanismo de revogação de sessões; o procedimento oficial pode restringir sessões pelo horário de emissão. (docs.aws.amazon.com)
Não prometa bloqueio instantâneo nem cancelamento retroativo. Valide a eficácia por testes e telemetria. Um rollback seguro remove a contenção somente após a correção da causa, sem reintroduzir a credencial exposta.
Troubleshooting
| Sintoma | Possível causa | Investigação | Correção proposta |
|---|---|---|---|
| Cobrança aumenta, aplicação está estável | Consumo direto ou workload não inventariado | Comparar identidade cloud, região e chamadas internas | Conter a identidade e completar o inventário |
AccessDenied após migração | Role, associação ou recurso incorreto | Conferir identidade efetiva, trust policy e ARN | Corrigir o escopo exato; não liberar bedrock:* indiscriminadamente |
429 após aumentar réplicas | Concorrência acima da quota | Comparar throttling, saída máxima e tentativas | Reduzir concorrência e reavaliar limites |
| Consumo permanece após excluir Pods | Outra origem ou sessões ainda utilizáveis | Investigar atividade cloud fora do cluster | Conter a identidade, não apenas o workload |
| Plataforma bloqueia chamadas legítimas | Ledger indisponível ou reservas pendentes | Examinar disponibilidade e reconciliação | Recuperar o ledger e liberar reservas somente com evidência |
Comandos de inspeção para o Namespace do exemplo:
kubectl get pods -n llm-runtime
kubectl get serviceaccount llm-inference -n llm-runtime -o yaml
kubectl get events -n llm-runtime --sort-by=.metadata.creationTimestamp
aws eks list-pod-identity-associations --cluster-name production-eksA listagem das associações permite conferir cluster, Namespace e ServiceAccount; ela não comprova que a aplicação está utilizando a credencial esperada. (docs.aws.amazon.com)
Evite coletar tokens, variáveis sensíveis e dumps completos de Secrets em tickets de troubleshooting. Secrets Kubernetes precisam de controle de acesso e proteção em repouso; codificação base64 não é criptografia. (kubernetes.io)
Desenvolvimento, produção e manutenção
Em desenvolvimento, recomendo uma conta isolada, modelos aprovados, baixo teto financeiro e menor redundância. Nunca reutilize a identidade de produção para simplificar testes.
Em produção, exija responsáveis por identidade e orçamento, alta disponibilidade, TLS, backups testados, alertas acionáveis e exercícios periódicos de contenção. Versione IAM e políticas de admissão com GitOps. Antes de upgrades de SDK, modelo ou endpoint, teste autenticação, contagem de consumo, limites, negativas esperadas e recuperação.
No planejamento de capacidade, inclua requests, memória, concorrência, filas e quotas do provedor. No custo total, orce também endpoints privados, rede, armazenamento do ledger, load balancers e observabilidade. Trate a adoção de Spot no executor como uma decisão de tolerância a interrupções; não como uma redução do preço da inferência gerenciada.
Evite credenciais hardcoded, identidades compartilhadas, contadores apenas em memória, retries ilimitados, ausência de probes e mecanismos de emergência nunca testados. Não permita que o workload de inferência altere suas próprias permissões ou os controles responsáveis por detectá-lo.
Quando adotar uma plataforma central e quando simplificar
Uma camada central é indicada, como decisão arquitetural, quando vários times compartilham provedores, há múltiplos tenants ou a exposição financeira exige limites coordenados.
Para uma única aplicação de baixo volume, uma identidade restrita, isolamento de conta, limites no backend e alertas podem ser mais proporcionais. Não é necessário operar Kubernetes apenas para resolver LLMJacking.
| Alternativa | Benefício esperado | Trade-off |
|---|---|---|
| Backend direto com identidade dedicada | Menor complexidade | Governança distribuída entre aplicações |
| Executor central com ledger | Admissão financeira consistente | Novo serviço crítico para operar |
| Contas separadas por ambiente ou equipe | Fronteiras administrativas claras | Mais gestão e consolidação financeira |
| Gateway gerenciado | Menor esforço em parte da operação | Validar limites, auditoria, portabilidade e bypass |
Resumo prático
- Identifique quem pode transformar uma requisição em despesa.
- Reduza permissões e elimine credenciais compartilhadas.
- Reserve orçamento antes de admitir novas chamadas.
- Compare consumo cloud com o tráfego conhecido da plataforma.
- Teste revogação, recuperação e rollback antes do incidente.
Conclusão
A defesa contra LLMJacking deve ser tratada como uma responsabilidade conjunta de DevSecOps, FinOps e engenharia de confiabilidade, ou SRE. A plataforma precisa transformar autorização de consumo em um contrato explícito: identidade, escopo, limite, evidência e procedimento de interrupção.
O objetivo não é apenas descobrir uma conta alta. É conseguir demonstrar quais chamadas eram autorizadas, limitar a exposição durante uma falha e restaurar o serviço sem restaurar a vulnerabilidade.
Artigos relacionados
Quer aplicar isso no seu ambiente?
Agende uma conversa de 30 minutos sem compromisso. Eu olho o seu cenário e digo por onde começar.
Agendar uma conversaReceba os novos artigos por e-mail
Um e-mail quando sair artigo novo sobre infraestrutura, backend e IA. Sem spam, cancele quando quiser.