8 min de leitura

Testes de SSRF para ferramentas de agente que injetam credenciais

Testes de SSRF para ferramentas de agente precisam de uma matriz de destinos que detecte loopback, intervalos privados, rebinding, redirecionamentos e IPv6 antes da autenticação.

Testes de SSRF para ferramentas de agente que injetam credenciais

Uma ferramenta de agente que injeta credenciais transforma uma simples requisição HTTP de saída em uma decisão de fronteira. Se a ferramenta aceita um destino vindo do agente, valida um hostname de aparência confiável e depois deixa o cliente HTTP seguir para onde o DNS e os redirecionamentos levarem, ela entregou sua credencial a um serviço escolhido pelo atacante.

A solução não é colar uma lista de bloqueio maior em um validador de URLs. Você precisa de uma matriz de destinos que exercite todo o ciclo da requisição: análise, resolução DNS, seleção do endereço, conexão, tratamento de redirecionamentos e só então injeção da credencial. O teste precisa observar o peer que recebeu a requisição, porque foi ali que o segredo chegou.

A injeção de credenciais deve ocorrer depois da aprovação do destino

A ferramenta deve decidir se pode contatar um destino antes de anexar qualquer material de autenticação. Isso inclui tokens bearer, credenciais básicas, cabeçalhos personalizados, assinaturas de requisição, certificados de cliente e identidades SSH.

As equipes costumam colocar a verificação no lugar errado. Validam a string da URL original, criam uma requisição com um cabeçalho Authorization e chamam um helper HTTP conveniente com o seguimento de redirecionamentos ativado. O helper então resolve os nomes, escolhe IPv6 ou IPv4, segue um cabeçalho Location e pode reutilizar cabeçalhos ou o estado da conexão de formas que o código de validação nunca viu.

Esse desenho tem uma propriedade útil: é fácil de escrever. Também deixa a decisão perigosa nas mãos de um componente que não sabe se a requisição transporta uma credencial.

Mantenha duas decisões separadas:

  • Esta URL é sintaticamente aceitável para a ferramenta?
  • Este destino de rede concreto foi aprovado para uma conexão autenticada?

A primeira decisão analisa esquema, host, porta, caminho, userinfo e codificação percentual. A segunda classifica os endereços resolvidos e controla a conexão real. Uma lista de permissões de hosts pode contribuir para as duas decisões, mas não substitui a segunda.

A RFC 3986 deixa o problema de análise claro. O componente de autoridade tem o formato [userinfo@]host[:port]; uma string que parece conter um hostname confiável antes de @ ainda pode indicar um endereço IP depois dele. A RFC 3986 usa essa construção ao discutir strings de autoridade URI enganosas. Não divida URLs por conta própria e não procure um nome confiável na string bruta. Analise a URL com um parser compatível com os padrões, rejeite userinfo para destinos se a ferramenta não tiver uma necessidade legítima e leia o campo de host analisado.

O invariante de segurança é simples o suficiente para ser testado:

A ferramenta não deve enviar nenhum byte autenticado até aprovar o peer conectado e a autoridade da requisição.

«Byte autenticado» inclui a linha da requisição ou o cabeçalho Host apenas quando esses valores revelam um segredo. Na maioria dos casos HTTP, o limite importante é o cabeçalho que contém a credencial ou o payload assinado. Seja mais rigoroso quando o caminho, a query string ou o corpo contiver uma capability URL, um identificador de tenant ou outro valor sensível.

Defina o ponto de decisão antes de escrever os casos

Você não pode testar um controle contra SSRF sem nomear o ponto exato em que ele decide permitir ou negar. «Antes da requisição» é vago demais. Uma requisição passa por vários momentos em que o destino pode mudar.

