Automatizando a descoberta de Plugins do WordPress
Já faz um tempo que tenho utilizado a ferramenta Nuclei do ProjectDiscovery para automatizar o processo de inventário de ativos e identificação de componentes vulneráveis em aplicações.
O WordPress é sem dúvida o CMS (Content Management System) mais popular na Internet, ocupando uma fatia de nada mais que 65% (para se ter uma ideia o 2º colocado tem uma participação de apenas 6,6%).
O Nuclei funciona por meio de templates que instruem a ferramenta quais ações realizar sobre o alvo. Esta ações podem ser desde uma simples identificação de um software até a exploração de uma vulnerabilidade em várias etapas.
Um dos templates disponíveis no Nuclei fazia a identificação dos plugins presentes em uma instalação do WordPress por força-bruta, passando uma relação de aproximadamente 90.000 palavras. Essa abordagem não me pareceia muito eficiente e, dependendo do número de URLs testadas, o processo se demonstrava bastante oneroso em termos de recursos de processamento além de inundar o alvo com requisições desnecessárias.
Pensando nisso, desenvolvi um script em Python que acessa o site do WordPress e faz uma varredura pelos 200 plugins mais populares e, em seguida, acessa o respectivo repositório SVN do plugin para recuperar o número da última versão disponível e, finalmente, gera automaticamente um template que, além de identificar o plugin, verifica se está na versão mais recente, oferecendo uma informação bastante útil sobre a possível presença de componentes desatualizados.
Esta é a aparência do template gerado, neste caso, para o plugin contact-form-7.
id: wordpress-contact-form-7
info:
name: Contact Form 7 Detection
author: ricardomaia
severity: info
reference:
- https://wordpress.org/plugins/contact-form-7/
metadata:
plugin_namespace: contact-form-7
wpscan: https://wpscan.com/plugin/contact-form-7
tags: tech,wordpress,wp-plugin,top-100,top-200
requests:
- method: GET
redirects: true
max-redirects: 2
path:
- "{{BaseURL}}/wp-content/plugins/contact-form-7/readme.txt"
payloads:
last_version: helpers/wordpress/plugins/contact-form-7.txt
extractors:
- type: regex
part: body
internal: true
name: internal_detected_version
group: 1
regex:
- '(?i)Stable.tag:\s?([\w.]+)'
- type: regex
part: body
name: detected_version
group: 1
regex:
- '(?i)Stable.tag:\s?([\w.]+)'
matchers-condition: or
matchers:
- type: dsl
name: "outdated_version"
dsl:
- compare_versions(internal_detected_version, concat("< ", last_version))
- type: regex
part: body
regex:
- '(?i)Stable.tag:\s?([\w.]+)'
Como se pode notar o template utiliza como payload
o conteúdo de um arquivo que contêm o número da versão do componente para então compará-lo à versão detectada no arquivo readme.txt
.
O template quando executado gera uma saída como na figura a seguir:
Observe a diferença entre as variáveis outdate_version
e detected_version
que são exibidas conforme o caso.
Para manter os templates atualizados faço uso do GitHub Actions para executar o script diariamente.
Na data de hoje (23/12/2022) meu PR (Pull Request) foi aceito e incluído no repositório do projeto. 🎉🎉🎉
TAGS: #infosec #WordPress #Nuclei