
Um fuzzer de plugins WordPress como prova de conceito
Um fuzzer de plugins WordPress de prova de conceito que levou à descoberta de mais de 300 vulnerabilidades em plugins WordPress instalados em quase 30 milhões de sites.
A técnica utilizada está descrita em https://kazet.cc/2022/02/03/fuzzing-wordpress-plugins.html
Se quiser continuar a investigação, comece com plugins menos populares - se um plugin alcançou pelo menos 10 mil instalações ativas entre outubro de 2021 e janeiro de 2024, eu provavelmente já vi os relatórios do fuzzer (e a maior parte do foco foi colocada em plugins com pelo menos 20 mil instalações ativas). Como há muita aleatoriedade na forma como o fuzzer funciona, algumas vulnerabilidades nestes plugins permanecem por descobrir - mas são menos.
Os relatórios do fuzzer contêm muitos falsos positivos - a maioria deles não indica uma vulnerabilidade. Depois de ver um relatório, analise primeiro se o comportamento que está a observar é de facto uma vulnerabilidade ou um falso positivo. Não spammeie o WPScan/fornecedores com relatórios brutos do fuzzer - em vez disso, forneça um PoC de exploit.
Por razões óbvias, os exemplos conterão apenas vulnerabilidades que já foram corrigidas.
Vamos supor que está a fazer fuzzing ao responsive-vector-maps na versão 6.4.0:
./bin/fuzz_object plugin responsive-vector-maps --version 6.4.0
(para fazer fuzzing à versão mais recente, basta omitir --version).
Depois de o fuzzing terminar (o que demorará 10-30 minutos para este plugin) pode executar:
./bin/print_findings data/object_fuzz_results/
Verá, entre outros:
.
Isso significa que o fuzzer detetou a execução de fopen() num payload conhecido.
A maioria dos payloads contém a palavra GARLIC para facilitar a deteção automática
na saída. Pode vê-los ou configurá-los em docker_image/magic_payloads.php.
Depois, pode explorar o código fonte e ver que de facto o endpoint wp_ajax_rvm_import_markers
usa o conteúdo do ficheiro para renderizar a saída, permitindo-lhe ler ficheiros arbitrários
no servidor: CVE-2021-24947.
O que vê a branco é um crash considerado interessante (pode modificá-los ou adicionar novos
em crash_detectors.py). A verde está o contexto. A azul vê o nome do ficheiro de relatório
(com o nome do plugin), a popularidade do plugin e o nome do endpoint (aqui: o nome da ação ajax).
Os dados a amarelo são os payloads que foram injetados em que variáveis.
Vamos supor que está a fazer fuzzing ao page-builder-add na versão 1.4.9.4:
./bin/fuzz_object plugin page-builder-add --version 1.4.9.4
Depois de imprimir os resultados, verá um payload conhecido ecoado de volta:
.
Pode então testar manualmente se este local (lembre-se: a azul tem o nome do endpoint, aqui: o nome da página do menu) é vulnerável a XSS. Neste caso, é: CVE-2021-25067.
./bin/fuzz_object plugin duplicate-page-or-post --version 1.4.6
Depois de imprimir os resultados, verá update_option a ser chamado:
.
A análise do código do endpoint dir-lhe-á que isto leva de facto a uma vulnerabilidade de XSS armazenado: CVE-2021-25075.
Infelizmente, para a maioria dos plugins o fuzzer não encontra crashes interessantes, e para o resto, a maioria dos relatórios são falsos positivos. Por exemplo, se vir:
Call: wp_mail arguments={'to': '[email protected]', 'subject': '[Plugin contact] - http://GARLICGARLICGARLIC.example.com'}
Isto pode significar que wp_mail é de facto chamado, mas não controla o destinatário
e a maior parte do assunto. Se quiser ter a certeza, veja o código fonte do plugin.
__GARLIC_ACCESSED__ _FILES[files] __ENDGARLIC__ - isso significa que foi detetado
o acesso a um ficheiro carregado. Atualmente não são feitas mais verificações - para verificar se isto é
uma vulnerabilidade, veja o código.$_GET['page'] se quiser que uma página de menu específica seja exibida.A primeira execução do fuzzing ou dos testes pode demorar cerca de uma hora, porque precisamos de construir a imagem Docker com PHP e WordPress instrumentados.
./bin/fuzz_object plugin PLUGIN_SLUG
./bin/fuzz_object theme THEME_SLUG
Também pode instalar um plugin a partir de um ficheiro zip local:
./bin/fuzz_object plugin NOME_DO_FICHEIRO_PLUGIN.zip
Para imprimir o que o fuzzer encontrou, use:
./bin/print_findings data/object_fuzz_results/
Para executar os testes, use:
./bin/test
Aviso: os testes demoram muito tempo (mais de uma hora) e, como verificam se o fuzzer encontraria vulnerabilidades, falham com alguma probabilidade.
O wpgarlic usa pre-commit para executar linters e formatar o código.
O pre-commit é executado no CI para verificar se o código está formatado corretamente.
Para executá-lo localmente, use:
pre-commit run --all-files
Para configurar o pre-commit de modo a que seja executado antes de cada commit, use:
pre-commit install
Pode iniciar um ambiente de teste com apenas um plugin instalado usando:
./bin/manual_testing PLUGIN_SLUG|PLUGIN_PATH.zip [versão]
Pode instalar um plugin usando o seu slug ou a partir de um ficheiro zip local.
O ambiente estará disponível em http://127.0.0.1:8001/
Haverá dois utilizadores de teste na base de dados:
Esta ferramenta é uma prova de conceito - esta secção contém lugares onde pode ser melhorada para encontrar mais vulnerabilidades.
Pode querer editar filtering.py -- contém as regras que consideram um determinado crash
importante ou não. Se as alterar, poderá ter mais falsos positivos, mas também encontrar mais
vulnerabilidades. Por exemplo, o único cabeçalho que considero interessante quando emitido é o cabeçalho
Location, para detetar vulnerabilidades de Open Redirect. Essa é apenas uma ideia e pode ter outras.
Outro ficheiro que pode valer a pena estender é docker_image/patch_wordpress.sh. Descreve
chamadas a quais funções serão registadas como interessantes.
Se quiser injetar outros payloads (ou alterar as probabilidades com que são injetados)
edite docker_image/magic_payloads.php e docker_image/fuzz/config.py.
crash_detector.py contém expressões regulares que encontram crashes interessantes ou informações
interessantes (ex.: e-mails) a serem expostas.
O fuzzing de rotas REST como administrador autenticado foi desativado porque levava a falsos positivos.
Descomente rest_routes_admin em config.DEFAULT_ENABLED_FEATURES para alterar isso.
Alguns plugins precisam de outros (ex.: woocommerce) como dependência. Ao fazer fuzzing de um plugin que tem uma dependência, queremos fazer fuzzing apenas ao plugin escolhido e ignorar as ações AJAX, rotas REST e páginas de menu da dependência. Queremos fazer fuzzing às ações/rotas/páginas do woocommerce apenas quando escolhemos woocommerce para fuzzing.
A lista de ações/rotas/páginas de dependência são chamadas listas de bloqueio e estão listadas em docker_image/blocklists/.
Os ficheiros chamados common contêm as ações/rotas/páginas do core do WordPress - também não queremos
fazer fuzzing a estas.
Para atualizar estas listas de bloqueio, use ./bin/update_blocklists.
Talvez. Instale o plugin num ambiente de teste local (por exemplo, pode usar o descrito na secção Ambiente de teste manual) e analise o bug.
Não assuma isso. O fuzzer encontra algumas classes de vulnerabilidades, mas tem as suas limitações.
O fuzzer não encontra nada para a maioria dos plugins - o objetivo da ferramenta é antes fazer uma varredura em massa de um grande número de plugins WordPress, não realizar testes exaustivos de um único plugin.
Isto é possível. O fuzzer escolhe payloads aleatoriamente e introduz aleatoriedade noutros locais (ex.: como
o operador == deve comportar-se em casos descritos em
https://kazet.cc/2022/02/03/fuzzing-wordpress-plugins.html#patched-equality).
Abra um ticket no Github ou envie-me um e-mail: [email protected].