Use esta sequência como modelo para uma ferramenta HTTP que injeta credenciais:

  1. Analise a URL absoluta fornecida e rejeite esquemas não suportados, autoridades malformadas, userinfo e portas fora do contrato da ferramenta.
  2. Resolva o hostname pelo resolvedor que o processo realmente usará. Reúna respostas A e AAAA, não apenas a resposta que sua máquina de desenvolvimento preferiu.
  3. Classifique cada endereço candidato. Rejeite a requisição quando o conjunto contiver um endereço fora das classes de destino aprovadas, a menos que o conector consiga fixar a conexão em um endereço aprovado.
  4. Abra uma conexão com um endereço aprovado e verifique o endereço do peer remoto antes de escrever a credencial.
  5. Construa a requisição autenticada apenas depois dessa verificação. Defina deliberadamente o cabeçalho Host e o nome do servidor TLS.
  6. Trate um redirecionamento como uma nova requisição que começa na análise, não como uma continuação que herda confiança.

Isso é mais exigente do que verificar hostname != "localhost". Precisa ser. A RFC 8305 descreve clientes fazendo consultas AAAA e A em intervalos próximos e tentando endereços levando a preferência por IPv6 em conta. Uma suíte que resolve apenas registros A pode certificar um código que falha assim que aparece um registro AAAA acessível.

O ponto de decisão também determina o que o seu harness precisa registrar. Para cada tentativa, capture:

  • a URL recebida pela ferramenta
  • as respostas DNS retornadas à ferramenta
  • o endereço escolhido para a conexão
  • o endereço observado pelo servidor receptor
  • todos os cabeçalhos da requisição, ocultando as credenciais de teste nos relatórios

Não use um teste que verifique apenas um código de status ou uma exceção. Um 403 do seu servidor de captura prova que ele recebeu a requisição. Um timeout pode não provar nada. A asserção desejada é: «O listener bloqueado não observou nenhuma requisição que carregasse credenciais.»

Construa a matriz em torno dos destinos, não dos hostnames

Uma matriz de destinos é o artefato durável desse trabalho. Cada linha nomeia uma forma de entrada, a resposta do resolvedor, um comportamento opcional de redirecionamento e o resultado esperado. Ela evita o desvio comum em que uma pessoa testa 127.0.0.1, outra testa 10.0.0.1 e ninguém testa as formas estranhas aceitas pelo runtime.

Comece com uma matriz pequena que tenha um oráculo real. O exemplo abaixo presume que public.test aponta para um listener de harness classificado como permitido, enquanto todas as outras classes de endereço devem ser negadas antes da injeção da credencial.

CasoURL enviadaComportamento DNS ou de redirecionamentoResultado esperado
IPv4 públicohttps://public.test/echoRegistro A para fixture público do harnessPermitir e enviar a credencial de teste
Loopback IPv4http://127.0.0.1:18080/Endereço literalNegar antes da conexão
Variante de loopback IPv4http://127.1:18080/Forma abreviada dependente do parserRejeitar ou classificar como loopback, nunca permitir
RFC 1918 privadohttp://10.20.30.40/Endereço literalNegar antes da conexão
RFC 1918 privadohttp://172.20.30.40/Endereço literalNegar antes da conexão
RFC 1918 privadohttp://192.168.20.40/Endereço literalNegar antes da conexão
Loopback IPv6http://[::1]:18080/Endereço literalNegar antes da conexão
IPv6 link-localhttp://[fe80::1]/Endereço literalNegar antes da conexão
IPv6 mapeado para IPv4http://[::ffff:127.0.0.1]/Endereço literalNegar antes da conexão
Resposta DNS mistahttps://mixed.test/A permitido, AAAA bloqueadoNegar ou fixar a conexão no endereço permitido
Nome com rebindinghttps://rebind.test/Primeiro permitido, depois bloqueadoNegar a requisição autenticada para o peer bloqueado
Redirecionamento para loopbackhttps://public.test/to-local302 para http://127.0.0.1:18080/Negar a segunda requisição
Redirecionamento para DNS privadohttps://public.test/to-private302 para https://internal.test/Resolver e negar a segunda requisição
Engano com userinfohttp://[email protected]/Host literal depois de @Rejeitar antes da conexão

A RFC 1918 define apenas três blocos privados IPv4: 10/8, 172.16/12 e 192.168/16. Teste os limites, especialmente 172.15.255.255, 172.16.0.0, 172.31.255.255 e 172.32.0.0. Uma verificação de prefixo descuidada costuma bloquear todo 172/8, quebrando endpoints públicos legítimos, ou bloquear apenas 172.16/16, deixando de cobrir a maior parte do intervalo privado alocado.

