--- name: wp-hardening description: Aplicar hardening de seguranca standard a sites WordPress via SSH. Desactiva XML-RPC, file editing, directory listing, esconde versao WP, verifica permissoes e security headers. --- # /wp-hardening - Hardening WordPress Aplica medidas de hardening standard a sites WordPress no servidor CWP (176.9.3.158). > **Nota:** Esta skill APLICA alteracoes. Para auditar sem alterar, usar `/security-check`. ## Contexto NotebookLM ANTES de executar, consultar notebook para contexto: | Notebook | ID | Consultar quando | |----------|-----|-----------------| | WordPress e Elementor | 5be0d1a6 | Sempre | ``` mcp__notebooklm__notebook_query({ notebook_id: "5be0d1a6-00f2-4cd9-b835-978cb7721601", query: "wordpress security hardening best practices" }) ``` --- ## Uso ``` /wp-hardening descomplicar.pt /wp-hardening all # todos os 16 sites /wp-hardening descomplicar.pt --dry # apenas verificar, sem aplicar ``` **Argumento:** dominio do site (ver tabela de sites em /wp-update) ou `all`. **Flag `--dry`:** apenas verifica estado actual sem aplicar alteracoes. --- ## Sites WordPress no servidor | Conta | Site | Path | |-------|------|------| | carstuff | carstuff.pt | /home/carstuff/public_html | | ealmeida | descomplicar.pt | /home/ealmeida/public_html | | ealmeida | emanuelalmeida.pt | /home/ealmeida/emanuelalmeida.pt | | ealmeida | ecommerce.descomplicar.pt | /home/ealmeida/ecommerce.descomplicar.pt | | ealmeida | ecommerce-demo.descomplicar.pt | /home/ealmeida/ecommerce-demo.descomplicar.pt | | ealmeida | starter.descomplicar.pt | /home/ealmeida/starter.descomplicar.pt | | ealmeida | care.descomplicar.pt | /home/ealmeida/care.descomplicar.pt | | ealmeida | e-commerce.descomplicar.pt | /home/ealmeida/e-commerce.descomplicar.pt | | espiral | espiralsenior.pt | /home/espiral/public_html | | espiral | dev.espiralsenior.pt | /home/espiral/dev.espiralsenior.pt | | familycl | familyclinic.pt | /home/familycl/public_html | | ignition | ignitionvortex.pt | /home/ignition/public_html | | karate | karateclubedegaia.com | /home/karate/karateclubedegaia.com | | sintri | sintricare.com.pt | /home/sintri/public_html | | solarfv | solarfvengenharia.com | /home/solarfv/public_html | | wtc | watercontrol.pt | /home/wtc/public_html | --- ## Execucao ### Passo 0: Identificar site e path Mapear o dominio fornecido para o path e conta do servidor usando a tabela acima. ```bash SITE="dominio.pt" WP_PATH="/home/USER/public_html" WP_USER="user" ``` ### Passo 1: Verificar estado actual (antes) Executar via `mcp__ssh-unified__ssh_execute` no servidor `cwp`: ```bash # 1. XML-RPC activo? curl -s -o /dev/null -w "%{http_code}" -X POST "${SITE}/xmlrpc.php" -d 'system.listMethods' # 2. DISALLOW_FILE_EDIT definido? grep -c "DISALLOW_FILE_EDIT" ${WP_PATH}/wp-config.php # 3. Permissoes directórios (esperado: 755) find ${WP_PATH} -type d -not -perm 755 | head -10 # 4. Permissoes ficheiros (esperado: 644) find ${WP_PATH} -type f -not -perm 644 -not -name "wp-config.php" | head -10 # 5. Versao WP exposta no HTML? curl -s ${SITE} | grep -o 'content="WordPress [0-9.]*"' | head -1 # 6. Versao WP exposta no feed? curl -s ${SITE}/feed/ | grep -o '.*' | head -1 # 7. Directory listing activo? curl -s -o /dev/null -w "%{http_code}" ${SITE}/wp-content/uploads/ # 8. wp-config.php permissoes (esperado: 400 ou 440) stat -c "%a" ${WP_PATH}/wp-config.php # 9. .htaccess security headers? grep -c "X-Frame-Options\|X-Content-Type-Options\|X-XSS-Protection\|Referrer-Policy\|Content-Security-Policy\|Strict-Transport-Security" ${WP_PATH}/.htaccess 2>/dev/null # 10. debug.log exposto? test -f ${WP_PATH}/wp-content/debug.log && echo "EXPOSTO" || echo "OK" ``` Registar cada resultado como ANTES. ### Passo 2: Aplicar hardening (se nao --dry) > **Regra:** Fazer backup de cada ficheiro ANTES de alterar. #### 2.1 Desactivar XML-RPC ```bash # Backup .htaccess cp ${WP_PATH}/.htaccess ${WP_PATH}/.htaccess.bak.$(date +%Y%m%d) # Adicionar bloqueio XML-RPC ao .htaccess (antes de # BEGIN WordPress) sed -i '/# BEGIN WordPress/i \ # BEGIN Block XML-RPC\ \ Require all denied\ \ # END Block XML-RPC\ ' ${WP_PATH}/.htaccess ``` **Excepcao:** Se o site usa JetPack ou aplicacao mobile WP, NAO desactivar XML-RPC. Verificar primeiro: ```bash sudo -u ${WP_USER} wp plugin list --status=active --path=${WP_PATH} | grep -i "jetpack" ``` #### 2.2 Desactivar file editing (DISALLOW_FILE_EDIT) ```bash # Backup wp-config.php cp ${WP_PATH}/wp-config.php ${WP_PATH}/wp-config.php.bak.$(date +%Y%m%d) # Adicionar se nao existir grep -q "DISALLOW_FILE_EDIT" ${WP_PATH}/wp-config.php || \ sed -i "/\/\* That's all, stop editing/i define('DISALLOW_FILE_EDIT', true);" ${WP_PATH}/wp-config.php ``` #### 2.3 Corrigir permissoes ```bash # Directorios: 755 find ${WP_PATH} -type d -exec chmod 755 {} \; # Ficheiros: 644 find ${WP_PATH} -type f -exec chmod 644 {} \; # wp-config.php: 440 (leitura apenas para owner e grupo) chmod 440 ${WP_PATH}/wp-config.php # Corrigir ownership chown -R ${WP_USER}:${WP_USER} ${WP_PATH} ``` #### 2.4 Esconder versao WordPress ```bash # Adicionar ao functions.php do tema activo (via wp-cli) THEME_PATH=$(sudo -u ${WP_USER} wp theme path --path=${WP_PATH})/$(sudo -u ${WP_USER} wp theme list --status=active --field=name --path=${WP_PATH}) # Verificar se ja tem o filtro grep -q "remove_action.*wp_head.*wp_generator" ${THEME_PATH}/functions.php 2>/dev/null if [ $? -ne 0 ]; then # Alternativa robusta: usar mu-plugin (nao se perde em updates de tema) mkdir -p ${WP_PATH}/wp-content/mu-plugins cat > ${WP_PATH}/wp-content/mu-plugins/dsc-hardening.php << 'MUEOF' > ${WP_PATH}/.htaccess << 'HTEOF' # BEGIN Security Headers Header always set X-Frame-Options "SAMEORIGIN" Header always set X-Content-Type-Options "nosniff" Header always set X-XSS-Protection "1; mode=block" Header always set Referrer-Policy "strict-origin-when-cross-origin" Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()" Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" # END Security Headers HTEOF fi ``` #### 2.7 Proteger debug.log ```bash # Se debug.log existe, bloquear acesso if [ -f "${WP_PATH}/wp-content/debug.log" ]; then cat >> ${WP_PATH}/wp-content/.htaccess << 'DLEOF' Require all denied DLEOF fi # Desactivar WP_DEBUG se estiver activo em producao grep -q "define.*WP_DEBUG.*true" ${WP_PATH}/wp-config.php && \ sed -i "s/define.*'WP_DEBUG'.*true.*/define('WP_DEBUG', false);/" ${WP_PATH}/wp-config.php ``` ### Passo 3: Verificar estado (depois) Re-executar todos os testes do Passo 1 e registar como DEPOIS. ### Passo 4: Verificar site funcional ```bash # Verificar que o site responde correctamente HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" https://${SITE}) echo "HTTP: ${HTTP_CODE}" # Verificar conteudo por erros criticos curl -s https://${SITE} | grep -i "critical error\|fatal error\|error establishing" | head -3 ``` **Se o site reportar erro apos hardening:** reverter imediatamente usando os backups (.bak). ### Passo 5: Corrigir ownership final ```bash chown -R ${WP_USER}:${WP_USER} ${WP_PATH} ``` --- ## Output Template ```markdown # WP Hardening Report - [site.pt] **Data:** YYYY-MM-DD **Modo:** Aplicado / Dry Run --- ## Checklist Hardening | # | Item | Antes | Depois | Accao | |---|------|-------|--------|-------| | 1 | XML-RPC desactivado | / | / | .htaccess + mu-plugin | | 2 | File editing desactivado | / | / | wp-config.php | | 3 | Permissoes dirs (755) | / | / | chmod recursivo | | 4 | Permissoes ficheiros (644) | / | / | chmod recursivo | | 5 | Versao WP escondida | / | / | mu-plugin | | 6 | Directory listing desactivado | / | / | .htaccess | | 7 | Security headers | / | / | .htaccess | | 8 | wp-config.php (440) | / | / | chmod | | 9 | debug.log protegido | / | / | .htaccess | | 10 | WP_DEBUG desactivado | / | / | wp-config.php | --- ## Ficheiros alterados - `wp-config.php` (DISALLOW_FILE_EDIT, WP_DEBUG) - `.htaccess` (XML-RPC, directory listing, security headers) - `wp-content/mu-plugins/dsc-hardening.php` (criado) ## Backups criados - `.htaccess.bak.YYYYMMDD` - `wp-config.php.bak.YYYYMMDD` ## Verificacao pos-hardening - HTTP: [200/301/etc] - Erros criticos: [Nenhum / Lista] --- *Gerado via /wp-hardening v1.0.0 - YYYY-MM-DD* ``` --- ## Notas importantes 1. **Backups obrigatorios** antes de qualquer alteracao 2. **mu-plugin** preferido sobre functions.php (sobrevive a updates de tema) 3. **JetPack** requer XML-RPC — verificar SEMPRE antes de desactivar 4. **Content-Security-Policy** nao incluido como header standard porque varia por site. Adicionar manualmente se necessario 5. **Reverter:** os backups `.bak.YYYYMMDD` permitem rollback rapido 6. **Ownership:** SEMPRE `chown -R USER:USER` no final (regra #11) --- ## Changelog ### v1.0.0 (2026-03-12) - Versao inicial - 10 verificacoes de hardening - Modo dry run (--dry) - mu-plugin dsc-hardening.php para medidas PHP - Security headers standard no .htaccess - Backup automatico antes de alteracoes - Verificacao pos-hardening com rollback - Tarefa Desk CRM #443 (Projecto #65, Discussao #33)