2 pontos por GN⁺ 15 시간 전 | 1 comentários | Compartilhar no WhatsApp
  • O GPT5.6 Sol Ultra analisou a versão estável mais recente do WordPress e, em cerca de 10 horas, montou uma cadeia de ataque que vai de uma injeção de SQL pré-autenticação até a criação de uma conta de administrador e execução remota de código (RCE)
  • O ponto de partida foi uma inconsistência de índices de arrays na Batch API, disponível desde o WordPress 5.6, combinando requisições Batch recursivas para contornar a restrição de GET e a validação de parâmetros
  • Após causar uma injeção UNION com a string não validada author_exclude, a cadeia coloca um post manipulado no cache em memória e explora em sequência cache de oEmbed, changeset, referência circular e hooks
  • Com user_id: 1 em customize_changeset, obtém temporariamente privilégios de administrador e reexecuta a requisição Batch via hook parse_request para criar um novo administrador; depois, faz upload de um ZIP de plugin com backdoor para chegar à execução de código
  • O custo proporcional a 50% do uso semanal de uma assinatura mensal de US$ 200 foi de cerca de US$ 25, e cresce a possibilidade de o papel humano migrar para a direção de pesquisa em alto nível, como escolher o produto e a superfície de ataque e ajustar prompts

Processo de descoberta e condições do experimento

  • Um prompt que a OpenAI disse ter usado para resolver a conjectura Cycle Double Cover foi adaptado para pesquisa de segurança e fornecido ao GPT5.6 Sol Ultra
  • A versão estável mais recente do WordPress foi clonada em main/, o diretório .git foi removido, e um diretório vazio third_party/ foi preparado para permitir investigar código de dependências
  • O prompt instruía o uso de até 4 agentes em paralelo para manter diversos caminhos de ataque por pelo menos 6 horas
    • Explorando parsing de entrada, conjuntos de caracteres, uploads de arquivo, tratamento de erros, caminhos internos, serialização, cache, condições de corrida, criptografia, tipos, atribuição em massa etc.
    • Registrando famílias de abordagens e redistribuindo agentes para áreas menos exploradas quando eles se concentrassem demais em uma estratégia específica
    • Fazendo um agente adversarial revalidar bugs concretos e reabrindo caminhos fracassados quando surgissem novos mecanismos
  • A busca foi limitada a encontrar novas vulnerabilidades no próprio código-fonte, sem usar histórico de mudanças, diferenças em relação a versões corrigidas ou pistas da internet
  • Para evitar configurações irreais ou pré-condições que um atacante não poderia satisfazer, o objetivo foi definido como “RCE pré-autenticação em uma implantação de produção comum usando MySQL”
  • Após cerca de 6 horas, o modelo encontrou uma injeção de SQL pré-autenticação e a reproduziu em um servidor WordPress remoto padrão, extraindo o e-mail do administrador em poucos minutos
  • Ao solicitar a escalada para RCE, cerca de 4 horas depois ele completou uma cadeia que sobe de uma injeção de SQL somente leitura para privilégios de administrador, sem quebra de senha nem cálculo offline
  • O tempo total de trabalho foi de pouco mais de 10 horas, consumindo 50% do uso semanal. O custo proporcional da assinatura mensal de US$ 200 foi de cerca de US$ 25
  • Antes da divulgação, foi dado tempo aos operadores durante o fim de semana para atualizar o WordPress; nesse intervalo, Calif e Hacktron reproduziram independentemente a cadeia completa antes de outros PoCs no GitHub
  • Instâncias em operação podem verificar se estão vulneráveis em wp2shell.com

Inconsistência de validação na Batch API

  • A Batch API, introduzida no WordPress 5.6, processa várias requisições virtuais de API em uma única requisição. O endpoint em si pode ser acessado sem autenticação, mas as credenciais são repassadas a cada sub-requisição
  • Uma requisição REST comum é processada na seguinte ordem
    • Verifica valores obrigatórios e validade com has_valid_params()
    • Sanitiza valores com sanitize_params()
    • Executa o callback de permissões
    • Executa o callback do endpoint
  • Para desempenho, a Batch API separa validação e execução em dois loops
    • No primeiro loop, valida e sanitiza todas as requisições
    • No segundo loop, verifica os resultados de validação e executa os callbacks de permissões e de endpoint
  • A implementação pressupõe que os mesmos índices em $matches, resultado do casamento de rotas, e $validation, resultado da validação, correspondem entre si
  • Quando uma requisição inválida entra no ramo is_wp_error($single_request), um item é adicionado a $validation, mas não a $matches por causa do continue
    • Depois disso, todos os itens de $matches ficam deslocados em uma posição
    • É possível validar os parâmetros de uma requisição com as regras de outra e depois executá-los em um handler de endpoint que originalmente não deveria recebê-los
  • Essa inconsistência de índices permite aplicar a um endpoint com suporte a Batch o resultado de validação de outro endpoint que não sanitiza os parâmetros