Não confunda esta tabela com uma política universal de produção. Algumas ferramentas internas precisam poder contatar um serviço privado específico. Se esse for o requisito do produto, crie uma regra explícita para o serviço, com hostname, porta e verificação de identidade restritos. Não transforme «endereços privados são permitidos no nosso escritório» no padrão para todo destino escolhido por um agente.

Testes de análise de URL detectam erros antes do DNS

O parser precisa identificar o host que o conector usará. Isso parece óbvio até que um teste revele que um componente normaliza a entrada de forma diferente de outro.

Coloque estes casos em uma suíte que teste apenas o parser. Eles devem executar sem DNS ou socket de rede:

http://[email protected]/admin
http://127.0.0.1.nip.example/
http://[::1]/
http://[::ffff:7f00:1]/
http://0177.0.0.1/
http://2130706433/
http://127.0.0.1%2f.example/
http://public.test:[email protected]/
http://public.test./

O resultado esperado nem sempre é «esta string exata deve ser analisada como loopback». Bibliotecas URI e URL divergem em formas numéricas IPv4 antigas, identificadores de zona e codificações percentuais inválidas. O teste deve declarar a propriedade de segurança: se o runtime aceitar a entrada e conectar-se a um endereço bloqueado, a ferramenta deve negá-la. Se o runtime rejeitar a entrada, tudo bem.

Essa distinção importa porque muitas equipes escrevem primeiro um filtro de host personalizado e depois entregam a URL inalterada a outra biblioteca. O filtro pode considerar 2130706433 um nome registrado desconhecido, enquanto o conector o interpreta como 127.0.0.1. Você acabou testando dois parsers e confiou na resposta mais segura.

Use a mesma representação analisada para validação e conexão. Quando isso não for possível, faça o conector final informar o peer numérico escolhido e realize uma última verificação da classe do endereço antes que as credenciais saiam do processo.

Teste também a normalização de hostnames. Um ponto final em public.test. refere-se ao mesmo nome DNS que public.test no uso comum, mas listas de permissões simplistas costumam comparar strings brutas. Hostnames internacionalizados acrescentam outro ponto de divergência. Converta uma vez para a representação canônica usada pelo runtime e compare o nome DNS nos limites dos labels. Uma verificação de sufixo como endsWith("trusted.example") aceita untrusted.example e trusted.example.attacker.test; nenhum dos dois é um subdomínio confiável.

Os testes de DNS rebinding precisam forçar a segunda consulta

Mova a injeção para trás da fronteira
As credenciais HTTP são injetadas pelo aplicativo, não copiadas para prompts ou argumentos de ferramentas.

O DNS rebinding é uma falha de tempo. A consulta inicial retorna um endereço aceitável. Uma consulta posterior para o mesmo nome retorna loopback, um endereço privado ou outro destino bloqueado. Se a validação e a conexão não usam o mesmo resultado de resolução, um atacante pode passar pela primeira verificação e direcionar a segunda.

Um fixture útil precisa de um pequeno servidor DNS autoritativo sob seu controle e dois listeners HTTP. Um listener é o fixture permitido. O outro é um fixture bloqueado que registra se recebeu o cabeçalho Authorization de teste. Dê ao servidor DNS uma sequência de respostas para rebind.test:

query 1: rebind.test. A     198.51.100.20
query 2: rebind.test. A     127.0.0.1
query 1: rebind.test. AAAA  2001:db8::20
query 2: rebind.test. AAAA  ::1

Use endereços exclusivos do harness e mapeie o listener permitido na rede de teste conforme necessário. Os endereços com aparência pública deste exemplo são rótulos do fixture, não endpoints que o teste deve contatar na Internet.

