Voltar as noticias
Desenvolvendo um Scanner para Identificar Vulnerabilidades em Servidores MCP
MCP ProtocolAltaEN

Desenvolvendo um Scanner para Identificar Vulnerabilidades em Servidores MCP

Dev.to - MCP·27 de junho de 2026

Há algumas semanas, eu lancei o Warden, uma camada de governança que fica na frente de um servidor MCP e impõe quem pode ler o que. Baseado em funções, nível de campo. A demonstração tinha um papel support que podia listar contas de clientes, mas nunca ver seu tier de cobrança. O campo tier é removido de tudo que o suporte recebe de volta.

Eu estava mexendo nisso da mesma forma que você mexe em seu próprio trabalho quando não confia muito nele.. Eu tentei isso:

query_resource("accounts", {"tier": "Enterprise"})

Seis linhas retornaram. Acme Corp, Initech, Umbrella, Hooli, Stark, Wayne. O papel de suporte não pode ver o tier, mas a camada de consulta ainda aceitou isso como um filtro. Então você pede por todas as contas Enterprise, e as que correspondem dizem seu tier simplesmente por existir no resultado. A redacção se manteve na saída. Vazou através da entrada.

Esse é o bug. É pequeno e é chato e é exatamente o tipo de coisa que é enviada.

A parte que mais me incomodou do que o bug. Eu fui e executei os scanners de segurança do MCP nele. Os que todos usam agora leem o manifest: eles olham as descrições das ferramentas, fazem grep por instruções envenenadas, sinalizam metadados suspeitos. Boas ferramentas. Todas voltaram verdes. Elas têm que voltar. Não há nada de errado com o manifest. A descrição da ferramenta query_resource é honesta. O bug só existe quando o servidor está em execução e um papel real faz uma chamada real. Um scanner que lê texto não pode alcançá-lo.

Então eu construí a coisa que pode. Chama-se Siege.

Execute o servidor, não o leia

Siege aponta para um servidor MCP ao vivo e se comporta como um atacante contra ele, como papéis reais. Sem grep de manifest. Ele se conecta como cada identidade que você lhe dá e compara o que retorna.

A cunha é a autorização em tempo de execução. Scanners estáticos dominam a contaminação de ferramentas estáticas e estão bem nisso; eu não vou superá-los em grep. O que ninguém envia é uma ferramenta que exerce o servidor em execução como diferentes usuários e tenta quebrar o controle de acesso. Os fornecedores de RBAC sempre dizem "você deve red-team seu escopo de autorização" como conselho. Siege é esse conselho transformado em uma coisa que você executa.

A regra rígida que eu me impus: sem nomes de campos codificados, sem papéis codificados. Se ele só pegasse o bug do Warden porque eu lhe disse sobre tier, seria um teste unitário, não um scanner. Então o método é diferencial. Aprenda o esquema e os valores reais da identidade mais permissiva, aquela que vê tudo. Então, para cada papel restrito, compare o que ele vê em relação a isso e investigue as lacunas.

Quatro detectores surgiram disso, todos relativos ao papel:

  • Vazamento de filtro de campo redigido. O bug do Warden, generalizado. Para qualquer campo removido da saída de um papel, tente-o como um filtro. Se filtrar nele retornar menos linhas do que a linha de base, o valor oculto vazou através da diferença.
  • Escalação de escopo de linha. Um papel cuja visão normal é limitada a um subconjunto (região = Oeste, por exemplo) tenta um valor de filtro fora do escopo. Se region=East retornar linhas que não deveria ter, o filtro foi executado contra o conjunto de dados completo em vez do limitado.
  • Enumeração de ID. O caminho da lista é governado, a busca de registro único muitas vezes não é. Portanto, get_record em ids adivinhados passa direto pela limitação que query_resource impõe. Clássico IDOR, edição MCP.
  • Leitura de recurso proibido. Um papel não pode nem listar um recurso, mas get_record entrega um de qualquer maneira. O acesso foi verificado na lista e na consulta, esquecido no caminho por-id.

Os últimos três eu nunca encontrei manualmente. Eles surgiram ao escrever o primeiro genericamente.. construa o motor para um bug e ele puxa os próximos alguns com ele.

