
Auditoria ao .htaccess: porque é que o site devolve 500 e que regras não funcionam
Arraste o ficheiro — a ferramenta encontra o BOM, as diretivas mortas, as regras com alto risco de erro 500 e os sinais de intervenção alheia. O ficheiro é lido no seu navegador e não é enviado para lado nenhum.
O texto foi colado manualmente, pelo que o bloco de verificações de bytes foi ignorado. Para ver o BOM, os CRLF e os caracteres invisíveis, arraste o próprio ficheiro.
Um .htaccess limpo não cura uma invasão. Se o site estiver comprometido, o código malicioso vive no PHP e o .htaccess é apenas a consequência: o dropper reescreve o ficheiro poucos minutos depois de o limpar. A ordem é a inversa — primeiro encontrar o código executável, depois arrumar a configuração.
Aqui aparecerá o ficheiro de origem com os números de linha.
As linhas com achados estão marcadas com !: vermelhas são erros, âmbar são avisos. Os caracteres invisíveis e não imprimíveis são mostrados com um ponto · — no próprio ficheiro, no lugar deles não há nada.
A limpeza remove o BOM, converte as quebras de linha para LF, retira os caracteres não imprimíveis, substitui os espaços inquebráveis por espaços normais e acrescenta uma quebra de linha final. As diretivas não são alteradas. O ficheiro é guardado como htaccess-clean.txt — mude-lhe o nome para .htaccess antes de o enviar para o servidor.
# BEGIN WordPress
# The directives (lines) between "BEGIN WordPress" and "END WordPress" are
# dynamically generated, and should only be modified via WordPress filters.
# Any changes to the directives between these markers will be overwritten.
<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>
# END WordPress
É exatamente isto que o WordPress escreve sozinho. Coloque as suas regras acima da linha # BEGIN WordPress: tudo o que está entre os marcadores é reescrito sempre que guarda as definições das ligações permanentes.
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L]
</IfModule>
# END WordPress
Para um multisite em subdomínios o bloco é o mesmo, mas sem o prefixo ^([_0-9a-zA-Z-]+/)? nas três últimas regras: RewriteRule ^(wp-(content|admin|includes).*) $1 [L] e RewriteRule ^(.*\.php)$ $1 [L].
Substituir o bloco não repõe as ligações permanentes por si só: depois da alteração, vá a Definições → Ligações permanentes e clique em «Guardar» — o WordPress verifica o bloco e reescreve-o se for preciso.
O ficheiro é lido no seu navegador — o seu conteúdo não é enviado para lado nenhum nem guardado.
Porquê um ficheiro e não texto colado
A causa mais frequente de um erro 500 depois de editar o .htaccess nem sequer se vê no texto. É o BOM — três bytes invisíveis no início do ficheiro, acrescentados pelo Bloco de notas do Windows ao gravar em UTF-8. O Apache considera-os parte da primeira diretiva e não consegue analisá-la. É por isso que a ferramenta recebe o próprio ficheiro: só assim é possível ler os bytes e ver o BOM, as mudanças de linha ao estilo Windows e os caracteres invisíveis dentro das linhas. O segundo grupo de problemas são as diretivas que não fazem nada, mas parecem funcionais. mod_gzip_on é sintaxe do Apache 1.3; nos servidores atuais é ignorada em silêncio, enquanto se acredita durante anos que a compressão está ligada. Um bloco ExpiresByType envolvido numa verificação de mod_headers.c em vez de mod_expires.c também não funciona — e sem um aviso ninguém repara. Em terceiro lugar, php_value e php_flag. Só funcionam quando o PHP está carregado como módulo do Apache. Em alojamentos modernos com PHP-FPM, essa linha ou é ignorada ou devolve logo um 500. E, à parte, sobre segurança: se o ficheiro tiver regras que redirecionam os visitantes conforme o motor de busca de onde vieram, ou que escondem o redirecionamento do administrador, isso é um sinal típico de compromisso. Mas um .htaccess limpo não cura a invasão: quase sempre há algures nos ficheiros um script PHP que o volta a escrever.