Execute agora duas variantes. Na primeira, faça a ferramenta realizar sua própria consulta de validação e depois chame uma biblioteca HTTP que resolva os nomes separadamente. O listener bloqueado deve receber a credencial se a implementação tiver a falha procurada. Na segunda, configure o caminho da conexão para usar o endereço resolvido aprovado, preserve o hostname original apenas para a verificação de Host e do nome TLS e confirme que o listener bloqueado não observa nada.

O cache pode ocultar o problema. Um cache do resolvedor, um pool de conexões ou o cache do sistema operacional pode transformar a segunda resposta em um evento que nunca acontece. O harness deve expor controles de cache, fechar conexões ociosas entre execuções, usar um hostname novo por execução quando necessário e registrar cada consulta DNS. Se um teste de rebinding passar sem confirmar duas consultas distintas, ele não testou rebinding.

Não resolva o problema confiando no TTL do DNS. TTL é uma instrução de cache, não uma afirmação de que um nome continua seguro entre a validação e a conexão. O código precisa levar o endereço aprovado até a conexão ou verificar o peer depois que o socket for aberto.

Redirecionamentos são decisões separadas sobre destinos

Um redirecionamento muda o destino. Ele pode mudar o esquema, o host, a porta, o caminho ou os quatro. Tratá-lo como uma continuação confiável é como uma URL pública aparentemente segura acaba virando uma requisição para 127.0.0.1, um serviço de metadados de instância, um roteador ou um plano de controle interno.

Desative o seguimento automático de redirecionamentos no transporte usado pela requisição que carrega credenciais. Leia a resposta de redirecionamento, imponha um limite moderado de redirecionamentos, analise o valor de Location em relação à URL atual conforme as regras de resolução da biblioteca e execute novamente toda a decisão sobre o destino.

Seu fixture de redirecionamento deve incluir pelo menos estes comportamentos:

  • Uma URL pública retorna 302 para um literal de loopback IPv4.
  • Uma URL pública retorna 307 para um hostname que resolve para um endereço IPv4 privado.
  • Uma URL pública retorna um Location relativo como /next, que deve permanecer na autoridade já aprovada depois da resolução normal.
  • Uma URL pública retorna um Location relativo ao esquema como //other.test/path, que muda a autoridade e precisa de validação completa.
  • Uma URL pública retorna uma cadeia em que o primeiro salto é permitido e um salto posterior é bloqueado.

Os códigos de status importam. Um 301, 302 ou 303 pode levar os clientes a transformar um método que não seja GET em GET. Um 307 ou 308 deve preservar o método e o corpo. Não dependa do comportamento padrão da biblioteca quando houver um POST assinado ou uma escrita autenticada por bearer. Registre o método, o hash do corpo, o cabeçalho Host e o cabeçalho Authorization em cada fixture de redirecionamento.

Remover Authorization sempre que a autoridade mudar é uma boa defesa, mas não torna a validação do destino opcional. Uma requisição sem Authorization ainda pode carregar uma URL assinada no caminho, um certificado de cliente, cookies ou um corpo sensível. Um redirecionamento para o mesmo host também pode apontar de um caminho comum para um serviço local se o DNS mudar entre os saltos.

Este é um ponto em que o teste deve ser deliberadamente simples. Faça o listener de redirecionamento bloqueado retornar 200. Se a asserção apenas esperar um erro do cliente, um cliente que segue redirecionamentos pode realizar a requisição SSRF com sucesso e o teste a considerará aprovado pelo motivo errado. Verifique a quantidade de requisições capturadas pelo listener e o estado das credenciais capturadas.

IPv6 é uma superfície de SSRF de primeira classe

Veja cada chamada com credenciais
Revise chamadas HTTP e SSH individuais no diário de Atividade depois que o agente terminar.

A omissão de IPv6 costuma ser acidental. O desenvolvedor testa 127.0.0.1, bloqueia intervalos RFC 1918 e entrega um código que trata [::1] como um hostname exótico. Clientes modernos podem consultar registros AAAA junto com registros A, e uma rota IPv6 pode vencer mesmo quando os testes IPv4 parecem limpos.

A RFC 4291 identifica ::1/128 como o endereço de loopback IPv6 e ::/128 como o endereço não especificado. Ela também define endereços unicast link-local em fe80::/10. Essas classes de endereço nunca devem virar acidentalmente um destino autenticado escolhido pelo agente.

