
Un fuzzer proof-of-concept per plugin WordPress
Un fuzzer di plugin WordPress proof-of-concept che ha portato alla scoperta di più di 300 vulnerabilità in plugin WordPress installati su quasi 30 milioni di siti.
La tecnica utilizzata è descritta in https://kazet.cc/2022/02/03/fuzzing-wordpress-plugins.html
Se vuoi continuare la ricerca, inizia con plugin meno popolari - se un plugin ha raggiunto almeno 10k installazioni attive tra ottobre 2021 e gennaio 2024, molto probabilmente ho già esaminato i report del fuzzer (e la maggior parte dell'attenzione è stata data ai plugin con almeno 20k installazioni attive). Poiché c'è molta casualità nel funzionamento del fuzzer, alcune vulnerabilità in questi plugin rimangono non scoperte - ma in numero minore.
I report del fuzzer contengono molti falsi positivi - la maggior parte non indica una vulnerabilità. Dopo aver visto un report, analizza prima se il comportamento che stai osservando è effettivamente una vulnerabilità o un falso positivo. Non inviare spam a WPScan/fornitori con report grezzi del fuzzer - fornisci invece un exploit PoC.
Per ovvie ragioni, gli esempi conterranno solo vulnerabilità già risolte.
Supponiamo che tu stia eseguendo il fuzzing di responsive-vector-maps versione 6.4.0:
./bin/fuzz_object plugin responsive-vector-maps --version 6.4.0
(per eseguire il fuzzing dell'ultima versione, ometti semplicemente --version).
Dopo che il fuzzing è completato (che richiederebbe 10-30 minuti per questo plugin) puoi eseguire:
./bin/print_findings data/object_fuzz_results/
Vedrai, tra gli altri:
.
Ciò significa che il fuzzer ha rilevato l'esecuzione di fopen() su un payload noto.
La maggior parte dei payload contiene la parola GARLIC per facilitare il rilevamento automatico nell'output. Puoi vederli o configurarli in docker_image/magic_payloads.php.
Poi, puoi esaminare il codice sorgente e vedere che effettivamente l'endpoint wp_ajax_rvm_import_markers utilizza il contenuto del file per generare l'output, permettendoti così di leggere file arbitrari sul server: CVE-2021-24947.
Quello che vedi in bianco è un crash considerato interessante (puoi modificarli o aggiungerne di nuovi in crash_detectors.py). Il verde è il contesto. In blu vedi il nome del file di report (con il nome del plugin), la popolarità del plugin e il nome dell'endpoint (qui: il nome dell'azione ajax).
I dati in giallo sono quali payload sono stati iniettati in quali variabili.
Supponiamo che tu stia eseguendo il fuzzing di page-builder-add versione 1.4.9.4:
./bin/fuzz_object plugin page-builder-add --version 1.4.9.4
Dopo aver stampato i risultati, vedrai un payload noto restituito:
.
Puoi quindi testare manualmente se effettivamente questo punto (ricorda: in blu hai il nome dell'endpoint, qui: il nome della pagina del menu) è vulnerabile a XSS. In questo caso lo è: CVE-2021-25067.
./bin/fuzz_object plugin duplicate-page-or-post --version 1.4.6
Dopo aver stampato i risultati, vedrai update_option essere chiamato:
.
L'analisi del codice dell'endpoint ti dirà che questo porta effettivamente a una vulnerabilità di XSS persistente: CVE-2021-25075.
Sfortunatamente, per la maggior parte dei plugin il fuzzer non trova crash interessanti, e per il resto, la maggior parte dei report sono falsi positivi. Per esempio, se vedi:
Call: wp_mail arguments={'to': '[email protected]', 'subject': '[Plugin contact] - http://GARLICGARLICGARLIC.example.com'}
Questo può significare che wp_mail è effettivamente chiamato, ma non controlli il destinatario e la maggior parte dell'oggetto. Se vuoi esserne certo, guarda il codice sorgente del plugin.
__GARLIC_ACCESSED__ _FILES[files] __ENDGARLIC__ - significa che è stato rilevato l'accesso a un file caricato. Non vengono effettuati ulteriori controlli al momento - per verificare se si tratta di una vulnerabilità, guarda il codice.$_GET['page'] se vuoi che venga visualizzata una particolare pagina del menu.La prima esecuzione del fuzzing o dei test potrebbe richiedere circa un'ora, perché dobbiamo costruire l'immagine Docker con PHP e WordPress strumentati.
./bin/fuzz_object plugin PLUGIN_SLUG
./bin/fuzz_object theme THEME_SLUG
Puoi anche installare un plugin da un file zip locale:
./bin/fuzz_object plugin PLUGIN_FILE_NAME.zip
Per stampare ciò che il fuzzer ha trovato, usa:
./bin/print_findings data/object_fuzz_results/
Per eseguire i test, usa:
./bin/test
Attenzione: i test richiedono molto tempo (più di un'ora) e poiché verificano se il fuzzer troverebbe vulnerabilità, falliscono con una certa probabilità.
wpgarlic utilizza pre-commit per eseguire i linter e formattare il codice.
pre-commit viene eseguito in CI per verificare che il codice sia formattato correttamente.
Per eseguirlo localmente, usa:
pre-commit run --all-files
Per configurare pre-commit in modo che venga eseguito prima di ogni commit, usa:
pre-commit install
Puoi avviare un ambiente di test con un solo plugin installato usando:
./bin/manual_testing PLUGIN_SLUG|PLUGIN_PATH.zip [version]
Puoi installare un plugin usando il suo slug o da un file zip locale.
Ascolterà su http://127.0.0.1:8001/
Ci saranno due utenti di test nel database:
Questo strumento è un proof of concept - questa sezione contiene i punti in cui può essere migliorato per trovare più vulnerabilità.
Potresti voler modificare filtering.py -- contiene le regole che determinano se un determinato crash è importante o meno. Se le modifichi, potresti avere più falsi positivi, ma anche trovare più vulnerabilità. Ad esempio, l'unico header che considero interessante quando viene emesso è l'header Location, per rilevare vulnerabilità di Open Redirect. Questa è solo un'idea e potresti averne altre.
Un altro file che potrebbe valere la pena estendere è docker_image/patch_wordpress.sh. Descrive le chiamate a quali funzioni verranno registrate come interessanti.
Se vuoi iniettare altri payload (o modificare le probabilità con cui vengono iniettati) modifica docker_image/magic_payloads.php e docker_image/fuzz/config.py.
crash_detector.py contiene espressioni regolari che trovano crash interessanti o informazioni interessanti (es. email) esposte.
Il fuzzing delle route REST come amministratore connesso è stato disabilitato poiché portava a falsi positivi. Commenta rest_routes_admin in config.DEFAULT_ENABLED_FEATURES per cambiare questo comportamento.
Alcuni plugin necessitano di altri (es. woocommerce) come dipendenza. Durante il fuzzing di un plugin che ha una dipendenza, vogliamo eseguire il fuzzing solo del plugin scelto e saltare le azioni AJAX, le route REST e le pagine di menu della dipendenza. Vogliamo eseguire il fuzzing delle azioni/route/pagine di woocommerce solo quando abbiamo scelto woocommerce da esaminare.
L'elenco delle azioni/route/pagine delle dipendenze sono chiamate liste di blocco e sono elencate in docker_image/blocklists/. I file denominati common contengono le azioni/route/pagine di base di WordPress - non vogliamo eseguire il fuzzing anche su queste.
Per aggiornare queste liste di blocco, usa ./bin/update_blocklists.
Forse. Installa il plugin in un ambiente di test locale (ad esempio puoi usare quello descritto nella sezione Ambiente di test manuale) e analizza il bug.
Non darlo per scontato. Il fuzzer trova alcune classi di vulnerabilità, ma ha i suoi limiti.
Il fuzzer non trova nulla per la maggior parte dei plugin - lo scopo dello strumento è piuttosto quello di scansionare massivamente un gran numero di plugin WordPress, non di eseguire test completi su un singolo plugin.
È possibile. Il fuzzer sceglie i payload in modo casuale e introduce casualità in altri punti (ad esempio come l'operatore == dovrebbe comportarsi nei casi descritti in https://kazet.cc/2022/02/03/fuzzing-wordpress-plugins.html#patched-equality).
Apri un ticket su Github o inviami un'email: [email protected].