Injeção de SQL em author__not_in

  • GET /wp/v2/posts usa a variável interna de consulta author__not_in para excluir autores específicos dos resultados
  • Se o valor for um array, absint é aplicado a cada elemento para transformá-lo em inteiro; se for um valor escalar, ele é inserido como está após implode na cláusula NOT IN do SQL
  • Em chamadas normais, o problema não aparece porque o parâmetro público author_exclude precisa ser um array de inteiros
  • Usando a inconsistência de índices da Batch, é possível validar uma string author_exclude pelas regras de DELETE /wp/v2/posts/1, que não a reconhecem, e então entregá-la a GET /wp/v2/posts
  • A restrição da Batch API que não permite sub-requisições GET também é contornada com chamadas Batch recursivas
    • Na Batch externa, provoca-se a inconsistência de índices para pular a validação do method da requisição interna
    • Na Batch interna, provoca-se de novo a inconsistência de índices para contornar a validação de author_exclude
  • Ao inserir um valor como 0) OR 1=1 --, todas as linhas de posts são retornadas, confirmando a injeção
  • Depois, uma injeção baseada em UNION permite criar linhas no formato de wp_posts e vazar valores arbitrários do banco de dados
  • Senhas, tokens de redefinição, chaves de API etc. são armazenados com hash no banco de dados; portanto, se a senha do administrador não for fraca, o vazamento de dados por si só não leva à tomada da conta

Manipulação do cache de posts dentro da requisição

  • O WordPress armazena objetos WP_Post referenciados repetidamente dentro de uma requisição em um cache em memória para reduzir idas ao banco de dados
  • Ao retornar uma linha falsa de post via injeção UNION, o atacante pode colocar no cache muitos campos definidos por ele, como ID do post, tipo, status, relação de pai e conteúdo
  • Como a resposta da API também pós-processa o conteúdo do post, um conteúdo manipulado pode executar caminhos de código adicionais
  • Esse cache desaparece ao fim da requisição, e o post falso não existe no banco de dados; portanto, a manipulação do cache sozinha não garante persistência entre requisições

Criação de linhas no banco usando cache de oEmbed

  • O recurso de embeds do WordPress insere conteúdo remoto compatível por meio da sintaxe [embed]...[/embed] no corpo de posts
  • Para não enviar requisições HTTP toda vez, o resultado é armazenado no banco de dados como um post do tipo oembed_cache em wp_posts
  • Ao embutir um post local do WordPress por caminho relativo, a requisição HTTP é omitida, e não há verificação de que o ID do post referenciado realmente exista
  • Mesmo ao embutir um post local inexistente como /?p=10, uma linha oembed_cache para esses dados pode ser criada
  • Se a linha criada for consultada novamente via injeção de SQL enquanto o tipo de post em memória é manipulado para post etc., as representações no banco de dados e no cache ficam diferentes
  • Ao reconciliar essas duas representações, o WordPress chama wp_update_post() e, com exceção de ID e post_content explicitamente especificados, prefere os valores em memória criados pelo atacante
  • Com isso, uma linha oembed_cache pode ser convertida em post comum, mas nessa chamada o post_content é sobrescrito pelo resultado do embed, então o atacante não controla também o corpo

Privilégios temporários de administrador via customize_changeset

  • Rascunhos de personalização de tema são armazenados em wp_posts como posts especiais do tipo customize_changeset
  • O post_content contém JSON com valores alterados por chave de configuração, tipos e o ID do usuário que realizou a alteração
  • Ao aplicar um changeset, o WordPress lê o user_id de cada item e altera temporariamente o usuário atual com wp_set_current_user()
  • Se um atacante aplicar um changeset com user_id: 1, pode usar momentaneamente a identidade de administrador mesmo durante uma requisição anônima
  • Como a chamada de reconciliação do oEmbed mencionada acima sobrescreve post_content, é necessário um caminho separado de chamada a wp_update_post() para preservar o JSON malicioso do changeset