Teste explicitamente estas categorias:

Classe de endereçoExemploExpectativa padrão do teste
Não especificado[::]Negar
Loopback[::1]Negar
Link-local[fe80::1]Negar
Local exclusivo[fc00::1], [fd12:3456::1]Negar, salvo aprovação explícita
Multicast[ff02::1]Negar
Loopback IPv4 mapeado[::ffff:127.0.0.1]Negar
IPv4 privado mapeado[::ffff:192.168.1.10]Negar

A classificação deve operar sobre o endereço binário, não sobre sua grafia. O mesmo endereço pode aparecer na forma comprimida ou expandida. Uma comparação de strings com ::1 não detecta 0:0:0:0:0:0:0:1. Analisar primeiro para um tipo IP real é a parte pouco glamourosa que impede essa categoria de bug.

Os identificadores de escopo também precisam de uma regra clara. Uma entrada como [fe80::1%25en0] contém uma zona de interface depois da codificação percentual. A maioria das ferramentas deve rejeitar destinos literais com escopo de zona vindos do agente, em vez de tentar decidir qual interface local é segura. Se o produto tiver um caso legítimo de uso na rede local, transforme a escolha da interface em uma configuração explícita do usuário, nunca em um detalhe da URL fornecido pelo agente.

Respostas A e AAAA mistas exigem uma decisão firme. Se o resolvedor retornar um endereço IPv4 permitido e um endereço IPv6 bloqueado, o padrão mais seguro é negar. Se a disponibilidade exigir o uso da resposta permitida, o conector deve fixar o socket nesse endereço e não devolver o hostname a um resolvedor depois. «Preferimos IPv4» não é um controle. Bibliotecas de rede, sistemas operacionais e disputas de conexão podem escolher outra opção.

Execute a matriz dentro de um harness fechado

Não aponte testes de SSRF para os serviços reais de localhost do seu laptop ou para um endpoint de metadados de nuvem. Você quer provas, não uma tarde estressante. Coloque o resolvedor e todos os listeners em uma rede de teste isolada, use credenciais descartáveis e faça os listeners registrarem o próprio endereço e os cabeçalhos recebidos.

Um harness simples tem quatro participantes:

  1. Um executor de testes que chama a ferramenta com uma URL e uma referência a uma credencial descartável.
  2. Um servidor DNS controlável que pode retornar respostas A e AAAA em uma ordem programada.
  3. Um fixture HTTP permitido que registra requisições autenticadas bem-sucedidas.
  4. Um fixture HTTP bloqueado que registra qualquer conexão ou requisição como falha do teste.

Dê ao fixture bloqueado um corpo de resposta que torne os vazamentos óbvios nos logs locais, mas nunca imprima um token completo. Por exemplo, ele pode retornar o endereço do peer, o método da requisição, o cabeçalho Host e um booleano informando se Authorization estava presente. O executor compara essa evidência com a linha esperada da matriz.

O formato do resultado deve ser simples o suficiente para inspeção no CI:

case=redirect_to_loopback
submitted=https://public.test/to-local
resolved=198.51.100.20
redirect=http://127.0.0.1:18080/
decision=deny
allowed_requests=0
blocked_connections=0
blocked_credentials=0

Uma falha deve preservar os mesmos campos, além do peer real. Isso transforma uma regressão vaga em um relatório acionável:

case=rebind_ipv6
submitted=https://rebind.test/export
validation_answer=2001:db8::20
connected_peer=::1
blocked_credentials=1
result=FAIL

Esse relatório identifica o bug imediatamente: o código aprovou uma resposta DNS e conectou-se a outra. Ele também informa se a credencial atravessou a fronteira, que é o risco importante.

Se a ferramenta aceitar configuração de proxy, acrescente linhas de proxy à matriz. Um proxy HTTP muda para onde vai a conexão TCP, enquanto CONNECT ainda pode fazer o proxy alcançar um destino escolhido pelo atacante. Decida se o próprio proxy é um transporte confiável e se a ferramenta valida a autoridade final. Um teste de proxy que verifica apenas o endereço do proxy pode certificar um relay aberto para destinos internos.

