Automatizando a descoberta de Plugins do WordPress

Automatizando a descoberta de Plugins do WordPress

Templates Nuclei para inventariar plugins mais populares

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:

image

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. 🎉🎉🎉