Das von uns am häufigsten verwendete Blog- und CMS-System ist WordPress. Dieses lässt sich auch performant als Docker Container betreiben. Redis als object cache beschleunigt die Zugriffe. Für mehr Sicherheit bietet sich die Community Version von Crowdsec an.
Im folgenden Beispiel zeigen wir, wie dies mittel Docker Compose einfach aufgesetzt werden kann.
Zutaten
- Server oder VM mit installiertem Docker + Compose sowie aktuellem Patchlevel
- SSH-Zugriff
- Kaffee & etwas Zeit
Vorbereitung
Für die Kommunikation zwischen WordPress und Crowdsec sollte man ein Dockernetzwerk mit festen IPs erstellen. Andernfalls kann es nach einem Neustart der Container passieren, dass diese andere IPs erhalten und die Kommunikation mit dem Bouncer ins Leere läuft.
In den Beispielen wird immer das Verzeichnis /docker/wordpress als Basis verwendet.
Erstellung des Netzwerkes für die Container & der wordpress.ini
In der Shell das Subnet erstellen (“wpnet”). Die Range kann natürlich frei gewählt werden:
docker network create --subnet=172.26.0.0/24 wpnet
Im nächsten Schritt erstellt man die wordpress.ini, welche wichtige Einstellungen für die Performance erhält:
nano /docker/wordpress/wordpress.ini
Die Werte innerhalb der wordpress.ini können nach eigenen Vorgaben angepasst werden:
upload_max_filesize = 256M
post_max_size = 512M
max_execution_time = 3000
max_input_time = 3000
memory_limit = 1024M
file_uploads= On
max_input_vars = 15000
Die docker-compose.yml erstellen
WordPress + MariaDB + Redis + Crowdsec
nano /docker/wordpress/docker-compose.yml
Inhalt der docker-compose.yml:
version: '3.1'
services:
wordpress:
image: wordpress:latest
container_name: wordpress
environment:
WORDPRESS_DB_HOST: wordpress-db
WORDPRESS_DB_USER: wp-dbuser
WORDPRESS_DB_PASSWORD: EinSuperGeheimesPasswort
WORDPRESS_DB_NAME: wordpress
WORDPRESS_CONFIG_EXTRA:
define('WP_POST_REVISIONS', 5);
define( 'WP_MEMORY_LIMIT' , '1024M' );
set_time_limit(300);
define( 'WP_REDIS_HOST', 'wordpress-redis' );
define( 'WP_REDIS_PORT', 6379 );
define( 'DISABLE_WP_CRON', true);
volumes:
- /docker/wordpress/app:/var/www/html
- /docker/wordpress/wordpress.ini:/usr/local/etc/php/conf.d/wordpress.ini
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
networks:
wpnet:
ipv4_address: 172.26.0.10
ports:
- 80:80
- 443:433
restart: always
logging:
driver: "syslog"
wordpress-db:
image: mariadb:latest
container_name: wordpress-db
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wp-dbuser
MYSQL_PASSWORD: EinSuperGeheimesPasswort
MYSQL_RANDOM_ROOT_PASSWORD: '1'
volumes:
- /docker/wordpress/database:/var/lib/mysql
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
networks:
wpnet:
ipv4_address: 172.26.0.11
restart: always
wordpress-redis:
image: redis:alpine
container_name: wordpress-redis
ports:
- 6379:6379
networks:
wpnet:
ipv4_address: 172.26.0.12
restart: always
crowdsec:
image: docker.io/crowdsecurity/crowdsec:latest
container_name: crowdsec
ports:
- 49155:8080
environment:
- GID=1000
- COLLECTIONS=crowdsecurity/wordpress crowdsecurity/http-cve crowdsecurity/whitelist-good-actors
networks:
wpnet:
ipv4_address: 172.26.0.13
volumes:
- /docker/wordpress/crowdsec/config:/etc/crowdsec:rw
- /docker/wordpress/crowdsec/data:/var/lib/crowdsec/data:rw
- /var/log:/var/log/host:ro
restart: unless-stopped
networks:
wpnet:
external: true
Die Ports von WordPress (80 & 443) können frei gewählt werden. Ebenso sollte die Umgebungsvariablen “MYSQL_PASSWORD:” auf ein eigenes starkes Passwort geändert werden. Für den HTTPS-Zugriff empfiehlt sich der Zugriff via einen der üblichen Proxies (Traefik, NPM, HAProxy, etc.). Die Werte unter “WORDPRESS_CONFIG_EXTRA:” können ebenfalls den eigenen Vorstellungen angepasst werden (konform zur wordpress.ini).
Wichtig sind hier die IPs der einzelnen Container:
- 172.26.0.10 -> WordPress
- 172.26.0.11 -> MariaDB
- 172.26.0.12 -> Redis
- 172.26.0.13 -> Crowdsec
Erstmaliger Pull & Start der Container
sudo docker compose -f /docker/wordpress/docker-compose.yml up -d
Die Container werden nach dem Pull im Hintergrund gestartet. Nach dem ersten Start sollte man die Verzeichnisberechtigungen anpassen. Hierfür stoppt man die Container zunächst wieder:
sudo docker compose -f /docker/wordpress/docker-compose.yml down
und setzt für das Verzeichnis ./app die Berechtigung/Ownership auf den user “www-data”:
sudo chown -R www-data:www-data /docker/wordpress/app
Die Container anschließend wieder starten und die Ersteinrichtung starten:
sudo docker compose -f /docker/wordpress/docker-compose.yml up -d
Ersteinrichtung von WordPress
Plugins für Redis + Crowdsec installieren
Nachdem man die Ersteinrichtung erledigt hat (Blogtitel, Sprache, User, E-Mail, Passwort, etc.) installiert man die Plugins “Redis Object Cache” und “Crowdsec”:
Nach der Aktivierung der Plugins klickt man in der oberen Leiste des Dashboards auf “Object Cache” und aktiviert diesen:
Konfiguration von Crowdsec
Zur Absicherung von WordPress konfiguriert man im letzten Schritt Crowdsec. Zunächst erstellt man sich für “cscli” (Crowdsec CLI) einen temporären Alias in der Shell:
alias cscli="docker exec -t crowdsec cscli"
Bouncer erstellen
Nun erstellt man einen “Bouncer” für WordPress. Wichtig: den API-Key, welcher angezeigt wird, unbedingt notieren/speichern. Dieser wird später in WordPress noch benötigt:
cscli bouncers add wordpress-bouncer
Die Ausgabe sollte dann so aussehen:
Den Bouncer mit WordPress verbinden
API key for 'wordpress-bouncer':
nDxCE0eGRCPl77eWqGJVSg
Please keep this key since you will not be able to retrieve it!
Zurück im Admin-Dashboard von WordPress in das Crowdsec-Menü gehen (Crowdsec -> Crowdsec). Hier tragen wir die Docker-IP mit Port von Crowdsec (172.26.0.13:8080) sowie unseren eben erzeugten API-Key ein und bestätigen die Änderungen:
Das Bouncing Level sollte auf “Normal bouncing” stehen. Um auch das Backend/Login abzusichern, sollte der Schieber “Public website only” nicht aktiviert werden.
Mittels “Test bouncing” kann man überprüfen, ob die Kommunikation soweit läuft.
Falls WordPress hinter einem Proxy betrieben wird, muss dessen IP unter Advanced eingetragen werden (im Format X.X.X.X/32):
Crowdsec "pimpen"
Um die Sicherheit via Crowdsec weiter zu erhöhen, können neben den bereits enthaltenen Collections (crowdsecurity/wordpress, crowdsecurity/http-cve, crowdsecurity/whitelist-good-actors) noch weitere Szenarios über die Shell hinzugefügt werden:
Detect WordPress bruteforce
cscli scenarios install crowdsecurity/http-bf-wordpress_bf
Detect WordPress bruteforce on xmlrpc
cscli scenarios install crowdsecurity/http-bf-wordpress_bf_xmlrpc
Detect WordPress authors enumeration
cscli scenarios install crowdsecurity/http-wordpress_user-enum
Detect WordPress probing aorund wp-config.php
cscli scenarios install crowdsecurity/http-wordpress_wpconfig
CSCLI dauerhaft in der Shell verfügbar machen
Möchte man den Alias CSCLI nicht nach jedem Neustart neu definieren, kann man diesen auch dauerhaft setzen:
nano ~/.bashrc
Am Ende der Datei diesen Eintrag setzen:
alias cscli='docker exec -t crowdsec cscli'
Die Datei speichern und bashrc reloaden:
source ~/.bashrc
Nützliche Kommandos für CSCLI
Alerts abfragen
cscli alerts list
Collections anzeigen
cscli collections list
COLLECTIONS
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Name 📦 Status Version Local Path
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
crowdsecurity/http-cve ✔️ enabled 2.5 /etc/crowdsec/collections/http-cve.yaml
crowdsecurity/linux ✔️ enabled 0.2 /etc/crowdsec/collections/linux.yaml
crowdsecurity/sshd ✔️ enabled 0.2 /etc/crowdsec/collections/sshd.yaml
crowdsecurity/whitelist-good-actors ✔️ enabled 0.1 /etc/crowdsec/collections/whitelist-good-actors.yaml
crowdsecurity/wordpress ✔️ enabled 0.4 /etc/crowdsec/collections/wordpress.yaml
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Collections, Scenarios & Parser (Hub) abfragen
cscli hub list
COLLECTIONS
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Name 📦 Status Version Local Path
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
crowdsecurity/http-cve ✔️ enabled 2.5 /etc/crowdsec/collections/http-cve.yaml
crowdsecurity/linux ✔️ enabled 0.2 /etc/crowdsec/collections/linux.yaml
crowdsecurity/sshd ✔️ enabled 0.2 /etc/crowdsec/collections/sshd.yaml
crowdsecurity/whitelist-good-actors ✔️ enabled 0.1 /etc/crowdsec/collections/whitelist-good-actors.yaml
crowdsecurity/wordpress ✔️ enabled 0.4 /etc/crowdsec/collections/wordpress.yaml
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
PARSERS
───────────────────────────────────────────────────────────────────────────────────────────────────────────────
Name 📦 Status Version Local Path
───────────────────────────────────────────────────────────────────────────────────────────────────────────────
crowdsecurity/cri-logs ✔️ enabled 0.1 /etc/crowdsec/parsers/s00-raw/cri-logs.yaml
crowdsecurity/dateparse-enrich ✔️ enabled 0.2 /etc/crowdsec/parsers/s02-enrich/dateparse-enrich.yaml
crowdsecurity/docker-logs ✔️ enabled 0.1 /etc/crowdsec/parsers/s00-raw/docker-logs.yaml
crowdsecurity/geoip-enrich ✔️ enabled 0.2 /etc/crowdsec/parsers/s02-enrich/geoip-enrich.yaml
crowdsecurity/sshd-logs ✔️ enabled 2.2 /etc/crowdsec/parsers/s01-parse/sshd-logs.yaml
crowdsecurity/syslog-logs ✔️ enabled 0.8 /etc/crowdsec/parsers/s00-raw/syslog-logs.yaml
crowdsecurity/whitelists ✔️ enabled 0.2 /etc/crowdsec/parsers/s02-enrich/whitelists.yaml
───────────────────────────────────────────────────────────────────────────────────────────────────────────────
SCENARIOS
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Name 📦 Status Version Local Path
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
crowdsecurity/CVE-2019-18935 ✔️ enabled 0.2 /etc/crowdsec/scenarios/CVE-2019-18935.yaml
crowdsecurity/CVE-2022-26134 ✔️ enabled 0.2 /etc/crowdsec/scenarios/CVE-2022-26134.yaml
crowdsecurity/CVE-2022-35914 ✔️ enabled 0.2 /etc/crowdsec/scenarios/CVE-2022-35914.yaml
crowdsecurity/CVE-2022-37042 ✔️ enabled 0.2 /etc/crowdsec/scenarios/CVE-2022-37042.yaml
crowdsecurity/CVE-2022-40684 ✔️ enabled 0.3 /etc/crowdsec/scenarios/CVE-2022-40684.yaml
crowdsecurity/CVE-2022-41082 ✔️ enabled 0.4 /etc/crowdsec/scenarios/CVE-2022-41082.yaml
crowdsecurity/CVE-2022-41697 ✔️ enabled 0.2 /etc/crowdsec/scenarios/CVE-2022-41697.yaml
crowdsecurity/CVE-2022-42889 ✔️ enabled 0.3 /etc/crowdsec/scenarios/CVE-2022-42889.yaml
crowdsecurity/CVE-2022-44877 ✔️ enabled 0.3 /etc/crowdsec/scenarios/CVE-2022-44877.yaml
crowdsecurity/CVE-2022-46169 ✔️ enabled 0.2 /etc/crowdsec/scenarios/CVE-2022-46169.yaml
crowdsecurity/CVE-2023-22515 ✔️ enabled 0.1 /etc/crowdsec/scenarios/CVE-2023-22515.yaml
crowdsecurity/CVE-2023-22518 ✔️ enabled 0.2 /etc/crowdsec/scenarios/CVE-2023-22518.yaml
crowdsecurity/CVE-2023-49103 ✔️ enabled 0.2 /etc/crowdsec/scenarios/CVE-2023-49103.yaml
crowdsecurity/apache_log4j2_cve-2021-44228 ✔️ enabled 0.5 /etc/crowdsec/scenarios/apache_log4j2_cve-2021-44228.yaml
crowdsecurity/f5-big-ip-cve-2020-5902 ✔️ enabled 0.2 /etc/crowdsec/scenarios/f5-big-ip-cve-2020-5902.yaml
crowdsecurity/fortinet-cve-2018-13379 ✔️ enabled 0.3 /etc/crowdsec/scenarios/fortinet-cve-2018-13379.yaml
crowdsecurity/grafana-cve-2021-43798 ✔️ enabled 0.2 /etc/crowdsec/scenarios/grafana-cve-2021-43798.yaml
crowdsecurity/http-bf-wordpress_bf ✔️ enabled 0.5 /etc/crowdsec/scenarios/http-bf-wordpress_bf.yaml
crowdsecurity/http-bf-wordpress_bf_xmlrpc ✔️ enabled 0.2 /etc/crowdsec/scenarios/http-bf-wordpress_bf_xmlrpc.yaml
crowdsecurity/http-cve-2021-41773 ✔️ enabled 0.2 /etc/crowdsec/scenarios/http-cve-2021-41773.yaml
crowdsecurity/http-cve-2021-42013 ✔️ enabled 0.2 /etc/crowdsec/scenarios/http-cve-2021-42013.yaml
crowdsecurity/http-wordpress_user-enum ✔️ enabled 0.2 /etc/crowdsec/scenarios/http-wordpress_user-enum.yaml
crowdsecurity/http-wordpress_wpconfig ✔️ enabled 0.2 /etc/crowdsec/scenarios/http-wordpress_wpconfig.yaml
crowdsecurity/jira_cve-2021-26086 ✔️ enabled 0.2 /etc/crowdsec/scenarios/jira_cve-2021-26086.yaml
crowdsecurity/netgear_rce ✔️ enabled 0.3 /etc/crowdsec/scenarios/netgear_rce.yaml
crowdsecurity/pulse-secure-sslvpn-cve-2019-11510 ✔️ enabled 0.3 /etc/crowdsec/scenarios/pulse-secure-sslvpn-cve-2019-11510.yaml
crowdsecurity/spring4shell_cve-2022-22965 ✔️ enabled 0.3 /etc/crowdsec/scenarios/spring4shell_cve-2022-22965.yaml
crowdsecurity/ssh-bf ✔️ enabled 0.3 /etc/crowdsec/scenarios/ssh-bf.yaml
crowdsecurity/ssh-slow-bf ✔️ enabled 0.4 /etc/crowdsec/scenarios/ssh-slow-bf.yaml
crowdsecurity/thinkphp-cve-2018-20062 ✔️ enabled 0.4 /etc/crowdsec/scenarios/thinkphp-cve-2018-20062.yaml
crowdsecurity/vmware-cve-2022-22954 ✔️ enabled 0.3 /etc/crowdsec/scenarios/vmware-cve-2022-22954.yaml
crowdsecurity/vmware-vcenter-vmsa-2021-0027 ✔️ enabled 0.2 /etc/crowdsec/scenarios/vmware-vcenter-vmsa-2021-0027.yaml
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
POSTOVERFLOWS
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Name 📦 Status Version Local Path
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
crowdsecurity/cdn-whitelist ✔️ enabled 0.4 /etc/crowdsec/postoverflows/s01-whitelist/cdn-whitelist.yaml
crowdsecurity/rdns ✔️ enabled 0.3 /etc/crowdsec/postoverflows/s00-enrich/rdns.yaml
crowdsecurity/seo-bots-whitelist ✔️ enabled 0.4 /etc/crowdsec/postoverflows/s01-whitelist/seo-bots-whitelist.yaml
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────