Mantendo seu WordPress livre de malwares

Como verificar e recuperar sem perder o conteúdo

Publicado em 05/05/2025 • Tags: wordpress, seguranca, invasao wordpress

Interessado neste tema? Agende uma conversa rápida sobre Mantendo seu WordPress livre de malwares.

Agendar 20 min

O WordPress é um dos sistemas mais populares do mundo para criação de sites e blogs, mas também é alvo constante de ataques. Plugins desatualizados, temas comprometidos e permissões indevidas podem abrir brechas de segurança.

Neste artigo, você vai aprender a:

  • Identificar sinais de invasão;
  • Remover malwares como backdoors;
  • Reinstalar com segurança o núcleo do WordPress;
  • Proteger pastas e arquivos sensíveis;
  • Automatizar auditorias com um script prático.

E o melhor: sem perder seu conteúdo. Vamos lá?

🚨 Sinais de que seu WordPress foi comprometido

Você deve ficar atento se notar:

  • Redirecionamentos estranhos ao acessar seu site;
  • Lentidão ou picos de tráfego não usuais;
  • Aparecimento de arquivos desconhecidos em /wp-content/;
  • Inclusões PHP suspeitas, como @include("/var/www/html/...").

🔐 Boas práticas de segurança

Antes de automatizarmos tudo, vale relembrar as boas práticas fundamentais:

  1. Atualize sempre seu WordPress, plugins e temas.
  2. Nunca use plugins piratas (nulled) — eles são porta de entrada para códigos maliciosos.
  3. Use senhas fortes e autenticação em duas etapas.
  4. Aplique permissões corretas: 755 para pastas e 644 para arquivos.
  5. Proteja arquivos críticos com chattr +i.
  6. Use um firewall de aplicação (WAF), se possível.

⚙️ Automatizando a verificação e recuperação

Criamos um script completo em bash para Linux, que faz tudo de forma automatizada:

  • Destrava o WordPress;
  • Remove possíveis backdoors;
  • Reinstala os diretórios principais;
  • Verifica a integridade com wp-cli;
  • Apaga .htaccess suspeitos e recria o padrão;
  • Audita temas com base em listas brancas;
  • Protege arquivos e envia um relatório por e-mail.

📦 Pré-requisitos

Antes de executar o script:

  • Acesse o servidor via SSH;
  • Tenha o wp-cli instalado e funcionando com permissões de www-data;
  • Certifique-se de ter mailutils instalado para envio de e-mails (sudo apt install mailutils);
  • Faça backup completo do site (banco e arquivos).

🧪 Como usar o script

  1. Salve o conteúdo abaixo como audit-total-v3.sh;
  2. Dê permissão de execução :
chmod +x audit-total-v3.sh

3. Execute com o caminho para o diretório do WordPress:

./audit-total-v3.sh /var/www/html/seusite

🧾 Script completo: audit-total-v3.sh

#!/bin/bash
# audit-total-v3.sh
# Auditoria e reforço de segurança para WordPress
# Autor: Osvaldo Janeri Filho

# ========================== CONFIGURAÇÕES ==========================

EMAIL="[email protected]"

# Verifica argumentos
if [ -z "$1" ]; then
echo "Erro: Caminho do WordPress não informado."
echo "Uso: $0 /caminho/do/wordpress [--run]"
exit 1
fi

WP_PATH="$1"
LOG_FILE="$WP_PATH/auditoria-$(date +%F).log"
SUBJECT="Relatório de Auditoria do WordPress"

# Detecta modo de execução
if [ "$2" == "--run" ]; then
DRY_RUN=false
else
DRY_RUN=true
fi

declare -A WHITELIST

# ========================== CORES E LOGS ==========================

txtInfo="\e[32m"
txtError="\e[31m"
txtWarn="\e[33m"
txtReset="\e[0m"
char_success="✅"
char_fail="❌"
char_alert="⚠️"
char_info="ℹ️"

function IO:success() { echo -e "${txtInfo}${char_success} $*${txtReset}" | tee -a "$LOG_FILE"; }
function IO:error() { echo -e "${txtError}${char_fail} $*${txtReset}" | tee -a "$LOG_FILE"; }
function IO:alert() { echo -e "${txtWarn}${char_alert} $*${txtReset}" | tee -a "$LOG_FILE"; }
function IO:info() { echo -e "${txtInfo}${char_info} $*${txtReset}" | tee -a "$LOG_FILE"; }

# ========================== EXECUTOR CONDICIONAL ==========================

run() {
local cmd="$1"
local desc="$2"

if $DRY_RUN; then
IO:info "[dry-run] Comando: $cmd"
IO:info "[dry-run] $desc"
else
eval "$cmd"
fi
}

