Wapiti goes brrr

Merci !

about:me

La tĂȘte dans l'infosec depuis 2k

Hat agnostic đŸŽ©

Accro aux CTF

Dev Python senior @CybelAngel

Et aussi la mĂ©canique auto 👹‍🔧

🔗devl00p.github.io

@devl00p

Sommaire

What is Wapiti ? (scanner don't hurt me)

Expérimentation #1

Expérimentation #2 (suspense)

Expérimentation #3 (surprise)

Conclusion

Futurs travaux

What the fuzz?

PremiÚre expérimentation

Let's hunt for false positives

(et comment le module XSS fonctionne)

Comment qu'on fait ?

Les tests unitaires ne protĂšgent que des problĂšmes connus

Pour ĂȘtre proactif il faut trouver les bugs avant les utilisateurs

Les utilisateurs trouvent des bugs en scannant des sites web

Il faut donc scanner les sites avant eux

Pour trouver ces sites il faut scanner Internet

Hack the planet!

Using Wapiti as a library

                                 def scan(url: str):
    wapiti = Wapiti(url)
    wapiti.set_bug_reporting(False)
    wapiti.set_timeout(20)
    wapiti.set_attack_options({"timeout": 20, "level": 1})
    wapiti.set_max_scan_time(2)
    wapiti.set_modules("xss,redirect")
    wapiti.set_report_generator_type("json")
    parts = urlparse(url)
    wapiti.set_output_file("/my/path/to/reports/{}_{}.json".format(parts.scheme, parts.netloc))
    wapiti.flush_session()
    wapiti.browse()
    wapiti.attack()
                            

Je nettoyais mon scanner et... (sur moins d'un mois)

Environ 18650 sites web scannés par jour

Des vulnérabilités connues retrouvées sur Wordpress, Twiki, Koha, Jenzabar, etc

Des vulnérabilités inconnues trouvées dans des CMS et autres applis web

Rapidement premier sur OBB

Seconde expérimentation

(comment j'ai joué au chat et à la souris avec des WAF)

TroisiÚme expérimentation

Il y a t-il une vulnérabilité dans le plugin ?

Ce jour heureux est plein d'allégresse

plugins.svn.wordpress.org comme liste de plugins

WP-CLI pour automatiser l'installation / suppression de plugins

docker-compose pour avoir Wordpress + MySQL + WP-CLI prĂȘts Ă  l'emploi

Simplement utiliser Wapiti aprĂšs chaque installation de plugin

Ayrton Senna

Tout le monde leur ait passĂ© dessus (mĂȘme le roflcopter)

La plupart des plugins ne sont utile qu'en zone admin

Beaucoup nécessitent une interaction humaine

👌 No problemo

Oulala

De nombreux plugins "briquent" le Wordpress

Docker est léger mais n'a pas de mécanismes de snapshots

Les uid/gid des fichiers sur le volume ne correspondent pas Ă  un utilisateur de l'OS

Solution: réinitialiser "à la dure"

Mise en place

ZeroWP: WordPress, Docker, and WP CLI
                        docker compose up -d
sudo find .srv/wordpress -type d -exec chmod 777 {} \;
docker compose run --rm wpcli core install --title="My Site" --admin_user=admin --admin_password=changeme --admin_email=me@example.com --url=http://localhost:8000/ --allow-root
docker compose run --rm wpcli term create category fun --description="This is gonna be fun"
docker compose run --rm wpcli user create bob bob@example.com --role=author
docker compose run --rm wpcli post create --post_title='Bob post' --post_content='Hello world' --meta_input='{"key1":"hi","key2":"there"}' --post_status=publish --post_category=fun --post_author=2 --tags_input=hello,world
docker compose run --rm wpcli plugin delete akismet
docker compose run --rm wpcli option update comment_whitelist 0
mysqldump -u root -pwordpress -h 127.0.0.1 wp-app > dump.sql
cp -r .srv/wordpress wordpress_backup
mkdir scans
                    

Script d'attaque

                        import os
from os.path import isfile
import subprocess

with open("plugins.txt") as fd:
    for plugin in fd:
        plugin = plugin.strip()
        if isfile(f"scans/{plugin}.json"):
            continue

        print(f"Installing {plugin}")
        try:
            subprocess.check_output(
                    ["docker-compose", "run", "--rm", "wpcli", "plugin", "install", plugin, "--activate", "--allow-root"],
                    stderr=subprocess.STDOUT,
            )
        except subprocess.CalledProcessError as exception:
            if "plugin could not be found" in exception.output.decode(encoding="utf-8", errors="ignore"):
                # Allows to skip non-existent plugins if the script crash
                with open(f"scans/{plugin}.json", "w") as fd_out:
                    fd_out.write("{}")
                continue

        subprocess.run(
                [
                    "./bin/wapiti",
                    "-u", "http://localhost:8000/",
                    "--color",
                    "--flush-session",
                    "-m", "exec,file,permanentxss,redirect,sql,ssrf,upload,xss,xxe",
                    "-f", "json",
                    "-o", f"scans/{plugin}.json",
                ]
        )
        os.system("sudo /usr/bin/bash /root/reinit.sh")
                    

Remise à zéro

                        #!/usr/bin/bash
cd /path/to/project
# remove content of wordpress directory
find .srv/wordpress/ -type f -name '.*' -exec rm -f {} \;
find .srv/wordpress/ -type d -name '.*' -exec rm -rf {} \;
rm -rf .srv/wordpress/*

# restore original files
cp -r wordpress_backup/* .srv/wordpress/

# get rid of permission issues
chown -R 33:33 .srv/wordpress/
find .srv/wordpress/ -type d -exec chmod 777 {} \;

# drop the db
mysqladmin -u wordpress -pwordpress -f -h 127.0.0.1 drop wp-app
# recreate it
mysqladmin -u wordpress -pwordpress -f -h 127.0.0.1 create wp-app
# restore original data
mysql -u wordpress -pwordpress -h 127.0.0.1 wp-app < dump.sql
                    

Résultats

Injection SQL dans WP Sessions Time Monitoring Full Automatic
Injection SQL dans Article Analytics
Cross-Site Scripting (reflected) dans AMP+ Plus
Cross-Site Scripting (reflected) dans Classifieds
Cross-Site Scripting (reflected) dans XYZZY Basic SEO & Analytics
Cross-Site Scripting (reflected) dans le plugin Wordpress Charjing For Subscription Billing
Cross-Site Scripting (reflected) dans le plugin Wordpress 'Clickbank WordPress Plugin (Storefront)'
Cross-Site Scripting (reflected) dans le plugin Wordpress JP Theme Switcher Bar
Open Redirect dans le plugin Wordpress Clik stats

Conclusion

Wapiti sait trouver des vulnérabilités

Wapiti est facilement automatisable

Wapiti demande moins de travail qu'un Burp / ZAP

Wapiti est aussi personalisable

Utilisez Wapiti

Futures expérimentations et travaux

Scanner les thĂšmes Wordpress ?

Appliquer Ă  d'autres CMS

Mass scanning des failles XXE

Idem sur les blind SQLi time-based

Modules passif (OSINT)

Documentatioooooooooon

Questions?