fix: harden wordpress edge exposure

This commit is contained in:
bisco
2026-06-25 22:57:43 +02:00
parent 02e05ec3b6
commit 82ae9eaae4
11 changed files with 91 additions and 7 deletions
+5 -1
View File
@@ -3,7 +3,7 @@
NGINX is the only public entry point for `azionelab.org`. It proxies HTTP to the
official WordPress 7.0/PHP 8.3 Apache image over the private `web` network. WordPress
connects to MariaDB 11.8 LTS over a separate internal `data` network. Neither WordPress
nor MariaDB publishes a host port.
nor MariaDB publishes a host port; automated security checks guard this assumption.
The custom `azionelab` classic theme renders the public single page. Theme modifications
store the hero, manifesto, laboratory, teacher, lesson, and contact fields. The
@@ -16,6 +16,10 @@ activates the theme, configures the site, and creates realistic demo content. Ce
another optional service, enabled only for direct deployments. It shares challenge and
certificate volumes with NGINX but has no container-control access.
Apache includes a small defense-in-depth hardening file that denies uploaded PHP files,
direct `wp-config.php` requests, and direct access to selected internal WordPress PHP
paths even if a future routing mistake bypasses NGINX.
Persistent state lives in host-based bind mounts configured by `DB_DATA_PATH`,
`WORDPRESS_DATA_PATH`, `LETSENCRYPT_DATA_PATH`, and `CERTBOT_CHALLENGES_PATH`.
Functional tests replace the database and WordPress mounts with isolated Docker test
+5 -3
View File
@@ -9,8 +9,9 @@
- File editing is always disabled. Production also disables web-based core, theme, and
plugin changes; patched images are rebuilt and redeployed instead.
- XML-RPC and comments are disabled. NGINX blocks PHP execution below uploads, dotfiles,
and direct `wp-config.php` requests, and rate-limits login/public requests. Public
REST user enumeration and author archives are disabled.
and direct `wp-config.php` requests, and rate-limits login/public requests. Apache
also denies uploaded PHP files and direct access to sensitive WordPress internals as
defense in depth. Public REST user enumeration and author archives are disabled.
- Security headers include CSP, same-origin framing, content-type protection, a strict
referrer policy, and a restrictive Permissions Policy. WordPress compatibility still
requires inline style/script CSP allowances; do not treat this CSP as an XSS sanitizer.
@@ -20,7 +21,8 @@
no Docker socket, dropped capabilities, and narrowly scoped volumes.
- Containers are not privileged and do not use host networking or the Docker socket.
WordPress/Apache retains the capabilities needed by the official image internally,
but no WordPress port is published.
but no WordPress port is published. A containerized security test fails if the
WordPress service is configured with host-published ports.
- Persistent state uses host-based bind mounts. Keep those paths outside the public web
root, restrict host access, never make them world-writable, and run
`./scripts/prepare-host-volumes.sh` when paths or image user IDs change.
+4 -1
View File
@@ -10,6 +10,7 @@ docker compose run --rm --no-deps proxy nginx -t
docker compose -f docker-compose.yml -f docker-compose.test.yml up --build -d db wordpress proxy
docker compose -f docker-compose.yml -f docker-compose.test.yml --profile tools run --rm wp-cli /scripts/bootstrap.sh
docker compose -f docker-compose.yml -f docker-compose.test.yml --profile test run --build --rm functional-tests
docker compose -f docker-compose.yml -f docker-compose.test.yml --profile test run --rm security-tests
docker compose config --quiet
LETSENCRYPT_ENABLED=1 docker compose config --quiet
```
@@ -19,7 +20,9 @@ override replaces database and WordPress state with isolated Docker volumes, map
`azionelab.org` to the internal proxy, and never publishes an extra port. Browser tests
cover content and section order, contact actions, mobile overflow/navigation, semantic
landmarks, image alternatives, admin routing, security headers, blocked sensitive
routes, and unknown virtual hosts.
routes, blocked uploaded PHP requests, and unknown virtual hosts. Security checks also
assert that WordPress does not publish host ports and that Apache hardening remains
installed in the WordPress image.
Subjective visual review and a real-device accessibility audit remain manual release
checks.