Mantenha autoridade e destino separados na implementação

Bloqueie as credenciais antes das ações
Bloqueie o cofre com o Touch ID e todas as ações do agente serão negadas.

O TLS facilita a confusão desse problema. Para conectar-se com segurança a um hostname, a ferramenta pode precisar abrir um socket para um endereço numérico aprovado enquanto apresenta o hostname original aprovado como nome do servidor TLS e cabeçalho HTTP Host. São campos diferentes, com funções diferentes.

O peer numérico responde: «Para onde este socket está indo?» O nome do servidor TLS responde: «Qual identidade de certificado este servidor precisa provar?» O cabeçalho Host responde: «Qual autoridade HTTP esta requisição está direcionando?» A implementação deve manter os três valores explícitos, em vez de deixar uma API HTTP conveniente inferi-los de uma string de URL mutável.

Essa separação também revela uma recomendação ruim que continua popular: resolver uma vez e substituir o hostname na URL pelo endereço numérico. Isso pode evitar uma segunda consulta DNS, mas pode quebrar a validação do certificado TLS, o virtual hosting e esquemas de requisição assinada. Os desenvolvedores frequentemente respondem desativando a verificação de certificados ou enfraquecendo as verificações de host. Isso é pior que o bug original.

Em vez disso, use um transporte que permita discar para o endereço aprovado mantendo a validação TLS rigorosa do hostname original. Depois do handshake, confirme que o peer do socket é o endereço aprovado. Se o runtime não oferecer esses controles, não afirme que ele impede DNS rebinding para requisições autenticadas de agentes. Coloque a limitação na fronteira do produto e evite injetar credenciais em destinos escolhidos pelo agente.

O SSH tem a mesma estrutura, embora não use redirecionamentos HTTP. Resolva e classifique o host solicitado, fixe a conexão no endereço aprovado e verifique a chave do host em relação à identidade pretendida. Um prompt de chave de host ou uma regra permissiva de known-hosts não é uma política de destino.

O Sallyport mantém as credenciais dentro do cofre criptografado e executa ações HTTP e SSH por conta própria, em vez de entregar o material secreto ao agente. Essa fronteira só funciona se a camada de ações aplicar controles de destino antes de usar uma credencial armazenada.

Transforme a matriz em um bloqueio de release, não em um documento de segurança

Uma matriz de destinos só é útil quando roda contra o mesmo caminho de requisição que será publicado. Um teste unitário de isPrivateIp() não testa o resolvedor do cliente HTTP, o código de redirecionamento, o comportamento do proxy ou o pool de conexões. Mantenha os testes unitários, mas torne a suíte do harness obrigatória sempre que atualizar a biblioteca de transporte, o parser de URL, a configuração do resolvedor ou o código de injeção de credenciais.

Acrescente linhas quando corrigir um bug. Não reduza um incidente doloroso a uma frase ampla como «melhorar a validação de SSRF». Preserve a entrada exata, a sequência DNS, a resposta de redirecionamento e a ausência esperada de credenciais. As futuras pessoas responsáveis pela manutenção precisam desse histórico em forma executável.

Revise as falhas por categoria. Divergências de parser apontam para tratamento duplicado de URLs. Um listener bloqueado que vê uma conexão TCP, mas nenhuma requisição, pode indicar que a validação ocorreu tarde demais, mesmo que nenhum token tenha vazado. Um listener bloqueado que vê um cabeçalho Authorization significa que o invariante falhou e deve interromper o release.

O trabalho compensa porque muda a pergunta feita pela equipe. Pare de perguntar se um hostname parecia externo. Pergunte qual peer recebeu uma requisição autenticada, como ele foi selecionado e se o teste consegue provar a resposta. Se a saída do teste não responder a isso, a ferramenta ainda tem um ponto cego de SSRF.

FAQ

Uma lista de permissões de hostnames basta para evitar SSRF em uma ferramenta de agente?