# ========================== FUNÇÕES DE SEGURANÇA ==========================

lock_wordpress() {
if [ "$1" == "on" ]; then
IO:info "Aplicando travas ao WordPress..."

run "chown -R root $WP_PATH" "Assume propriedade como root"
run "chmod g-w $WP_PATH" "Remove permissão de escrita para grupo"
run "chmod g+xr $WP_PATH" "Garante leitura/execução do diretório"

run "find $WP_PATH -type d -exec chmod 555 {} \;" "Permissão de leitura/execução para pastas"
run "find $WP_PATH -type f -exec chmod 444 {} \;" "Permissão de somente leitura para arquivos"

run "find $WP_PATH/wp-content/cache -type d -exec chmod 775 {} \; &>/dev/null" "Permissões especiais para cache (pastas)"
run "find $WP_PATH/wp-content/cache -type f -exec chmod 664 {} \; &>/dev/null" "Permissões especiais para cache (arquivos)"
run "chmod -f 664 $WP_PATH/wp-content/wp-cache-config.php" "Permissões corretas para wp-cache-config.php"

run "chattr +i $WP_PATH/wp-content/plugins" "Imutável: plugins"
run "chattr +i $WP_PATH/wp-content/themes" "Imutável: temas"
run "chattr +i $WP_PATH/wp-admin" "Imutável: painel admin"
run "chattr +i $WP_PATH/wp-config.php" "Imutável: wp-config.php"
run "chattr +i $WP_PATH/index.php" "Imutável: index.php"
run "chattr +i $WP_PATH/wp-settings.php" "Imutável: wp-settings.php"

run "chattr -i $WP_PATH/wp-content" "Remove imutabilidade de wp-content"
run "chattr -i $WP_PATH/wp-content/uploads" "Remove imutabilidade de uploads"
run "chmod g+rw $WP_PATH/wp-content/uploads" "Permite escrita em uploads"
run "chmod 755 $WP_PATH/wp-content/uploads -R" "Permissões corretas em uploads"
run "chown www-data:www-data $WP_PATH/wp-content/wmufs-temp" "Permissões corretas no temp"

IO:success "WordPress travado com sucesso."

elif [ "$1" == "off" ]; then
IO:info "Removendo travas do WordPress..."

run "chattr -i $WP_PATH" "Remove imutabilidade do diretório"
run "chattr -i $WP_PATH/*" "Remove imutabilidade de arquivos principais"

run "chown -R www-data $WP_PATH" "Retorna propriedade ao www-data"
run "find $WP_PATH -type d -exec chmod 755 {} \;" "Permissão padrão de pastas"
run "find $WP_PATH -type f -exec chmod 644 {} \;" "Permissão padrão de arquivos"

run "chattr -i $WP_PATH/wp-content/plugins" "Destrava plugins"
run "chattr -i $WP_PATH/wp-content/themes" "Destrava temas"

IO:success "WordPress destravado com sucesso."
fi
}

# ========================== BACKDOOR CHECK ==========================

procura_arq_includes() {
IO:info "Procurando por backdoors..."
search_strings=("@include (\"/var/www/html/")

find $WP_PATH -type f | while read -r file; do
for str in "${search_strings[@]}"; do
if grep -q "$str" "$file"; then
IO:alert "Backdoor encontrado em: $file"

secondary_file=$(grep "@include" "$file" | cut -f 2 -d '"')
if [ -f "$secondary_file" ]; then
run "rm '$secondary_file'" "Remove arquivo malicioso incluído"
fi

if ! $DRY_RUN; then
grep -v "$str" "$file" > temp && mv temp "$file"
else
IO:info "[dry-run] Remover linha com '$str' de $file"
fi

IO:success "Backdoor removido de: $file"
fi
done
done
}

# ========================== TEMA - LISTA BRANCA ==========================

gerar_lista_branca() {
IO:info "Gerando lista branca de arquivos por tema..."

sudo -u www-data wp theme list --field=name --path=$WP_PATH | while read -r theme; do
theme_path=$(sudo -u www-data wp theme path "$theme" --path=$WP_PATH)
if [ -d "$theme_path" ]; then
WHITELIST[$theme]="$(find "$theme_path" -type f -printf "%P\n")"
IO:success "Lista branca para '$theme'."
else
IO:error "Tema '$theme' não encontrado."
fi
done
}

