2
Cloudflare WAF Bypass Discovery
WMJ Ismail edited this page 2026-07-03 09:00:59 +02:00

Cloudflare WAF Bypass Discovery 🎯

The Breakthrough Finding

We discovered that Cloudflare WAF was NOT blocking the Contabo IP from the WordPress REST API. This was a critical misconception that had blocked deployment for days.

What Actually Happened

We assumed Cloudflare's WAF was blocking 172.17.0.1 (our Contabo Docker host) from reaching ummah.falahos.my/wp-json/. This assumption was wrong.

Evidence:

$ curl -s -w "HTTP %{http_code}" "https://ummah.falahos.my/wp-json/wp/v2/users"
HTTP 200

$ curl -s -w "HTTP %{http_code}" "https://ummah.falahos.my/wp-json/wp/v2/plugins"
HTTP 401

The WP REST API was fully reachable — it just returned:

  • HTTP 200 for public endpoints (users, index, etc.)
  • HTTP 401 for protected endpoints (plugins, etc.) — not a WAF block!

Why We Thought It Was Blocked

Earlier testing used /wp-json/hermes/v1/content/generate which returned HTTP 404 (plugin not installed yet, not blocked). And the assumption that cPanel shared hosting behind Cloudflare would block non-browser traffic was natural but incorrect.

The Real Blocker

The actual blocker was authentication, not Cloudflare:

WP REST API needs → Application Password (HTTP Basic Auth)
                  → OR Cookie + Nonce (browser-based auth)

Cloudflare WAF was never the issue — we just needed a WordPress Application Password.

Solution: Application Passwords

WordPress Application Passwords provide app-layer authentication via HTTP Basic Auth:

curl -u "username:application_password" \
  "https://ummah.falahos.my/wp-json/wp/v2/plugins"

This bypasses any WAF because the auth happens at the application layer inside WordPress, not at the network level.

How to Create

Via REST API (if already logged in):

# 1. Log in with cookie auth
curl -c cookies.txt \
  -d "log=wmj&pwd=PASSWORD&wp-submit=Log+In" \
  "https://ummah.falahos.my/wp-login.php"

# 2. Extract nonce from admin page
NONCE=$(curl -b cookies.txt \
  "https://ummah.falahos.my/wp-admin/profile.php" \
  | grep -oP '"nonce":"[^"]*"' | head -1 | cut -d'"' -f4)

# 3. Create Application Password
curl -b cookies.txt \
  -H "X-WP-Nonce: $NONCE" \
  -H "Content-Type: application/json" \
  -d '{"name":"my-agent"}' \
  "https://ummah.falahos.my/wp-json/wp/v2/users/me/application-passwords"

Via Admin UI:

  1. Log in to https://ummah.falahos.my/wp-admin
  2. Go to Users → Profile
  3. Scroll to "Application Passwords" section
  4. Enter a name and click "Add New"
  5. Copy the generated password

Key Takeaway

Always verify assumptions about network-level blocking before engineering complex workarounds. Test with curl -w "HTTP %{http_code}" first to distinguish between:

  • HTTP 403/503 → WAF or server block
  • HTTP 401 → Authentication needed (WordPress is responding!)
  • HTTP 404 → Endpoint not found (plugin not installed)
  • WordPress Application Passwords plugin is already installed on ummah.falahos.my
  • Gitea Actions CI/CD uses WP_APP_PASSWORD secret for auto-deployment
  • The CF API token (cfut_...) has DNS:Edit + Zone:Read scopes but NOT WAF management