Não. O hostname é apenas uma entrada para a resolução, e um nome que parecia inofensivo pode resolver para um endereço local ou privado quando o cliente se conecta. Teste o conjunto de endereços resolvidos e o peer conectado de fato, não apenas o texto original fornecido pelo agente.

Um cliente HTTP deve encaminhar credenciais durante redirecionamentos?

Trate cada redirecionamento como uma nova solicitação para um destino diferente. Valide a nova URL, resolva-a novamente, aplique a mesma decisão sobre o destino e só anexe as credenciais depois que ela for aprovada. Se o redirecionamento mudar a autoridade, remover o cabeçalho Authorization é uma boa defesa, mas não basta.

Quais endereços IPv6 um teste de SSRF deve bloquear?

Sim. Bloqueie ou classifique explicitamente o loopback IPv6 (::1), o endereço não especificado (::), endereços link-local (fe80::/10), endereços locais exclusivos (fc00::/7), multicast e formas IPv4 mapeadas em IPv6. Uma suíte que testa apenas endereços IPv4 com pontos deixa uma grande área sem cobertura.

Como testar DNS rebinding com segurança?

O DNS rebinding ocorre quando o nome passa por uma consulta inicial, mas retorna outro endereço depois, muitas vezes pouco antes da conexão. Use um fixture de DNS controlável que responda primeiro com um endereço permitido e depois com um endereço bloqueado. Em seguida, confirme que a ferramenta não envia uma solicitação autenticada para o peer bloqueado.

Posso validar o DNS uma vez e deixar a biblioteca HTTP se conectar normalmente?

Não. Verificar um resultado de resolução e depois permitir que a biblioteca HTTP resolva o hostname novamente cria uma lacuna entre a verificação e o uso. Resolva o nome, classifique todos os candidatos e conecte-se usando o endereço aprovado, ou verifique o endereço do peer depois da conexão e antes de enviar as credenciais.

O que é uma matriz de destinos para testes de SSRF?

Uma matriz de destinos é uma lista de entradas de URL, respostas DNS, destinos de redirecionamento e decisões de segurança esperadas. Ela transforma afirmações vagas como «bloqueamos IPs privados» em testes repetíveis que detectam erros de parser, formatos alternativos de endereço e mudanças no comportamento das bibliotecas.

Ferramentas de agente somente leitura precisam de proteção contra SSRF?

Sim, se a ferramenta anexar um segredo, certificado de cliente, solicitação assinada ou qualquer credencial com autoridade além do agente. Uma solicitação que apenas lê documentação pública tem um impacto menor, mas ainda deve evitar o acesso não planejado a serviços locais.

O que deve acontecer quando o DNS retorna endereços públicos e privados?

Falhe de forma segura. Se o resolvedor retornar uma mistura de endereços permitidos e bloqueados, um cliente HTTP comum poderá escolher o endereço bloqueado por causa da ordem dos endereços ou da preferência por IPv6. Uma ferramenta que injeta credenciais deve rejeitar respostas mistas, a menos que controle o endereço aprovado ao qual se conecta.

Bloquear os intervalos RFC 1918 basta para se defender contra SSRF?

Não. Intervalos privados são apenas uma categoria. Loopback, endereços link-local, espaço de NAT de operadoras, intervalos de documentação, endereços não especificados, multicast, valores IPv4 mapeados em IPv6, redirecionamentos e mudanças no DNS também precisam de tratamento deliberado.

Como provar que uma ferramenta de agente nunca enviou uma credencial para um destino bloqueado?

Use um servidor de captura inofensivo que registre o peer remoto, o caminho da solicitação, o cabeçalho Host e se um cabeçalho Authorization chegou. Alimente-o com um token de teste descartável, sem acesso fora do ambiente de testes. Um bom relatório de falha informa qual destino recebeu o token, não apenas que uma solicitação retornou 200.

Sallyport

O Sallyport executa chamadas de API e comandos SSH pelo seu agente de IA. As chaves ficam em um cofre local no seu Mac; você aprova cada execução e toda ação vai para um registro selado.

© 2026 Sallyport · Código aberto sob Apache-2.0 · Oleg Sotnikov