verificar_arquivos_temas() {
IO:info "Verificando arquivos não permitidos nos temas..."

for theme in "$WP_PATH/wp-content/themes/"*/; do
theme_name=$(basename "$theme")
if [[ -n "${WHITELIST[$theme_name]}" ]]; then
IFS=$'\n' read -r -d '' -a allowed_files <<< "${WHITELIST[$theme_name]}"
find "$theme" -type f | while read -r file; do
relative_path="${file#$theme}"
if [[ ! " ${allowed_files[@]} " =~ " $relative_path " ]]; then
IO:alert "Arquivo suspeito em $theme_name: $file"
run "rm '$file'" "Remoção de arquivo fora da lista branca"
fi
done
else
IO:alert "Tema '$theme_name' sem lista branca. Pulando."
fi
done
}

# ========================== .HTACCESS E PHP.INI ==========================

adicionar_htaccess_padrao() {
IO:info "Criando .htaccess padrão..."

if ! $DRY_RUN; then
cat <<EOL > "$WP_PATH/.htaccess"
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
EOL

else
IO:info "[dry-run] Recriar .htaccess padrão"
fi
IO:success ".htaccess preparado."
}

# ========================== RELATÓRIO FINAL ==========================

gerar_relatorio() {
IO:info "Enviando relatório por e-mail..."
sed 's/\x1b\[[0-9;]*m//g' "$LOG_FILE" | mail -a "Content-Type: text/plain; charset=UTF-8" -s "$SUBJECT" "$EMAIL"
IO:success "Relatório enviado para $EMAIL."
}

# ========================== AUDITORIA COMPLETA ==========================

audit_total() {
lock_wordpress off
procura_arq_includes

run "chattr -i $WP_PATH/php.ini" "Destrava php.ini"
run "rm -f $WP_PATH/php.ini" "Remove php.ini para recriar"
run "find $WP_PATH -type f -name '.htaccess' -delete" "Remove .htaccess antigos"

IO:info "Verificando checksums..."
if ! $DRY_RUN; then
sudo -u www-data wp core verify-checksums --path=$WP_PATH >> $LOG_FILE 2>&1
else
IO:info "[dry-run] Verificação de integridade do WordPress"
fi

run "rm -rf $WP_PATH/wp-admin" "Remove wp-admin"
run "rm -rf $WP_PATH/wp-includes" "Remove wp-includes"
run "sudo -u www-data wp core download --force --locale=pt_BR --path=$WP_PATH" "Reinstala o núcleo do WordPress"

IO:info "Criando php.ini seguro..."
if ! $DRY_RUN; then
echo "disable_functions = exec,shell_exec,system,passthru,pcntl_exec,proc_open" > $WP_PATH/php.ini
else
IO:info "[dry-run] Criar php.ini com funções perigosas desabilitadas"
fi
run "chattr +i $WP_PATH/php.ini" "Trava php.ini"

gerar_lista_branca
verificar_arquivos_temas
adicionar_htaccess_padrao

run "chattr +i $WP_PATH/index.php" "Trava index.php"
run "chattr +i $WP_PATH/wp-settings.php" "Trava wp-settings.php"
run "chattr +i $WP_PATH/wp-config.php" "Trava wp-config.php"

run "chattr +i $WP_PATH/wp-content/plugins" "Trava plugins"
run "chattr +i $WP_PATH/wp-content/themes" "Trava temas"

lock_wordpress on
gerar_relatorio

IO:success "Auditoria completa."
}

# ========================== EXECUÇÃO ==========================

audit_total

✉️ O que acontece ao final?

O script:

  • Rodando apenas com o diretório nos argumentos, ele irá rodar em modo — dry-run, ou seja, sem modificar nada
  • Para rodar e executar as ações, rode como ./script.sh caminho-do-wordpress — run
  • Envia um relatório com tudo que foi encontrado e corrigido;
  • Reforça a proteção dos arquivos principais;
  • Restaura a integridade da instalação;
  • E deixa o site rodando com segurança sem comprometer seu conteúdo, banco de dados ou uploads.

✅ Conclusão

Manter seu WordPress seguro não precisa ser um bicho de sete cabeças. Com automação, boas práticas e atenção aos sinais, é possível blindar sua instalação sem perder produtividade.

Salve este script, agende auditorias periódicas e durma mais tranquilo sabendo que seu site está protegido.

Se você gostou deste artigo, deixe um comentário, compartilhe e acompanhe novas dicas sobre segurança da informação!

Sobre o Autor

Osvaldo Janeri Filho

Osvaldo Janeri Filho

Perito Digital especializado em perícia digital, nulidade de provas digitais, contratos digitais e cibersegurança. Executivo em Tecnologia & Segurança da Informação com mais de 15 anos de experiência no mercado.

Perícia Digital LGPD/GDPR Cibersegurança Direito Digital

Artigos Relacionados

Precisa de Consultoria Especializada?

Conte com minha expertise em perícia digital, direito eletrônico e cibersegurança. Agende uma reunião de 20 minutos para discutir seu caso específico.