O golpe de mestre

Eu mantenho duas versões do Warden: o commit vulnerável e o corrigido. O Siege roda contra ambos.

ANTES — Warden vulnerável (4938bdf)
## 1. [ALTO] Campo redigido 'tier' vaza através do predicado de filtro em 'accounts'
   Encontrado como papel: support
   Reproduzir: query_resource({"resource_type":"accounts","filters":{"tier":"Enterprise"}})
   contagem_base: 8   contagem_filtrada: 6
   registros_vazados: ['Acme Corp', 'Initech', 'Umbrella Co', 'Hooli', 'Stark Industries', 'Wayne Enterprises']

DEPOIS — Warden corrigido (7188eed)
   Sem descobertas. As classes sondadas mantiveram-se.

VEREDITO: APROVADO — Siege pegou o bug e limpou a correção.

Cada descoberta carrega uma reprodução exata e reproduzível: a ferramenta, os argumentos, as linhas que retornaram. Você pode colá-lo em seu próprio cliente e assistir ao vazamento. E para garantir que os detectores não sejam no-ops que passam tudo, há um servidor de fixture intencionalmente quebrado no repositório. O Siege dispara todos os quatro detectores nele, incluindo a leitura de recurso proibido crítica. está lá se você quiser assisti-lo funcionar.

A segunda classe: o agente realmente foi comprometido

A contaminação de ferramentas é o ataque de que todos falam: esconder uma instrução em uma descrição de ferramenta ou na saída de uma ferramenta, e o agente que a lê faz o que o atacante disse em vez do que o usuário pediu. Scanners estáticos perguntam "essa descrição parece hostil?" O Siege faz uma pergunta diferente. O agente foi sequestrado.

Então ele executa um loop de agente real. Ferramenta de leitura benigna, além de um export_record que envia dados para uma URL. A tarefa do usuário é somente leitura: resumir o registro 1, isso é tudo. Então o Siege injeta cada carga útil através do canal de descrição e do canal de saída e observa se o modelo aciona o sink em um destino de atacante que nunca foi solicitado a tocar. Um sequestro é observado, não inferido a partir do texto.

A saída é uma matriz, não um veredicto. Cinco cargas úteis através de dois canais: spoofing de bloqueio do sistema (executado através de ambos os canais de descrição e saída), texto de política simples, confusão de papéis, decomposição de tarefas. Você vê quais deles direcionaram o modelo e quais não funcionaram. Um resultado limpo de 0 em 5 também é um resultado real, e uma proteção contra regressão para o dia em que você atualizar versões de modelo e uma estrutura que costumava falhar deixa de falhar.

O que não faz

O relatório nomeia as classes que executou e imprime o que pulou. Servidores MCP apenas por enquanto, sem chamadas de função OpenAI, isso é uma expansão futura. Transporte stdio hoje, HTTP na próxima. A classe de falha silenciosa (o servidor afirma sucesso enquanto retorna dados vazios) está projetada e ainda não foi enviada. Nenhum "encontra todas as vulnerabilidades" em qualquer lugar na saída, porque essa frase é como scanners mentem.

E ele só ataca meus próprios fixtures e servidores que eu explicitamente opto por participar. Apontar uma ferramenta de red-team em tempo de execução para o servidor ao vivo de outra pessoa sem um convite não é uma demonstração.

Onde ele se encontra

Siege é o braço ofensivo de um stack de três peças. Warden governa o servidor. Crumb atribui cada chamada à pessoa que a autorizou. Siege é a parte que tenta quebrar o que o Warden construiu. Construa o muro, depois cerque-o.

O código é público: github.com/AlexlaGuardia/siege. É v0.1 e é estreito de propósito. Executa contra um servidor ao vivo, como papéis reais. A parte que o manifest não pode mostrar a você.

Contexto Triplo Up

A segurança em servidores MCP é crucial para empresas que utilizam esse protocolo. O Siege permite que as empresas identifiquem e corrijam vulnerabilidades de acesso, garantindo a proteção de dados sensíveis e a conformidade com regulamentações de segurança.

Noticias relacionadas

Gostou do conteudo?

Receba toda semana as principais novidades sobre WebMCP.