Preservação do conteúdo usando ciclo no pai do post

  • Posts do WordPress podem ter um único pai, mas uma estrutura circular em que o próprio post ou um descendente seja definido como pai não é permitida
  • O filtro wp_insert_post_parent percorre a hierarquia de pais para verificar ciclos e, ao encontrar um, chama wp_update_post() para alterar o post_parent daquele post para 0
  • Essa segunda chamada especifica apenas ID e post_parent, sem sobrescrever post_content
  • Ao usar a injeção de SQL para disfarçar um post em memória como um customize_changeset cujo pai é ele mesmo, o processo de recuperação do ciclo grava no banco de dados o JSON malicioso de changeset especificado pelo atacante
  • Ao criar um changeset com data passada e status future, o WordPress o aplica e, por causa de user_id: 1, executa as alterações especificadas com privilégios de administrador
  • Os privilégios de administrador se mantêm apenas durante a operação do changeset e voltam a ser de convidado após a conclusão

Reexecução de toda a requisição por hook dinâmico

  • Hooks do WordPress se dividem em ações (actions) e filtros (filters), permitindo que plugins intervenham em vários pontos do ciclo de vida, como login, publicação e registro de scripts
  • Quando o status de um post muda, o WordPress executa uma ação dinâmica no formato "{$new_status}_{$post->post_type}"
    • Para um post normal, o nome seria algo como publish_post
    • Um post falso em memória pode ter status e tipo arbitrários, permitindo construir o nome de uma ação desejada que contenha ao menos um sublinhado
  • Os argumentos do hook se limitam ao ID do post e ao objeto WP_Post definidos pelo atacante, então é difícil invocar diretamente uma ação arbitrária de forma útil
  • A cadeia de ataque manipula o status para parse e o tipo para request, chamando o hook parse_request
  • Como parse_request é um hook executado no início do ciclo de vida da requisição, chamá-lo de novo faz com que a requisição original da Batch API seja reprocessada desde o início
  • O reprocessamento ocorre enquanto a identidade temporária de administrador definida pelo changeset ainda está ativa, de modo que requisições exclusivas de administrador que falharam na primeira execução passam a ter sucesso na segunda

Cadeia RCE concluída com duas requisições

  • O exploit final usa duas requisições HTTP e atribui aos posts falsos IDs grandes o bastante para não colidirem com posts reais
  • Primeira requisição: preparar linhas persistentes

    • Retorna via injeção de SQL um post falso com três embeds locais, criando 3 linhas oembed_cache correspondentes a O, C e D
    • Os três embeds apontam para o mesmo post S, mas usam query strings diferentes para gerar hashes distintos de cache oEmbed
  • Segunda requisição: montar seis posts

    • Constrói os seis posts falsos seguintes no cache em memória
    • O: cache antigo com status/tipo publish/oembed_cache e pai C
    • C: status/tipo future/customize_changeset, tendo a si mesmo como pai e contendo JSON malicioso de changeset
    • P: draft/page com pai D
    • D: status/tipo parse/request, tendo a si mesmo como pai
    • S: publish/post que fornece os dados do embed
    • T: publish/post contendo o embed externo
    • O embed de T consulta O e, por causa do horário de modificação antigo, força a atualização do cache de S
    • Quando a atualização de O detecta o ciclo no pai C, ela altera o pai de C para 0 e grava no banco o customize_changeset em memória com o JSON malicioso
    • O changeset future com data passada é aplicado, publicando P com a identidade de administrador de user_id: 1
    • A atualização de P encontra o ciclo no pai D, grava D e, com o status e tipo manipulados, chama a ação parse_request
    • A requisição Batch já inclui desde o início uma requisição para criar um novo administrador
    • No primeiro processamento, ela falha por estar com privilégios de convidado
    • Ao ser reexecutada por parse_request, a permissão temporária de administrador ainda está ativa e ela tem sucesso
    • Após fazer login com a nova conta de administrador, o upload de um ZIP de plugin com backdoor leva finalmente à execução remota de código

Mudança de papéis na pesquisa de segurança com IA

  • As etapas especialmente criativas da cadeia completa foram contornar a restrição de GET com chamadas Batch recursivas, combinar cache e changeset para obter privilégios de administrador, e chamar parse_request com posts falsos para reexecutar a requisição
  • Embora não seja possível afirmar uma superioridade geral, a avaliação é que teria sido impossível para um pesquisador de segurança descobrir e completar a mesma cadeia em 10 horas sem IA
  • Mesmo que o bug original da Batch fosse fornecido previamente, há dúvidas se seria possível construir uma RCE nesse prazo
  • A conclusão é que o GPT5.6 Sol Ultra avançou muito em relação ao GPT5.5 na capacidade de encontrar vários gadgets de código separados e conectá-los em uma única cadeia
  • À medida que o modelo assume mais do desenvolvimento técnico de exploits, as pessoas tendem a se concentrar em decidir o produto e a superfície de ataque a investigar, o tempo a investir, o rumo da pesquisa e em corrigir o modelo quando ele se desvia
  • Essa competência de meta-pesquisa ainda não é bem tratada pela IA e tende a se tornar mais importante conforme aumenta a capacidade técnica dos modelos

