# ==========================================================================
#  dww.show — hardened WordPress root .htaccess (restored 2026-09-05)
#  Basis: incident kit 2026-07-16 (~/code/dww-seo-audit/incident-2026-07-16/LIVE-htaccess.txt)
#  + WP Fastest Cache static-serve rules + REST Authorization pass-through.
#  Previous file kept as .htaccess.bak-20260905 (stock rules, 2026-07-25).
# ==========================================================================

# --- Rule 1: Deny direct access to xmlrpc.php ------------------------------
<Files "xmlrpc.php">
  <IfModule mod_authz_core.c>
    Require all denied
  </IfModule>
  <IfModule !mod_authz_core.c>
    Order allow,deny
    Deny from all
  </IfModule>
</Files>

# --- Rule 2: Protect wp-config.php ----------------------------------------
<Files "wp-config.php">
  <IfModule mod_authz_core.c>
    Require all denied
  </IfModule>
  <IfModule !mod_authz_core.c>
    Order allow,deny
    Deny from all
  </IfModule>
</Files>

# --- Rule 3: Protect dotfiles ---------------------------------------------
<FilesMatch "^\.(?:htaccess|htpasswd)$">
  <IfModule mod_authz_core.c>
    Require all denied
  </IfModule>
  <IfModule !mod_authz_core.c>
    Order allow,deny
    Deny from all
  </IfModule>
</FilesMatch>

# --- Rule 4: Blocklist incident webshell filenames at any depth -----------
<FilesMatch "^(?:wp-server|detail|products|cloak|ima|alam|massby1|massby2|lock360|4|222|333|444|555|321|123|155|144|199|166|heatmap-log|schedule-handler|sync|wp-link)\.php$">
  <IfModule mod_authz_core.c>
    Require all denied
  </IfModule>
  <IfModule !mod_authz_core.c>
    Order allow,deny
    Deny from all
  </IfModule>
</FilesMatch>

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

# Pass HTTP Basic auth to PHP (WordPress Application Passwords / REST API).
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

# --- Incident cleanup: 410 Gone for the attacker's SEO-spam doorway URLs --
RewriteCond %{QUERY_STRING} (^|&)[qzclomr]=[0-9]{9,}(&|$) [NC]
RewriteRule ^$ - [G,L]

# --- No PHP execution under wp-content/uploads ----------------------------
RewriteRule ^wp-content/uploads/.*\.(?i:php|php3|php4|php5|php7|php8|phps|phtml|pht|phar)$ - [F,L]

# BEGIN WpFastestCache
# Serve the static HTML cache directly (no PHP) for anonymous GET requests.
RewriteCond %{HTTP_HOST} ^dww\.show$ [NC]
RewriteCond %{HTTPS} =on
RewriteCond %{REQUEST_METHOD} !POST
RewriteCond %{REQUEST_URI} !(\/){2}$
RewriteCond %{QUERY_STRING} !.+
RewriteCond %{HTTP:Cookie} !comment_author_
RewriteCond %{HTTP:Cookie} !wordpress_logged_in
RewriteCond %{HTTP:Cookie} !wp-postpass_
RewriteCond %{HTTP:Cookie} !wpfc-lang
RewriteCond %{HTTP:Cookie} !wpfc-mobile-switcher
RewriteCond %{HTTP_USER_AGENT} !(WP\sFastest\sCache\sPreload(\siPhone\sMobile)?\s*Bot)
RewriteCond %{DOCUMENT_ROOT}/wp-content/cache/all/$1/index.html -f
RewriteRule ^(.*) "/wp-content/cache/all/$1/index.html" [L]
# END WpFastestCache

# BEGIN WordPress
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress
</IfModule>

# --- Browser caching for static assets (WPFC "browser caching" equivalent) --
<IfModule mod_expires.c>
  ExpiresActive On
  ExpiresByType image/png "access plus 1 month"
  ExpiresByType image/jpeg "access plus 1 month"
  ExpiresByType image/webp "access plus 1 month"
  ExpiresByType image/gif "access plus 1 month"
  ExpiresByType image/svg+xml "access plus 1 month"
  ExpiresByType image/x-icon "access plus 1 month"
  ExpiresByType text/css "access plus 1 month"
  ExpiresByType application/javascript "access plus 1 month"
  ExpiresByType text/javascript "access plus 1 month"
  ExpiresByType font/woff2 "access plus 1 year"
  ExpiresByType font/woff "access plus 1 year"
</IfModule>
<FilesMatch "index\.(html|htm)$">
  AddDefaultCharset UTF-8
  <IfModule mod_headers.c>
    FileETag None
    Header unset ETag
    Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
    Header set Pragma "no-cache"
    Header set Expires "Mon, 29 Oct 1923 20:30:00 GMT"
  </IfModule>
</FilesMatch>