1 comentários

 
Comentários do Hacker News
  • Não há base para afirmar que US$ 500 mil foram ou seriam pagos por esse tipo de exploit. Como o texto diz que o prompt foi ajustado cuidadosamente como se fosse uma bíblia, talvez fosse melhor vender esse prompt por US$ 500 mil
    O autor trabalha na https://www.assetnote.io/, que oferece um produto de IA para varredura automática

    • Acho que ele está se referindo a https://www.crowdfense.com/exploit-acquisition-program/. A Zerodium também ofereceu até US$ 300 mil em 2021: https://www.securityweek.com/sites/default/files/images/Zero...
      Esses brokers geralmente não pagam uma quantia enorme de uma vez; eles vendem o acesso a atores estatais e vão pagando em parcelas enquanto o bug não é corrigido. Como a estrutura existe para evitar revenda ou esgotamento precoce, provavelmente quase ninguém poderá confirmar se alguém realmente recebeu o valor total por uma vulnerabilidade parecida
    • Removeram US$ 500 mil do título
    • A interseção entre pessoas capazes de encontrar esse tipo de vulnerabilidade antes dos LLMs, dispostas a vendê-la a brokers, e ao mesmo tempo burras o bastante para colocar uma enorme placa de “por favor, me prendam” nas redes sociais, deve ser minúscula
      O exemplo mais próximo são adolescentes da Flórida que colocaram malware em jogos da Steam para roubar contas e acabaram pegos. Seriam pegos de qualquer forma, mas teria demorado muito mais se não tivessem se exibido nas redes sociais
    • Só porque alguém comprou um Macintosh que custava US$ 5.000 quando era novo por US$ 25 num mercado de usados, isso não significa que a mesma comparação de valor se aplique
    • “Ajustar como se fosse uma bíblia” quer dizer que não se corrige nada, mesmo quando é claramente contraditório ou eticamente depravado?
  • Olhando https://github.com/WordPress/WordPress/commit/3a640e1c5e39aa..., vemos injeção de SQL por concatenação de strings em 2026

    • O conteúdo mais grave está em https://developer.wordpress.org/plugins/creating-tables-with...
      Em vez de executar SQL diretamente, mandam usar dbDelta, mas exigem regras de formatação absurdamente rígidas, como colocar cada campo em uma linha, usar dois espaços entre PRIMARY KEY e escrever KEY em vez de INDEX. Não se pode usar aspas nem crases nos nomes dos campos, os tipos devem ficar em minúsculas, as palavras-chave SQL em maiúsculas, e todos os parâmetros de tamanho precisam ser especificados
    • A base de código do WordPress é constrangedora. PHP virou uma ótima linguagem, mas o WordPress a usa de um jeito terrível e ainda se recusa a melhorar
    • A forma de correção também é horrível. Fico me perguntando se o WordPress ainda monta queries SQL com simples concatenação de strings e sprintf
    • Vi um ataque usando esse exploit neste fim de semana em um site em produção
      Havia payloads no POST e no GET no formato /wp/v2/widgets?author_exclude=1%29+AND+1%3D0+UNION+ALL+SELECT...
    • No perfil está escrito Principal Software Engineer @ Bluehost, WordPress Core Committer; com um código desses, a palavra “principal” soa estranha mesmo
  • Já cansei desse estilo de escrita FOMO. Não foi descoberto só com US$ 25; havia conhecimento especializado da área sobre onde olhar e como explorar, além de anos de material acumulado
    Precisamos parar de espalhar essa narrativa de aposta e a ilusão de que todo mundo está perdendo a oportunidade

    • Esse tipo de texto faz mal por parecer uma versão jornalística do Instagram, em que só se publica o momento de sucesso e a vida toda parece incrível. Nesse cálculo de US$ 25 faltam não só anos de experiência, mas também inúmeras tentativas fracassadas
    • O cálculo de custo também não está correto. US$ 25 foi apenas o custo dos tokens subsidiados por um plano de assinatura
    • Se tivesse feito isso pessoalmente, não teria divulgado como “fiz de graça”; mas, só porque gastou US$ 25 em tokens, é estranho que a forma de enxergar o resultado mude
  • A parte surpreendente é o alto preço de uma vulnerabilidade já conhecida, e isso talvez nem seja verdade. O WordPress é frequentemente chamado de shell root remoto com funcionalidade de blog

    • Ainda é difícil entender por que um blog não seria suficientemente atendido por páginas estáticas. Especialmente quando a maioria dos problemas do WordPress é “resolvida” adicionando cache
      Entendo que, para usuários comuns, é mais fácil orientar arrastar e soltar do que mandar fazer commit num repositório GitHub e compilar com Hugo. Mas, do ponto de vista de segurança, a estrutura fica só esperando surgir uma vulnerabilidade no core ou em um dos milhares de plugins para abrir uma execução remota de código como serviço
    • Para saber se é verdade, seria preciso fazer threat intelligence e se infiltrar em grupos de Telegram onde esses brokers atuam, algo que o autor provavelmente não fez. Ele pode ter confundido uma vulnerabilidade comum com um zero-day
    • O WordPress é um dos alvos que mais receberam hardening de segurança de todos os tempos. Como o código antigo quase não mudou em décadas, também dá para dizer que a maioria dos bugs já foi encontrada e corrigida
    • Também há estatísticas de que quase 50% dos sites da internet usam WordPress, então não é totalmente irreal que um zero-day de execução remota de código sem autenticação não divulgado valha US$ 500 mil
  • Texto interessante, e a descoberta e divulgação de exploits baseadas em LLM são uma preocupação real. Já consegui fazer um modelo gerar relativamente rápido código de escape de contêiner a partir de uma vulnerabilidade de escalonamento local de privilégio no Linux
    Ainda assim, surpreende que o GPT-5.6 não tenha bloqueado o prompt por causa dos guardrails. O GPT-5.5 ou superior tende a evitar trabalho ofensivo de segurança, como Opus 4.7+/Fable, então parece possível que o autor tenha obtido da OpenAI uma aprovação de cibersegurança com guardrails relaxados

  • Ferramentas de teste estático de segurança de aplicações (SAST) não baseadas em IA, de antes de 2020, também detectariam muitas dessas injeções de SQL, e isso ao menos deveria ter sido encontrado em revisão de código. Fico me perguntando se o WordPress não usa revisão de código nem SAST

    • Como este ataque exige a combinação de várias vulnerabilidades, provavelmente não teria sido detectado só com essas ferramentas
  • Um dos meus sites foi invadido por causa dessa vulnerabilidade, mas felizmente era um lugar sem usuários
    O invasor criou duas contas de administrador no banco de dados e instalou um web shell de execução remota de comandos em wp-content/plugins/wp-core, chamado wp-core-[12 caracteres aleatórios].php. Em mu-plugins, deixou o backdoor firewall.php, que cria um administrador com GET ?sergei, e também adicionou o backdoor cache-seo-helper.php; além disso, usou fixer.php para alterar o número da versão do WordPress para que parecesse uma versão corrigida. No fim, decidi abandonar o uso do WordPress

  • No fim do texto, começou a se referir às postagens com nomes estranhos, o que dificultou o entendimento. Fiquei me perguntando por que um ID foi feito como O e outro como 0, e por que usou um único caractere e algo aparentemente aleatório como OCPDST, em vez de EMBED_01 ou ABCDEF

    • Tudo isso são marcadores de posição, e o significado está explicado no texto. O significa publish/oembed_cache, C significa future/customize_changeset, P significa draft/page, D significa parse/request, S significa publish/post que fornece os dados de embed, e T significa publish/post que contém o embed externo
  • Fico me perguntando se estão assumindo que as pessoas dispostas a pagar 500 mil dólares não têm capacidade de usar o GPT-5.6 diretamente

    • Se for esse o caso, vale pensar por que análises como essa não surgiram antes. Ainda é preciso conhecimento especializado para revisar a saída de um LLM e transformá-la em uma prova de conceito realmente válida
      Eu também encontro vulnerabilidades de segurança com LLMs, mas não dá para simplesmente enviar o resultado como está e encerrar por aí; embora muita gente tente fazer isso
    • Continuam saindo notícias de que autoridades obtiveram registros de LLMs em nuvem e os usaram como prova em processos criminais; então, se for um criminoso profissional, é bem provável que lave suas atividades por meio de intermediários antiéticos, mas legais
    • Quem ganha dinheiro e quem escreve o melhor código não são necessariamente a mesma pessoa. Elon Musk também não escreveu o código dos foguetes pessoalmente; ele contratou quem escrevesse
  • Se o GPT-5.6 Sol é sobre-humano não é uma pergunta simples de sim ou não. Os computadores já superam os humanos no xadrez há décadas e, por este texto, agora parecem ter superado os humanos também em compreensão de código

    • Em cálculo aritmético, eles superam os humanos há muito mais tempo