
Guia abrangente para endurecer instalações WordPress: abrange alterações de usuário admin, imposição de HTTPS, segurança de plugins, permissões de arquivos e configuração do servidor para sites corporativos estáticos.
Este documento foi escrito com o objetivo de ser adequado para aplicações web desenvolvidas com WordPress que não interagem com utilizadores. Destina-se principalmente a páginas de marca corporativas, várias visualizações estáticas, páginas de recrutamento e sites semelhantes.
Para sites onde os utilizadores se registam e usam livremente o site, como comunidades abertas, alguns itens deste documento podem não ser aplicáveis. Tenha isto em mente ao ler.
Este documento não inclui todo o conteúdo necessário para proteger o WordPress.
No entanto, inclui informações gerais e detalhadas a um nível que permite avaliações de risco de segurança e respostas a vulnerabilidades com base no guia.
Se achar útil, por favor, dê uma "estrela"🌟 para apoiar melhorias futuras.
Quando instala o WordPress, o nome de utilizador admin padrão é "admin", a menos que o altere durante o processo de configuração. O nome de conta "admin" é amplamente conhecido, por isso deve ser alterado para um nome diferente. Se continuar a usar "admin" como nome de utilizador admin, um atacante pode tentar um ataque de força bruta usando "admin" para obter acesso ao seu site WordPress.
Se um atacante obtiver acesso à conta admin do WordPress, terá controlo total sobre o site. O nome de utilizador admin padrão do WordPress deve ser alterado para um nome diferente.
Auditoria:
Remediação:
Nota:
Por padrão, o WordPress tem cinco funções de utilizador - "Administradores", "Editores", "Autores", "Colaboradores", "Subscritores"
Estas funções permitem controlar que tarefas os utilizadores podem realizar no seu site, atribuindo permissões adequadas. Se as funções e permissões de utilizador não forem geridas adequadamente, os utilizadores podem obter acesso desnecessário a funcionalidades críticas, representando um risco de segurança significativo.
Auditoria:
Remediação:
Nota:
O WordPress inclui uma funcionalidade de registo de utilizador incorporada. Esta funcionalidade está desativada por padrão, mas pode ser ativada por um administrador.
Se esta funcionalidade estiver ativada, qualquer pessoa pode registar-se e potencialmente aceder ao painel de administração do WordPress, o que pode levar a problemas de segurança. Para a maioria dos sites que não se destinam a operar como comunidades abertas, a funcionalidade de registo de utilizador é desnecessária e deve permanecer desativada.
Auditoria:
Usando um navegador web

Usando curl
(response) HTTP/1.1 302 Moved Temporarily cache-control: no-cache, no-store, must-revalidate, max-age=0 content-type: text/html; charset=UTF-8 server: Apache content-length: 0 ... location: https://yourwordpress.com/wp-login.php?registration=disabled
**Remediação:**
- Se o registro de usuários estiver ativado, desative-o.
- Desmarque "Anyone can register"

## 4. Garanta que o Editor de Arquivos de Plugin esteja Desativado
Se um invasor conseguir acessar uma conta de Administrador do WordPress, ele pode assumir o controle total do seu site.
Eles podem editar o código do seu tema e plugins através do recurso "Editor" embutido, enviar scripts maliciosos, desfigurar seu site, enviar spam para seus usuários e muito mais.
Hacks comuns através desses editores incluem injeções SQL, hacks de spam de SEO e spam de SEO japonês.
**Auditoria:**
- Verifique se o editor de arquivos está desativado.
- Verifique se você pode acessar o editor através de Aparência > Editor ou Plugins > Editor de Plugins.
**Remediação:**
- Se o editor de arquivos estiver ativado, desative-o seguindo estas etapas:
1. Acesse seu arquivo wp-config.php usando o Gerenciador de Arquivos ou FTP
2. Abra o arquivo wp-config.php para edição.
3. Role até o final do arquivo (se estiver usando o wp-config.php padrão).
4. Localize a seguinte linha:
`
/* That’s all, stop editing! Happy publishing. */
`
5. Acima desta linha, adicione o seguinte código:
`
define('DISALLOW_FILE_EDIT', true);
`
6. Salve as alterações e feche o editor.
7. Volte ao painel do WordPress e confirme que as opções do editor não estão mais disponíveis.
## 5. Garanta que Plugins Não Utilizados e Desnecessários estejam Desativados
Muitas vulnerabilidades no WordPress decorrem de problemas de segurança em plugins.
Os plugins são de código aberto, o que facilita para invasores encontrarem e explorarem vulnerabilidades.
É crucial manter os plugins que você usa atualizados e desativar quaisquer plugins não utilizados para evitar possíveis explorações.
**Auditoria:**
- Verifique se os plugins não utilizados e desnecessários estão desativados.
- Verifique se os plugins não utilizados e desnecessários estão desativados.
**Remediação:**
- Desative quaisquer plugins não utilizados e desnecessários seguindo estas etapas:
**Use o Plugin Check - PCP:**
- PCP: https://wordpress.org/plugins/plugin-check
1. Instale e Ative o Plugin Check (PCP):
- Vá para o painel de administração do WordPress
- Navegue até Plugins > Adicionar Novo.
- Pesquise por "Plugin Check" e instale, ative-o.
2. Execute uma verificação de plugin:
- No painel do WordPress, vá para o menu Plugin Check.
- Selecione os plugins que deseja verificar e execute a varredura.
3. Analise os resultados da varredura:
- O PCP analisará o código do plugin e fornecerá um relatório, incluindo:
- Conformidade com os Padrões de Código: Quão bem o plugin segue os padrões de codificação do WordPress.
- Problemas de Segurança: Vulnerabilidades potenciais ou código malicioso.
- Problemas de Desempenho: O impacto no desempenho do site.
- Problemas de Compatibilidade: Se o plugin é compatível com outros plugins e temas.
4. Identifique Plugins Problemáticos:
- Se o relatório destacar vulnerabilidades de segurança significativas, código malicioso ou numerosas violações de padrões de codificação, o plugin é provavelmente "suspeito".
- Tenha cuidado com plugins que fazem solicitações externas desnecessárias ou executam consultas excessivas ao banco de dados.
5. Resolva os Problemas:
- Corrija os problemas identificados atualizando ou encontrando os problemas nas páginas dos plugins.
- Evite usar plugins com problemas graves de segurança. Encontre plugins alternativos quando necessário.
**Gerenciamento de Plugins:**
1. Seleção de Plugins:
- Use Repositórios Oficiais, Verifique Avaliações e Classificações, Verifique a Credibilidade do Desenvolvedor
- Não use plugins desconhecidos ou não verificados
2. Atualizações Regulares
- Mantenha os plugins atualizados para garantir que você tenha as últimas correções de segurança.
3. Desative e Exclua Plugins Não Utilizados
- Mesmo plugins inativos podem representar um risco de segurança, então remova-os se não forem usados.
- Minimize Plugins: Use apenas os plugins essenciais
## 6. Garanta que o WordPress Esteja Configurado para Usar Apenas HTTPS, Incluindo o Admin do WordPress
Hoje, a maioria dos sites é configurada para operar sobre SSL (HTTPS).
No entanto, alguns servidores web ainda podem estar configurados erroneamente para lidar com conexões HTTP e HTTPS.
Isso pode permitir o acesso ao WordPress por ambos os protocolos, o que é um risco de segurança. O WordPress, incluindo o Admin do WordPress, deve ser forçado a usar exclusivamente HTTPS.
**Auditoria:**
- Verifique se o WordPress, incluindo o admin do WordPress, está configurado para ser acessível apenas via HTTPS.
- Verifique a configuração do VirtualHost do servidor web para garantir que não haja VirtualHosts HTTP configurados.
**Remediação:**
- Se o acesso HTTP for possível, primeiro revise e modifique as configurações do servidor web.
- Se o servidor tiver VirtualHosts HTTP, redirecione-os para HTTPS ou exclua os VirtualHosts HTTP.
- Se necessário, ative o recurso "FORCE_SSL_ADMIN" para forçar o acesso HTTPS para o Admin do WordPress.
**Passos para Ativar o FORCE_SSL_ADMIN:**
1. Acesse seu arquivo wp-config.php usando o Gerenciador de Arquivos ou FTP.
2. Abra o arquivo wp-config.php para edição.
3. Role até o final do arquivo (se estiver usando o wp-config.php padrão).
4. Localize a seguinte linha:
`
/* That’s all, stop editing! Happy publishing. */
`
5. Acima desta linha, adicione o seguinte código:
`
define('FORCE_SSL_ADMIN', true);`
`
6. Salve as alterações e feche o editor.
Volte ao painel do WordPress e faça login novamente para garantir que o Admin do WordPress seja acessível apenas via HTTPS.
**Redirecione HTTP para HTTPS no Servidor Web:**
1. Para Apache:
```
<VirtualHost *:80>
ServerName yourwordpress.com
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</VirtualHost>
```
2. Para Nginx:
```
server {
listen 80;
server_name yourwordpress.com;
location / {
return 301 https://$host$request_uri;
}
}
```
Ao garantir que o WordPress e o Admin do WordPress sejam acessíveis apenas via HTTPS, você pode aumentar significativamente a segurança do seu site, protegendo dados e prevenindo acessos não autorizados.
## 7. Garanta que as Restrições de Acesso por IP (ACL) sejam Aplicadas
Verifique se as restrições de acesso por IP estão aplicadas
Para operar o WordPress com segurança, é essencial aplicar restrições de acesso por IP a certas URLs, incluindo o Admin do WordPress, para evitar que usuários indesejados, computadores e bots acessem-nas. Isso envolve permitir o acesso apenas de endereços IP permitidos, como IPs de administradores. Além disso, desativar recursos não utilizados é necessário para minimizar superfícies de ataque.
As URLs a serem protegidas incluem Admin do WordPress, registro de usuário (wp-signup.php), JSON REST API e o recurso XML-RPC.
Este guia de segurança é direcionado a sites orientados a serviços, como blogs empresariais, páginas de recrutamento, sites de marca e sites promocionais, onde a interação do usuário é mínima e o conteúdo é principalmente apresentado.
Ao implementar restrições de acesso por IP, você pode reduzir significativamente o risco de acesso não autorizado e melhorar a segurança geral do seu site.
### 7.1. Garanta que as restrições de acesso por IP sejam aplicadas ao admin do WordPress.
O caminho de acesso ao admin do WordPress é fixo na forma de wp-login.php ou /wp-admin, tornando-o facilmente acessível a usuários não autorizados.
Garanta que a restrição de acesso por IP seja aplicada para evitar acesso não autorizado à página de admin.
**Auditoria:**
- Verifique se as restrições de acesso por IP estão aplicadas para o admin do WordPress.
- Na maioria dos casos, isso é configurado no servidor web (Apache, Nginx).
**Remediação:**
- Se as restrições de acesso por IP não estiverem aplicadas, implemente-as.
- A seguir estão métodos para aplicar restrições de acesso por IP usando servidores web Apache e Nginx.
**Aplicando Restrição de Acesso por IP ao Admin do WordPress:**
- /wp-admin, wp-login.php
1. Para Apache:
```
# Diretiva Files
<Files "wp-login.php">
Require ip 10.10.77.49 # Substitua pelo seu endereço IP
</Files>
# Diretiva FilesMatch
<FilesMatch "^wp-login\.php$">
Require all granted
</FilesMatch>
# Diretiva combinada Directory e Files
<Directory /www/vhosts/seuwordpress>
Require all granted
AllowOverride None
<Files "wp-login.php">
Require ip 10.10.77.49 # Substitua pelo seu endereço IP
</Files>
</Directory>
# Diretiva Location
<Location "/wp-admin">
Require ip 10.10.77.49 # Substitua pelo seu endereço IP
</Location>
<Location "/wp-login.php">
Require ip 10.10.77.49 # Substitua pelo seu endereço IP
</Location>
```
2. Para Nginx:
```
location /wp-admin {
allow 10.10.77.49; # Substitua pelo seu endereço IP
deny all;
}
location ~* \wp-login.php {
allow 10.10.77.49; # Substitua pelo seu endereço IP
deny all;
}
```
### 7.2. Restrinja o Acesso por IP ou Desative o Recurso JSON REST API
O WordPress fornece duas funcionalidades REST (xmlrpc, json rest api) e está ativado por padrão na instalação do WordPress.
A REST API fornece endpoints para os tipos de dados do WordPress, permitindo interação remota com o site para tarefas como consultar posts ou dados, modificar recursos, editar e excluir.
Para a maioria dos WordPress, o recurso REST API não é essencial.
Ativá-lo pode expor o WordPress a ataques DDoS e pode resultar em consumo de recursos e lentidão do site.
**Auditoria:**
- Verifique se o recurso JSON REST API está ativado. (Padrão: Ativado)```
# curl -i -k https://yourwordpress.com/wp-json
(response)
HTTP/1.1 200 OK
cache-control: no-cache, no-store, must-revalidate, max-age=0
content-type: text/html; charset=UTF-8
...
Server: Apache
{"name":"mywordress","description":"".......................
Remediação:
Instalar o Plugin "Disable REST API", Ativar:
Restrição de Acesso por IP para a JSON REST API:
<Location "/wp-json">
Require ip 10.10.77.49 # Replace with your IP address
</Location>
location ~ ^/wp-json/ {
allow 10.10.77.49; # Replace with your allowed IP address
deny all;
}
Similar à JSON REST API, é aconselhável desabilitar a XML-RPC API, já que não é necessária para a maioria das instalações do WordPress.
Se a REST API for necessária, recomenda-se usar a JSON REST API em vez disso.
XML-RPC possui duas principais vulnerabilidades:
Ataques de força bruta:
Ataques de Negação de Serviço via Pingback:
Se XML-RPC estiver habilitado, ainda pode ser explorado para tais ataques.
Auditoria:
(response) HTTP/1.1 405 Method Not Allowed Date: Mon, 25 Jun 2018 08:30:24 GMT Server: Apache Allow: POST Content-Length: 42 Content-Type: text/plain; charset=UTF-8
XML-RPC server accepts POST requests only.
**Remediação:**
- Desabilitar o recurso XML-RPC usando plugin
**Instalar o plugin "Disable XML-RPC-API", Ativar:**
1. Acesse o painel de administração do WordPress
2. Navegue até Plugins > Adicionar Novo.
3. Pesquise por "[Disable XML-RPC-API](https://wordpress.org/plugins/disable-xml-rpc-api/)" e instale, ative-o.
4. A XML-RPC-API agora está desabilitada.
**Sobre ataques de pingbacks XML-RPC:**
1. Verifique se o XML-RPC está habilitado
```
# curl -i -k https://yourwordpress.com/xmlrpc.php
(response)
HTTP/1.1 405 Method Not Allowed
Date: Mon, 25 Jun 2018 08:30:24 GMT
Server: Apache
Allow: POST
Content-Length: 42
Content-Type: text/plain; charset=UTF-8
XML-RPC server accepts POST requests only.
```
2. Pesquisando métodos XML-RPC disponíveis
```
(request)
POST /xmlrpc.php HTTP/1.1
Host: yourwordpress.com
Content-Length: 135
<?xml version="1.0" encoding="utf-8"?>
<methodCall>
<methodName>system.listMethods</methodName>
<params></params>
</methodCall>
(response)
HTTP/1.1 200 OK
cache-control: no-cache, no-store, must-revalidate, max-age=0
...
Server: Apache
Content-Length: 4272
Content-Type: text/xml; charset=UTF-8
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<params>
<param>
<value>
<array><data>
<value><string>system.multicall</string></value>
<value><string>system.listMethods</string></value>
<value><string>system.getCapabilities</string></value>
<value><string>demo.addTwoNumbers</string></value>
<value><string>demo.sayHello</string></value>
<value><string>pingback.extensions.getPingbacks</string></value>
<value><string>pingback.ping</string></value>
<value><string>mt.publishPost</string></value>
...
<value><string>wp.getUsersBlogs</string></value>
</data></array>
</value>
</param>
</params>
</methodResponse>
```
3. Realizar pingbacks
- O sucesso de um ataque de pingback e métodos específicos de verificação não são descritos.
```
(request)
POST /xmlrpc.php HTTP/1.1
Host: yourwordpress.com
Content-Length: 303
<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>pingback.ping</methodName>
<params>
<param>
<value><string>call-back url for pingback result</string></value>
</param>
<param>
<value><string>https://yourwordpress.com/</string></value>
</param>
</params>
</methodCall>
(response)
HTTP/1.1 200 OK
...
Server: Apache
Content-Length: 370
Content-Type: text/xml; charset=UTF-8
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<fault>
<value>
<struct>
<member>
<name>faultCode</name>
<value><int>0</int></value>
</member>
<member>
<name>faultString</name>
<value><string></string></value>
</member>
</struct>
</value>
</fault>
</methodResponse>
```
### 7.4. Desabilitar WP-Cron ou Restringir Recurso
No WordPress, o WP-Cron (wp-cron.php) é usado para automatizar tarefas como publicação programada de posts, verificações de atualizações de plugins/temas e envio de e-mails de notificação.
O WP-Cron essencialmente funciona verificando a lista de tarefas agendadas toda vez que uma página é carregada.
O problema surge quando há carregamento pesado de páginas.
Como as tarefas do WP-Cron são executadas a cada carregamento de página, múltiplos acessos repetidos resultam em invocações correspondentes do WP-Cron. Consequentemente, os recursos do sistema podem se tornar escassos, fazendo com que o site fique lento ou até pare.
Isso é uma ocorrência real e é frequentemente explorada em ataques de vulnerabilidade direcionados ao WordPress.
Se o WP-Cron não for necessário, é aconselhável desativá-lo.
Se necessário, restrinja o acesso apenas a hosts locais.
**Auditoria:**
- Verifique se o WP-Cron está habilitado. (Padrão: Habilitado)```
# curl -i -k https://yourwordpress.com/wp-cron.php
(response)
HTTP/1.1 200 ok
Date: Mon, 25 Jun 2018 08:30:24 GMT
Server: Apache
Allow: POST
Content-Length: 42
Content-Type: text/plain; charset=UTF-8
Remediação:
Passos para Desativar o WP-Cron:
/* That’s all, stop editing! Happy publishing. */define('DISABLE_WP_CRON', true);# Files Directive
<Files "wp-cron.php">
Require ip 127.0.0.1 # localhost only
</Files>
# FilesMatch Directive
<FilesMatch "^wp-cron\.php$">
Require ip 127.0.0.1 # localhost only
</FilesMatch>
# Location Directive
<Location "/wp-cron.php">
Require ip 127.0.0.1 # localhost only
</Location>
location = /wp-cron.php {
allow 127.0.0.1;
deny all;
access_log off;
log_not_found off;
}
Passos para Ativar "ALTERNATE_WP_CRON":
/* That’s all, stop editing! Happy publishing. */define( 'ALTERNATE_WP_CRON', true );# Files Directive
<Files "wp-cron.php">
Require ip 127.0.0.1 # localhost only
</Files>
# FilesMatch Directive
<FilesMatch "^wp-cron\.php$">
Require ip 127.0.0.1 # localhost only
</FilesMatch>
# Location Directive
<Location "/wp-cron.php">
Require ip 127.0.0.1 # localhost only
</Location>
location = /wp-cron.php {
allow 127.0.0.1;
deny all;
access_log off;
log_not_found off;
}
Exemplo: Usando Cron do Sistema (crontab):
.. ... */10 * * * * curl http://yourwordpress.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1
*/10 * * * * cd /var/www/yourwordpress.com/htdocs; php /var/www/yourwordpress.com/htdocs/wp-cron.php?doing_wp_cron > /dev/null 2>&1
*/10 * * * * cd /var/www/example.com/htdocs; wp cron event run --due-now > /dev/null 2>&1
**Sobre como realizar ataque DoS usando wp-cron.php:**
- Enviar um volume extenso de requisições para o wp-cron.php
- Isso resulta no script consumindo uma quantidade excessiva de recursos, eventualmente sobrecarregando o servidor


## 8. Configuração do Sistema para WordPress Seguro.
Garantir a operação segura do WordPress requer uma configuração adequada do servidor web e o hardening dos componentes de backend.
Aqui estão vários itens essenciais que devem ser verificados e implementados.
### 8.1. Garantir o Uso de Versões do WordPress e PHP que não estejam em Fim de Vida (EOL)
Para manter uma instalação segura do WordPress, é essencial usar versões do WordPress e PHP que não estejam em fim de vida (EOL).
Versões EOL não são mais suportadas e não recebem atualizações de segurança, deixando seu site vulnerável a problemas de segurança não corrigidos.
Usar versões suportadas garante que quaisquer vulnerabilidades descobertas sejam prontamente tratadas, protegendo seu site contra possíveis ataques.
Aqui está o que você precisa fazer para verificar e atualizar suas versões do WordPress e PHP:
**Auditoria:**
- Verifique se suas versões atuais do WordPress e PHP não estão em EOL.
**Remediação:**
- Instale e execute versões do WordPress e PHP que não estejam em EOL.
- Em maio de 2024, a versão suportada do WordPress é 6.5 e superior. As versões suportadas do PHP são 8.1, 8.2 e 8.3.
- Se você usa um serviço de hospedagem web, aproveite os recursos de alternância de versão para garantir que está usando versões suportadas tanto do WordPress quanto do PHP.
**Status EOL em maio de 2024**
1. PHP: [supported-versions](https://www.php.net/supported-versions.php)
- Versões Atualmente Suportadas: 8.1, 8.2, 8.3
2. WordPress: [current-releases](https://wordpress.org/download/releases/)
- Versões Atualmente Suportadas: série 6.5
**Exemplo: PHP no RockyLinux 8.5**
- No RockyLinux 8.5, as versões padrão do PHP disponíveis são 7.2, 7.3 e 7.4.
```
# dnf module list php
Rocky Linux 8 - AppStream
Name Stream Profiles Summary
php 7.2 [d] common [d], devel, minimal PHP scripting language
php 7.3 common [d], devel, minimal PHP scripting language
php 7.4 common [d], devel, minimal PHP scripting language
Hint: [d]efault, [e]nabled, [x]disabled, [i]nstalled
# dnf module enable php:7.4
==============================================================================================
Package Architecture Version Repository Size
==============================================================================================
Enabling module streams:
httpd 2.4
php 7.4
Transaction Summary
==============================================================================================
Is this ok [y/N]: y
Complete!
```
- O PHP 7 já atingiu o fim de vida (EOL); recomenda-se a atualização para o PHP 8.
- O PHP 8 pode ser instalado a partir do repositório REMI.
- Aqui está um exemplo de como habilitar e instalar o PHP 8.2 usando o REMI:
```
# Install PHP 8.2 in Rocky Linux 8
# dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
# dnf -y install https://rpms.remirepo.net/enterprise/remi-release-8.rpm
# dnf -y install yum-utils
# dnf module reset php
# dnf module install php:remi-8.2
Last metadata expiration check: 0:00:39 ago on Tue 13 Dec 2022 07:19:26 AM UTC.
Dependencies resolved.
=======================================================================================================================================
Package Architecture Version Repository Size
=======================================================================================================================================
Installing group/module packages:
php-cli x86_64 8.2.0-1.el8.remi remi-modular 5.4 M
php-common x86_64 8.2.0-1.el8.remi remi-modular 1.3 M
php-fpm x86_64 8.2.0-1.el8.remi remi-modular 1.9 M
php-mbstring x86_64 8.2.0-1.el8.remi remi-modular 574 k
php-xml x86_64 8.2.0-1.el8.remi remi-modular 254 k
Installing dependencies:
httpd-filesystem noarch 2.4.37-51.module+el8.7.0+1059+126e9251 appstream 41 k
libxslt x86_64 1.1.32-6.el8 baseos 249 k
oniguruma5php x86_64 6.9.8-1.el8.remi remi-safe 212 k
Installing weak dependencies:
nginx-filesystem noarch 1:1.14.1-9.module+el8.4.0+542+81547229 appstream 23 k
Installing module profiles:
php/common
Enabling module streams:
httpd 2.4
nginx 1.14
php remi-8.2
Transaction Summary
=======================================================================================================================================
Install 9 Packages
# dnf update
# dnf install php
Last metadata expiration check: 0:00:23 ago on Tue 13 Dec 2022 07:29:55 AM UTC.
Dependencies resolved.
=======================================================================================================================================
Package Architecture Version Repository Size
=======================================================================================================================================
Installing:
php x86_64 8.2.0-1.el8.remi remi-modular 1.8 M
Installing dependencies:
apr x86_64 1.6.3-12.el8 appstream 128 k
apr-util x86_64 1.6.1-6.el8.1 appstream 104 k
httpd x86_64 2.4.37-51.module+el8.7.0+1059+126e9251 appstream 1.4 M
httpd-tools x86_64 2.4.37-51.module+el8.7.0+1059+126e9251 appstream 108 k
libsodium x86_64 1.0.18-2.el8 epel 162 k
mailcap noarch 2.1.48-3.el8 baseos 38 k
mod_http2 x86_64 1.15.7-5.module+el8.6.0+823+f143cee1 appstream 153 k
rocky-logos-httpd noarch 86.3-1.el8 baseos 24 k
Installing weak dependencies:
apr-util-bdb x86_64 1.6.1-6.el8.1 appstream 23 k
apr-util-openssl x86_64 1.6.1-6.el8.1 appstream 26 k
php-opcache x86_64 8.2.0-1.el8.remi remi-modular 633 k
php-pdo x86_64 8.2.0-1.el8.remi remi-modular 166 k
php-sodium x86_64 8.2.0-1.el8.remi remi-modular 105 k
Transaction Summary
=======================================================================================================================================
Install 14 Packages
Total download size: 4.8 M
Installed size: 14 M
Is this ok [y/N]: y
# php -v
PHP 8.2.0 (cli) (built: Dec 6 2022 14:26:47) (NTS gcc x86_64)
Copyright (c) The PHP Group
Zend Engine v4.2.0, Copyright (c) Zend Technologies
with Zend OPcache v8.2.0, Copyright (c), by Zend Technologies
```
**Nota:**
- Para instruções detalhadas sobre a instalação do PHP a partir do repositório REMI: [rpms.remirepo.net](https://rpms.remirepo.net/)
- Documentação sobre compatibilidade entre WordPress e PHP: [php-compatibility-and-wordpress-versions](https://make.wordpress.org/core/handbook/references/php-compatibility-and-wordpress-versions/)
### 8.2. Garantir que Apenas as Extensões PHP Necessárias para o WordPress Estejam Ativadas
Garanta que apenas as extensões PHP necessárias para o seu site WordPress estejam ativadas.
Extensões desnecessárias podem aumentar a superfície de ataque do seu site e podem expor o WordPress a vulnerabilidades de segurança.
Ao ativar apenas as extensões necessárias, você pode minimizar riscos potenciais e melhorar a segurança geral.
Abaixo estão as necessárias para que um site WordPress funcione corretamente. **(Não é uma lista para fins de hardening de segurança)**
| Extensão | Descrição |
|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| json | Usado para comunicações com outros servidores e processamento de dados no formato JSON. |
| mysqli | Conecta-se ao MySQL para interações com o banco de dados. |
| curl | Realiza operações de requisição remota. |
| dom | Usado para validar o conteúdo do widget de texto e configurar automaticamente o IIS7+. |
| exif | Trabalha com metadados armazenados em imagens. |
| fileinfo | Usado para detectar o tipo MIME de uploads de arquivos. |
| hash | Usado para hashing, incluindo senhas e pacotes de atualização. |
| igbinary | Aumenta o desempenho como substituto direto do serializador PHP padrão. |
| imagick | Fornece melhor qualidade de imagem para uploads de mídia. Veja WP_Image_Editor para detalhes. Redimensionamento de imagem mais inteligente (para imagens menores) e suporte a miniaturas de PDF, quando o Ghost Script também estiver disponível. |
| intl | Permite operações sensíveis à localidade, incluindo, mas não se limitando a, formatação, transliteração, conversão de codificação, operações de calendário, colação conforme, localização de limites de texto e trabalho com identificadores de localidade, fusos horários e grafemas. |
| mbstring | Usado para processar corretamente texto UTF8. |
| openssl | Conexões baseadas em SSL com outros hosts. |
| pcre | Aumenta o desempenho da correspondência de padrões em buscas de código. |
| xml | Usado para análise de XML, como de um site de terceiros. |
| zip | Usado para descompactar plugins, temas e pacotes de atualização do WordPress. |
| bc | Para matemática de precisão arbitrária, que suporta números de qualquer tamanho e precisão de até 2147483647 dígitos decimais. |
| filter | Usado para filtrar com segurança a entrada do usuário. |
| image | Se o Imagick não estiver instalado, a Biblioteca Gráfica GD é usada como substituto funcionalmente limitado para manipulação de imagens. |
| iconv | Usado para converter entre conjuntos de caracteres. |
| shmop | Shmop é um conjunto fácil de usar de funções que permite ao PHP ler, escrever, criar e excluir segmentos de memória compartilhada Unix. |
| simplexml | Usado para análise de XML. |
| sodium | Valida assinaturas e fornece bytes aleatórios de forma segura. |
| xmlreader | Usado para análise de XML. |
| zlib | Compressão e descompressão Gzip. |
Extensões essenciais podem ser encontradas aqui: [WordPress Hosting Handbook: PHP Extensions](https://make.wordpress.org/hosting/handbook/server-environment/#php-extensions)
**Auditoria:**
- Verifique se apenas as extensões PHP necessárias para o seu site WordPress estão ativadas.
**Remediação:**
- Remova quaisquer extensões desnecessárias. Às vezes, extensões são instaladas junto com plugins, que podem não ser necessárias para o seu site.
- Para verificar as extensões PHP atualmente ativadas, você pode revisar o arquivo **php.ini** ou usar a função **phpinfo()** para listar todas as extensões ativas.

- Certas extensões, se não forem necessárias, devem ser desativadas para evitar possíveis problemas de segurança.
- Por exemplo, extensões como exif, fileinfo, imap, soap, pdo_sqlite e opcache podem ser exploradas se deixadas ativas sem uso adequado.
- Se você estiver usando um serviço de hospedagem web, muitos provedores oferecem interfaces fáceis de usar para alternar configurações do PHP, incluindo ativar ou desativar extensões PHP. Usando esses recursos, você pode gerenciar extensões de forma eficaz.
### 8.3. Garantir a Segurança de Plugins com Recursos de Upload de Arquivos
Plugins com capacidade de upload de arquivos podem representar um risco significativo de segurança se não forem devidamente protegidos. Vulnerabilidades em funções de upload de arquivos podem permitir que invasores façam upload de web shells, potencialmente levando ao comprometimento total do sistema. Portanto, é crucial garantir que qualquer funcionalidade de upload de arquivos inclua mecanismos de validação e sanitização.
Por que isso é importante?
1. Validação de Extensão:
- O servidor deve validar as extensões de arquivo em relação a uma lista de permissões de tipos permitidos para evitar o upload de arquivos maliciosos.
2. Verificação do Tipo MIME:
- O tipo MIME do arquivo deve ser verificado para garantir que corresponda ao tipo esperado, adicionando uma camada extra de segurança.
3. Restrições de Caminho de Upload:
- Certifique-se de que não haja caminhos expostos que permitam acesso direto aos arquivos enviados sem validação.
Vulnerabilidades de upload de arquivos são particularmente perigosas porque fornecem um caminho direto para invasores fazerem upload de código executável e executarem comandos arbitrários. Vulnerabilidades de upload de arquivos são frequentemente mais fáceis de identificar e explorar em comparação com outras falhas de segurança, como injeção SQL.
**Auditoria:**
- Identifique plugins com funcionalidade de upload de arquivos no seu site WordPress.
- Verifique se esses plugins implementam verificações de validação adequadas para arquivos enviados, incluindo validação de extensão e tipo MIME.
**Remediação:**
- Se um plugin com funcionalidade de upload de arquivos não tiver validação adequada, melhore sua segurança ou remova o plugin.
- Abaixo estão exemplos de plugins WordPress populares com recursos de upload de arquivos e como eles lidam com a validação de arquivos.
**Exemplo: Plugins WordPress Populares com Manipulação de Upload de Arquivos**
1. Contact Form 7
- Contact Form 7 é um dos plugins de formulário mais amplamente utilizados no WordPress. Ele inclui funcionalidade básica de upload de arquivos com validação de extensão e tipo MIME.**Código para extensões permitidas e verificação de tipo MIME:**
```
function wpcf7_allowed_file_extensions() {
// Default allowed file extensions
$allowed_file_extensions = array(
'jpg', 'jpeg', 'png', 'gif', 'pdf', 'doc', 'docx',
'xls', 'xlsx', 'txt', 'csv', 'rtf', 'html', 'zip'
);
return $allowed_file_extensions;
}
function wpcf7_handle_upload( $file ) {
$allowed_mime_types = wpcf7_allowed_file_extensions();
$file_type = wp_check_filetype( $file['name'] );
// Check if the file type is allowed
if ( ! in_array( $file_type['ext'], $allowed_mime_types ) ) {
return new WP_Error( 'wpcf7_upload_failed', __( 'File type is not allowed.', 'contact-form-7' ) );
}
// Handle the file upload
$upload = wp_handle_upload( $file, array( 'test_form' => false ) );
// Check if the upload was successful
if ( isset( $upload['error'] ) ) {
return new WP_Error( 'wpcf7_upload_failed', $upload['error'] );
}
return $upload;
}
```
No Contact Form 7, a função `wpcf7_allowed_file_extensions()` retorna uma lista de extensões de arquivo permitidas,
e a função `wpcf7_handle_upload()` verifica se a extensão do arquivo está nesta lista antes de prosseguir com o upload.
2. WPForms
- O WPForms lida com uploads de arquivos verificando os tipos de arquivo permitidos.
**Código de exemplo para WPForms:**
```
function wpforms_get_file_types() {
// Return an array of allowed file types
return array( 'jpg', 'jpeg', 'png', 'gif', 'pdf', 'doc', 'docx' );
}
function wpforms_process_file_upload( $file ) {
$allowed_file_types = wpforms_get_file_types();
$file_type = wp_check_filetype( $file['name'] );
if ( ! in_array( $file_type['ext'], $allowed_file_types ) ) {
return new WP_Error( 'wpforms_upload_failed', __( 'File type is not allowed.', 'wpforms' ) );
}
$upload = wp_handle_upload( $file, array( 'test_form' => false ) );
if ( isset( $upload['error'] ) ) {
return new WP_Error( 'wpforms_upload_failed', $upload['error'] );
}
return $upload;
}
```
3. WooCommerce
- O WooCommerce também define e verifica as extensões de arquivo permitidas diretamente no seu código de manipulação de upload.
**Código de exemplo para WooCommerce:**
```
function woocommerce_handle_upload( $file ) {
$allowed_file_types = array( 'jpg', 'jpeg', 'png', 'gif', 'pdf', 'doc', 'docx' );
$file_type = wp_check_filetype( $file['name'] );
if ( ! in_array( $file_type['ext'], $allowed_file_types ) ) {
return new WP_Error( 'woocommerce_upload_failed', __( 'File type is not allowed.', 'woocommerce' ) );
}
$upload = wp_handle_upload( $file, array( 'test_form' => false ) );
if ( isset( $upload['error'] ) ) {
return new WP_Error( 'woocommerce_upload_failed', $upload['error'] );
}
return $upload;
}
```
**Exemplo: Plugin malicioso de upload de arquivos**
- Um plugin malicioso pode parecer legítimo, mas explorar a extensão fileinfo para contornar verificações de segurança:
```
<?php
/*
Plugin Name: Simple Malicious Upload
Description: A plugin with hidden malicious file upload capability.
Version: 1.0
*/
function simple_file_upload_menu() {
add_menu_page('File Upload', 'File Upload', 'manage_options', 'file-upload', 'simple_file_upload_page');
}
add_action('admin_menu', 'simple_file_upload_menu');
function simple_file_upload_page() {
?>
<h1>File Upload</h1>
<form method="post" enctype="multipart/form-data">
<input type="file" name="uploaded_file" />
<input type="submit" name="upload_file" value="Upload" />
</form>
<?php
if (isset($_POST['upload_file'])) {
simple_handle_file_upload();
}
}
function simple_handle_file_upload() {
if (!empty($_FILES['uploaded_file']['tmp_name'])) {
$file_tmp = $_FILES['uploaded_file']['tmp_name'];
$file_name = basename($_FILES['uploaded_file']['name']);
// Using fileinfo to check MIME type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type = finfo_file($finfo, $file_tmp);
finfo_close($finfo);
// Insecure handling: allows any PHP files to be uploaded
if ($mime_type === 'text/plain' || $mime_type === 'application/x-php') {
$upload_dir = wp_upload_dir();
$upload_file = $upload_dir['path'] . '/' . $file_name;
// Move the uploaded file to the uploads directory
if (move_uploaded_file($file_tmp, $upload_file)) {
echo "File uploaded successfully.";
} else {
echo "File upload failed.";
}
} else {
echo "Invalid file type.";
}
}
}
?>
```
**Explicação da Exploração:**
- O plugin malicioso permite o upload de arquivos PHP se o tipo MIME deles for `application/x-php.`
- Um invasor pode fazer upload de um web shell PHP usando essa funcionalidade.
- Uma vez enviado, o invasor acessa a URL do arquivo e executa comandos arbitrários.
**Exemplo: Código de Web Shell PHP**```
<?php
if (isset($_GET['cmd'])) {
echo "<pre>";
system($_GET['cmd']);
echo "</pre>";
}
?>
Demonstração do Ataque
http://yourwordpress.com/wp-content/uploads/webshell.php.http://yourwordpress.com/wp-content/uploads/webshell.php?cmd=ls, o atacante pode executar comandos arbitrários.Nota:
Garantir que as funções e configurações do PHP estejam devidamente configuradas pode melhorar significativamente a segurança do seu site WordPress. Configurações mal configuradas podem expor seu site a diversas vulnerabilidades, incluindo execução remota de código, divulgação de informações e sequestro de sessão. É crucial endurecer o PHP desabilitando ou configurando adequadamente essas funções.
Por quê isso é importante?
Execução Remota de Código:
allow_url_fopen e funções como exec podem permitir a execução remota de código, levando a um possível comprometimento do sistema.Divulgação de Informações:
display_errors e expose_php podem vazar informações confidenciais sobre a configuração do seu servidor, facilitando a localização de vulnerabilidades por atacantes.Segurança de Sessão:
session.cookie_secure e session.cookie_httponly, protegem os cookies de sessão contra acesso por scripts do lado do cliente ou transmissão por canais inseguros.Auditoria:
Remediação:
allow_url_fopen:
file_get_contents(), fopen(), include() e require() podem recuperar dados de locais remotos via FTP ou HTTP.allow_url_fopen para vários recursos.; (Optional) Disable allow_url_fopen, if not unnecessary
allow_url_fopen = Off
display_errors:
; Disable PHP errors not be displayed on your WordPress website
display_errors = Off
expose_php:
; Prevent exposing PHP version in HTTP response headers
expose_php = Off
session.cookie_secure
session.cookie_secure:
; Ensure session cookies are sent over HTTPS
session.cookie_secure = On
session.cookie_httponly
Exemplo: Abaixo está uma Lista de Funções PHP Desabilitadas em um WordPress Real``` system, exec, shell_exec, passthru, mysql_list_dbs, ini_alter, dl, symlink, link, chgrp, leak, popen, apache_child_terminate, virtual, mb_send_mail
### 8.5. Assegure que o Servidor Web Execute como um Utilizador Não-Root - Utilizador e Grupo Únicos e Não Privilegiados para a Aplicação do Servidor
Na maioria dos casos, os servidores web são executados como utilizadores como "www-data" (Debian/Ubuntu) ou "apache" (RHEL/CentOS).
Estes utilizadores são contas de serviço dedicadas, sem privilégios especiais no servidor, e são usados para designar o utilizador e o grupo que os processos worker do servidor web assumirão.
Se estes utilizadores tiverem privilégios de sistema ou estiverem a executar como root, devem ser alterados.
**Auditoria:**
- Verifique o utilizador que está a executar o processo do servidor web. (Especificamente, é o processo worker do servidor web.)
1. Para Apache:
```
# ps -ef | grep httpd
root 2257 1 0 Apr08 ? 00:00:01 /usr/local/apache/bin/httpd -k start
apache 5678 1234 0 Apr08 ? 00:00:00 /usr/sbin/httpd -k start
apache 5679 1234 0 Apr08 ? 00:00:00 /usr/sbin/httpd -k start
apache 5680 1234 0 Apr08 ? 00:00:00 /usr/sbin/httpd -k start
apache 5681 1234 0 Apr08 ? 00:00:00 /usr/sbin/httpd -k start
```
2. Para Nginx:
```
# ps -ef | grep nginx
root 626653 1 0 Apr08 ? 00:00:00 nginx: master process /usr/sbin/nginx
nginx 626654 626653 0 Apr08 ? 00:00:00 nginx: worker process
nginx 626655 626653 0 Apr08 ? 00:00:00 nginx: worker process
nginx 626656 626653 0 Apr08 ? 00:00:00 nginx: worker process
nginx 626657 626653 0 Apr08 ? 00:00:00 nginx: worker process
```
**Correção:**
- O servidor web deve executar como uma conta dedicada e não privilegiada.
- Na maioria dos casos, uma destas contas comuns, como "www-data", "apache", "nginx", "nobody" ou "daemon", é utilizada.
1. Para Apache:
```
# vim /etc/httpd/httpd.conf
..
...
User www-data
Group www-data
..
...
```
2. Para Nginx:
```
# vim /etc/nginx/nginx.conf
..
...
user daemon;
```
**Nota:**
- Os utilizadores de processo do servidor web não devem ter privilégios de login de shell. ```
# cat /etc/passwd | grep -i www-data
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
WordPress é construído com PHP, portanto uma configuração correta do sistema é necessária para executar código PHP adequadamente.
A execução de código PHP no WordPress é gerenciada pelo PHP-FPM, um Gerenciador de Processos FastCGI. Para garantir a operação segura do PHP-FPM, ele deve ser executado sob uma conta de serviço dedicada e não privilegiada.
Geralmente, a conta do processo do servidor web e a conta do PHP-FPM são configuradas como a mesma conta. No entanto, para maior segurança, é melhor executá-los sob contas separadas.
Aqui estão duas razões:
Isolamento de Processos:
Princípio do Menor Privilégio:
Auditoria:
root 1234 1 0 12:00 ? 00:00:01 php-fpm: master process (/etc/php-fpm.conf) php-fpm 5678 1234 0 12:00 ? 00:00:00 php-fpm: pool www php-fpm 5679 1234 0 12:00 ? 00:00:00 php-fpm: pool www php-fpm 5680 1234 0 12:00 ? 00:00:00 php-fpm: pool www php-fpm 5681 1234 0 12:00 ? 00:00:00 php-fpm: pool www
**Remediação:**
- O PHP-FPM deve ser executado como uma conta dedicada e não privilegiada.
- Na maioria dos casos, a conta usada é 'php-fpm'.
**Alterando a conta do processo para PHP-FPM:**```
# vim /etc/php-fpm.d/www.conf # Adjust the path based on your PHP version
...
user = php-fpm
group = php-fpm
listen.owner = php-fpm
listen.group = php-fpm
A conta do processo PHP-FPM não deve ter privilégios de login de shell.```
php-fpm❌999:999:PHP-FPM:/run/php:/usr/sbin/nologin
**Nota:**
- Usar contas de usuário diferentes para os processos PHP-FPM e para os processos do servidor web é preferível do ponto de vista de segurança.
- Quando perguntado qual é melhor para segurança, eles devem ser diferentes. Evite usar a mesma conta de execução neste contexto.
### 8.7. Garanta a Configuração Segura do Diretório Home do WordPress
Para operar um servidor web de forma segura, é crucial configurar corretamente a propriedade e as permissões do diretório home do WordPress
Na maioria dos casos, a propriedade e as permissões dos arquivos e diretórios do WordPress são definidas para corresponder à conta do processo do servidor web.
Essa configuração permite que o servidor web acesse arquivos na raiz web e opere sem erros.
No entanto, essa configuração é insegura.
Por exemplo, se o processo do servidor web for 'apache' e tanto o diretório raiz web quanto os arquivos forem de propriedade de 'apache', isso pode levar a vulnerabilidades graves.
Atacantes poderiam explorar essas vulnerabilidades para obter acesso não autorizado a arquivos e diretórios críticos dentro do diretório home do WordPress.
**Exemplo de Vulnerabilidade Comum:**
- Se tanto a conta do processo do servidor web quanto o diretório home (raiz web) e os arquivos forem de propriedade de 'apache':
- Em caso de vulnerabilidades no site e acesso externo ao sistema (como webshell), atacantes podem realizar várias ações dentro da raiz web:
1. Criar, modificar ou excluir arquivos ou diretórios dentro da raiz web.
2. Manipular logs de acesso web, incluindo modificação, exclusão ou criação. (exceto em alguns ambientes)
3. Pode obter acesso a cookies de sessão ativos de usuários logados. (em ambientes particularmente vulneráveis)
Para mitigar esses riscos, é crucial ajustar adequadamente a propriedade e as permissões do diretório home do WordPress
**Remediação:**
- Defina o proprietário do diretório home (raiz web) e dos arquivos como 'root:root'. (Evite defini-lo como o mesmo que a conta do processo do servidor web)
- O UMASK padrão para diretórios e arquivos é 022. (Diretórios: 755, Arquivos: 644)
- Para diretórios que exigem permissão de escrita, como upload de arquivos pelo serviço web, defina o proprietário desses diretórios como a conta do processo do servidor web.
**Diretórios com Permissões de Escrita Geralmente Necessárias no WordPress:**```
/wp-content/uploads
/wp-content/cache
/wp-content/wflogs (when using security plugins like Wordfence)
/wp-content/upgrade (used during the WordPress upgrade process)
Após configurar a propriedade e as permissões do diretório home de acordo com as medidas de correção acima, a saída do diretório home do WordPress é a seguinte:
Exemplo: Diretório Home do WordPress``` drwxr-xr-x 5 root root 4096 May 27 2024 . drwxr-xr-x 3 root root 4096 May 27 2024 .. -rw-r--r-- 1 root root 418 May 27 2024 index.php -rw-r--r-- 1 root root 19935 May 27 2024 license.txt -rw-r--r-- 1 root root 7346 May 27 2024 readme.html -rw-r--r-- 1 root root 7106 May 27 2024 wp-activate.php drwxr-xr-x 9 root root 4096 May 27 2024 wp-admin -rw-r--r-- 1 root root 351 May 27 2024 wp-blog-header.php -rw-r--r-- 1 root root 2328 May 27 2024 wp-comments-post.php -rw-r--r-- 1 root root 4973 May 27 2024 wp-config-sample.php -rw-r--r-- 1 root root 2755 May 27 2024 wp-config.php drwxr-xr-x 8 root root 4096 May 27 2024 wp-content -rw-r--r-- 1 root root 3940 May 27 2024 wp-cron.php drwxr-xr-x 25 root root 12288 May 27 2024 wp-includes -rw-r--r-- 1 root root 2496 May 27 2024 wp-links-opml.php -rw-r--r-- 1 root root 3300 May 27 2024 wp-load.php -rw-r--r-- 1 root root 51556 May 27 2024 wp-login.php -rw-r--r-- 1 root root 8403 May 27 2024 wp-mail.php -rw-r--r-- 1 root root 24568 May 27 2024 wp-settings.php -rw-r--r-- 1 root root 30869 May 27 2024 wp-signup.php -rw-r--r-- 1 root root 4620 May 27 2024 wp-trackback.php -rw-r--r-- 1 root root 3065 May 27 2024 xmlrpc.php
**Caso as contas de processo do php-fpm e do servidor web sejam diferentes (Permissões Separadas)**
Se a conta do processo do servidor web for "apache" e a conta do processo do php-fpm for "php-fpm".
Altere as permissões dos diretórios que exigem permissão de escrita no WordPress (ex.: /wp-content/uploads).
- Proprietário: php-fpm
- Grupo: apache
- Permissões do diretório: 775 (755 se necessário)
**Estrutura de Arquivos e Diretórios**
Defina as permissões de escrita para os diretórios necessários de modo que ambas as contas "php-fpm" e "apache" possam escrever.```
ex) /service/wordpress/www
├── index.php (root:root, 644)
├── license.txt (root:root, 644)
├── readme.html (root:root, 644)
├── wp-activate.php (root:root, 644)
├── wp-admin/ (root:root, 755)
├── wp-blog-header.php (root:root, 644)
├── wp-comments-post.php (root:root, 644)
├── wp-config-sample.php (root:root, 644)
├── wp-config.php (root:root, 644)
├── wp-content/ (root:root, 755)
│ ├── plugins/ (root:root, 755)
│ ├── themes/ (root:root, 755)
│ ├── uploads/ (php-fpm:apache, 775)
│ │ ├── 2024/ (php-fpm:apache, 775)
│ │ └── ... (php-fpm:apache, 775)
│ └── ... (root:root, 755)
├── wp-cron.php (root:root, 644)
├── wp-includes/ (root:root, 755)
├── wp-links-opml.php (root:root, 644)
├── wp-load.php (root:root, 644)
├── wp-login.php (root:root, 644)
├── wp-mail.php (root:root, 644)
├── wp-settings.php (root:root, 644)
├── wp-signup.php (root:root, 644)
├── wp-trackback.php (root:root, 644)
└── xmlrpc.php (root:root, 644)
Resumo
Configurando desta forma, você pode separar as permissões do servidor web e do PHP-FPM, aplicar corretamente as configurações de propriedade e permissão do diretório raiz e aumentar a segurança.
Este método se aplica não apenas ao WordPress, mas a qualquer estrutura de servidor web que exiba conteúdo web.
Garantir que a execução de PHP esteja desabilitada em diretórios onde arquivos podem ser enviados é crucial para manter um ambiente seguro.
Diretórios de upload com permissões de escrita são alvos potenciais para invasores enviarem scripts maliciosos, como shells web, que podem ser executados para comprometer o servidor.
Por que isso é importante?
Mitigar ataques de web shell:
Reduzir a superfície de ataque:
Conformidade com as melhores práticas de segurança:
Auditoria:
Correção:
/wp-content/uploads.Etapas de Configuração
<Location "/wp-content/uploads">
SetHandler application/octet-stream
</Location>
location /wp-content/uploads {
default_type application/octet-stream;
}
<Location "/wp-content/uploads">
php_flag engine off
# ou alternativamente
php_value engine 0
</Location>
<Location "/wp-content/uploads">
<FilesMatch "\.php$">
SetHandler none
Require all denied
</FilesMatch>
</Location>
<Directory "/var/www/html/yourwordpress/wp-content/uploads">
# Desabilitar execução de PHP
<FilesMatch "\.php$">
SetHandler none
Require all denied
</FilesMatch>
</Directory>
location /wp-content/uploads {
location ~ \.php$ {
fastcgi_pass off;
}
}
location /wp-content/uploads {
location ~ \.php$ {
deny all;
}
}
Essas configurações garantem que mesmo que um arquivo PHP seja enviado para o diretório /wp-content/uploads, ele não possa ser executado, prevenindo assim possíveis ataques.
Explicação das Diretivas de Configuração
SetHandler application/octet-stream:
php_flag engine off / php_value engine 0:
SetHandler none:
Observação:
/wp-content/uploads ainda será acessível e exibido corretamente usando uma tag :```
Ao aplicar essas configurações, você melhora significativamente o diretório de upload contra possíveis vulnerabilidades de execução de scripts.
### 8.9. Garantir que o Servidor Web Responda Apenas a Host Headers Baseados em Domínio
Para proteger seu servidor web, é essencial garantir que ele responda apenas a requisições direcionadas ao seu nome de domínio e não a requisições feitas diretamente ao endereço IP do servidor.
Isso pode ser alcançado através da configuração adequada das diretivas VirtualHost.
Na maioria dos casos, os serviços web são acessados por um nome de domínio, como `https://yourwordpress.com`. O servidor web recebe essa requisição e serve o conteúdo apropriado. Para reforçar esse comportamento, precisamos configurar o servidor web para responder apenas a requisições com o cabeçalho Host correto.
**Riscos de Segurança Potenciais ao Permitir Acesso Baseado em IP**
1. Enumeração de Serviços:
- Atacantes podem usar endereços IP para enumerar serviços em execução no servidor, aumentando o risco de descobrir e explorar vulnerabilidades.
2. Exposição de Informações Sensíveis:
- Servidores mal configurados podem expor diretórios, arquivos ou outras informações sensíveis quando acessados via IP, que não deveriam ser acessíveis publicamente.
3. Desvio de Controles de Segurança:
- O acesso baseado em IP pode contornar medidas de segurança que são aplicadas apenas para acesso baseado em domínio, potencialmente levando a acesso não autorizado.
**Auditoria:**
- Verifique se o servidor web está configurado para responder apenas a requisições baseadas em domínio e não a acesso direto por endereço IP.
**Remediação:**
- Configure o servidor web para lidar com requisições apenas com base no domínio especificado e negar ou redirecionar outras requisições adequadamente.
**Passos de Configuração**
1. Configuração do VirtualHost Padrão
- Crie um VirtualHost padrão que capture todas as requisições não especificadas e retorne um 403 Forbidden ou as redirecione.
**Para Apache:**
```
<VirtualHost _default_:80>
DocumentRoot /var/www/html/yourwordpress
...
<Location />
Require all denied
</Location>
<VirtualHost _default_:443>
DocumentRoot /var/www/html/yourwordpress
...
SSLEngine on
SSLCertificateFile /path/to/ssl/certificate.crt;
SSLCertificateKeyFile /path/to/ssl/private.key;
...
<Location />
Require all denied
</Location>
</VirtualHost>
```
**Para Nginx:**
```
server {
listen 80 default_server;
return 403;
}
server {
listen 443 ssl default_server;
...
ssl_certificate /path/to/ssl/certificate.crt;
ssl_certificate_key /path/to/ssl/private.key;
...
return 403;
}
```
2. Configuração do VirtualHost Baseado em Domínio
- Certifique-se de ter um VirtualHost configurado para o seu domínio.
**Para Apache:**
```
<VirtualHost *:80>
ServerName yourwordpress.com
...
Redirect permanent / https://yourwordpress.com/
</VirtualHost>
<VirtualHost *:443>
ServerName yourwordpress.com
DocumentRoot /var/www/html/yourwordpress
...
SSLEngine on
SSLCertificateFile /etc/httpd/to/ssl/certificate.crt;
SSLCertificateKeyFile /etc/httpd/to/ssl/private.key;
...
</VirtualHost>
```
**Para Nginx:**
```
server {
listen 443 ssl;
server_name yourwordpress.com;
root /var/www/html/wordpress;
...
ssl_certificate /path/to/ssl/certificate.crt;
ssl_certificate_key /path/to/ssl/private.key;
...
```
3. Teste
- Aqui está a criação do VirtualHost Padrão e do VirtualHost Baseado em Domínio para `yourwordpress.com`.
- Após criar o VirtualHost Padrão e o VirtualHost Baseado em Domínio para `yourwordpress.com`, o acesso é negado (erro 403) para requisições que não são baseadas em domínio (https://ip), resultando em uma tela de erro 403.
```
$ curl -i -k http(s)://10.10.66.88
HTTP/1.1 403 Forbidden
Server: nginx
Date: Mon, 03 Jun 2024 23:23:13 GMT
Content-Type: text/html
Content-Length: 162
Connection: keep-alive
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>
$ curl -i -k https://yourwordpress.com
HTTP/1.1 200 OK
Server: nginx
Date: Mon, 03 Jun 2024 23:32:12 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 9
Connection: keep-alive
Hello, yourwordpress.com
```
- Se houver necessidade de comunicação entre servidores ou comunicação dentro da mesma sub-rede IP, você pode configurar o VirtualHost Padrão para permitir acesso de endereços IP específicos.
Ao implementar essas configurações, o servidor web responde apenas a requisições direcionadas ao seu domínio.
### 8.10. Configuração Completa do Servidor Web
Aqui está um exemplo de uma configuração completa do servidor web que inclui as diretrizes de segurança. Ajuste e use esta configuração de acordo com o ambiente do seu servidor web WordPress.
1. Apache
```
<VirtualHost _default_:80>
DocumentRoot /var/www/html/yourwordpress
ErrorLog /var/log/httpd/http.ip.error.log
CustomLog /var/log/httpd/http.ip.access.log combined
<Location />
Require all denied
</Location>
<VirtualHost _default_:443>
DocumentRoot /var/www/html/current/public
ErrorLog /var/log/httpd/https.ip.error.log
CustomLog /var/log/httpd/https.ip.access.log combined
# SSL Configuration
SSLEngine on
SSLCertificateFile /etc/httpd/conf.d/cert/yourwordpress.com_ssl.crt
SSLCertificateKeyFile /etc/httpd/conf.d/cert/yourwordpress.com_ssl.key
SSLSessionTimeout 1d
SSLSessionCache shared:MozSSL:10m
SSLSessionTickets off
SSLProtocol TLSv1.2 TLSv1.3
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305
SSLHonorCipherOrder off
<Location />
Require all denied
</Location>
</VirtualHost>
<VirtualHost *:80>
ServerName yourwordpress.com
Redirect permanent / https://yourwordpress.com/
</VirtualHost>
<VirtualHost *:443>
ServerName yourwordpress.com
Protocols h2 http/1.1
DocumentRoot /var/www/html/current/public
ErrorLog /var/log/httpd/https.yourwordpress.com.error.log
CustomLog /var/log/httpd/https.yourwordpress.com.access.log combined
# SSL Configuration
SSLEngine on
SSLCertificateFile /etc/httpd/conf.d/cert/yourwordpress.com_ssl.crt
SSLCertificateKeyFile /etc/httpd/conf.d/cert/yourwordpress.com_ssl.key
SSLSessionTimeout 1d
SSLSessionCache shared:MozSSL:10m
SSLSessionTickets off
SSLProtocol TLSv1.2 TLSv1.3
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305
SSLHonorCipherOrder off
<Directory /var/www/html/current/public>
Options -Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# Deny PHP execution in uploads directory
<Directory "/var/www/html/current/public/wp-content/uploads">
<FilesMatch "\.php$">
SetHandler none
Require all denied
</FilesMatch>
</Directory>
# PHP Serving
ProxyPassMatch ^/(?!wp-content/uploads/.*\.php$)(.*\.php(/.*)?)$ unix:/var/run/php-fpm/php-fpm.sock|fcgi://localhost/var/www/html/current/public
#ProxyPassMatch ^/(?!wp-content/uploads/.*\.php$)(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/html/current/public
# Favicon
<Location "/favicon.ico">
ErrorDocument 404 "Not Found"
SetEnvIf Request_URI "^/favicon\.ico$" no_log
</Location>
# Robots.txt
<Location "/robots.txt">
Require all granted
SetEnvIf Request_URI "^/robots\.txt$" no_log
</Location>
# Restrict access to wp-cron.php
<Files "wp-cron.php">
Require all denied
Require ip 127.0.0.1
</Files>
# Restrict access to wp-json
<Location "/wp-json/">
Require all denied
Require ip 127.0.0.1
Require ip 10.10.77.49
Require ip 10.10.71.20
</Location>
# Restrict access to wp-admin
<Location "/wp-admin">
Require all denied
Require ip 10.10.77.49
Require ip 10.10.71.20
</Location>
<Files "wp-login.php">
Require all denied
Require ip 10.10.77.49
Require ip 10.10.71.20
</Files>
# Deny access to hidden files
<FilesMatch "^\.">
Require all denied
</FilesMatch>
</VirtualHost>
```
2. Nginx
```
server {
listen 80 default_server;
listen 443 default_server ssl http2;
error_log /var/log/nginx/http.ip.error.log;
access_log /var/log/nginx/http.ip.access.log main;
ssl_certificate /etc/nginx/conf.d/cert/yourwordpress.com_ssl.crt;
ssl_certificate_key /etc/nginx/conf.d/cert/yourwordpress.com_ssl.key;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
location / {
deny all;
}
}
server {
listen 443 ssl http2;
server_name yourwordpress.com;
root /var/www/html/wordpress;
error_log /var/log/nginx/https.yourwordpress.com.error.log;
access_log /var/log/nginx/https.yourwordpress.com.access.log main;
ssl_certificate /etc/nginx/conf.d/cert/yourwordpress.com_ssl.crt;
ssl_certificate_key /etc/nginx/conf.d/cert/yourwordpress.com_ssl.key;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# Restrict to access Wordpress Cron
location = /wp-cron.php {
allow 127.0.0.1;
deny all;
access_log off;
log_not_found off;
}
# Restrict to access json rest-api
location ~ ^/wp-json/ {
allow 127.0.0.1; # Allow localhost
allow 10.10.77.49; # Allow myip
allow 10.10.71.20; # Allow myip
deny all;
access_log off;
log_not_found off;
}
# Restrict to access Wordpress Admin
location = /wp-admin {
allow 10.10.77.49; # Allow myip
allow 10.10.71.20; # Allow myip
deny all;
}
location ~* \wp-login.php {
allow 10.10.77.49; # Allow myip
allow 10.10.71.20; # Allow myip
deny all;
}
# Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac).
# Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)
location ~ /\. {
deny all;
}
# Deny access to any files with a .php extension in the uploads directory
location /wp-content/uploads {
location ~ \.php$ {
deny all;
}
}
# Other example
# location ~* /(?:uploads|files)/.*\.php$ {
# deny all;
# }
# Rewrite rules, sends everything through index.php and keeps the appended query string intact
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
# Serving PHP
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\\.php)(/.+)$;
# fastcgi_pass 127.0.0.1:9000; # With php-cgi (or other tcp sockets):
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; # With php-fpm (or other unix sockets):
fastcgi_index index.php;
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
}
```
## 9. Garantir Atualizações de Segurança do WordPress
O WordPress aborda vulnerabilidades de segurança lançando novas versões de atualização quando vulnerabilidades são descobertas.
Por exemplo, se uma vulnerabilidade de segurança for encontrada no WordPress 6.5.2, ela será corrigida e distribuída na versão 6.5.3.
Como as atualizações de segurança não são gerenciadas versão por versão, atualizações regulares de versão são necessárias para corrigir vulnerabilidades de segurança.
Consulte as informações oficiais de lançamento do WordPress para atualizações:
[WordPress Releases](https://wordpress.org/download/releases/)
**Remediação:**
- Atualize o WordPress regularmente.
- O WordPress não gerencia atualizações (incluindo atualizações de segurança) versão por versão.
- A partir de 20 de maio de 2024, apenas a versão 6.5 está em manutenção.
**Nota:**
- Versões Beta, Nightly builds e outros checkouts do Subversion não são suportados.
- Evite usar produtos bifurcados ou versões que não sejam lançamentos oficiais do WordPress.
- Documentação para versões suportadas: [Supported Versions](https://wordpress.org/documentation/article/supported-versions/)
## 10. Garantir Verificações Regulares de Vulnerabilidades de Segurança para o WordPress
WordPress é um software de sistema de gerenciamento de conteúdo (CMS).
Como é um software empacotado, as vulnerabilidades de segurança ocorrem principalmente em seus componentes (arquivos principais, plugins, temas, etc.).
Ao contrário de aplicações web desenvolvidas sob medida para requisitos específicos, a identificação e correção de vulnerabilidades de segurança devem ser feitas usando métodos adequados ao WordPress.
Se um site construído com WordPress não foi extensivamente personalizado e mantém a natureza do WordPress, as vulnerabilidades de segurança podem ser facilmente verificadas usando o WPScan.
O WPScan é um software parcialmente pago, mas o nível básico gratuito não possui limitações funcionais. Ele permite verificações regulares e respostas a vulnerabilidades de segurança do WordPress.
**Remediação:**
- Realize verificações regulares de vulnerabilidades usando o WPScan (ou ferramentas similares que possam escanear WordPress).
- Se vulnerabilidades forem encontradas, verifique e realize as ações necessárias para eliminá-las. Na maioria dos casos, isso é resolvido por meio de atualizações.
- Consulte a [documentação do usuário do WPScan](https://github.com/wpscanteam/wpscan/wiki/WPScan-User-Documentation).
- Mais informações sobre vulnerabilidades comuns frequentemente encontradas no WordPress: [Extending WordPress Common Security Vulnerabilities](https://learn.wordpress.org/tutorial/extending-wordpress-common-security-vulnerabilities/)
**WPScan:**```
_______________________________________________________________
__ _______ _____
\ \ / / __ \ / ____|
\ \ /\ / /| |__) | (___ ___ __ _ _ __ ®
\ \/ \/ / | ___/ \___ \ / __|/ _` | '_ \
\ /\ / | | ____) | (__| (_| | | | |
\/ \/ |_| |_____/ \___|\__,_|_| |_|
WordPress Security Scanner by the WPScan Team
Version 3.8.22
Sponsored by Automattic - https://automattic.com/
@_WPScan_, @ethicalhack3r, @erwan_lr, @firefart
_______________________________________________________________
[+] URL: https://yourwordpress.com/ [192.168.10.100]
[+] Started: Fri May 24 14:39:06 2024
Interesting Finding(s):
[+] Headers
..
...
| - content-security-policy: upgrade-insecure-requests
| Found By: Headers (Passive Detection)
| Confidence: 100%
..
...
[+] XML-RPC seems to be enabled: https://yourwordpress.com/xmlrpc.php
| Found By: Link Tag (Passive Detection)
| Confidence: 30%
| References:
| - http://codex.wordpress.org/XML-RPC_Pingback_API
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_ghost_scanner/
| - https://www.rapid7.com/db/modules/auxiliary/dos/http/wordpress_xmlrpc_dos/
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_xmlrpc_login/
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_pingback_access/
..
...
[+] Finished: Fri May 24 14:39:48 2024
[+] Requests Done: 187
[+] Cached Requests: 7
[+] Data Sent: 56.32 KB
[+] Data Received: 605.595 KB
[+] Memory used: 276.602 MB
[+] Elapsed time: 00:00:42
| nº | Função | Descrição | Pessoal Administrativo |
|---|
| 1 | Administrador | Tem acesso total a todas as funcionalidades do WordPress e pode gerir todo o conteúdo do site. | Administradores de Sistema |
| 2 | Editor | Pode gerir e publicar publicações de outros utilizadores, bem como editar e publicar conteúdo. | Gestores de Serviços Operacionais, Contribuidores de Conteúdo Internos |
| 3 | Autor | Pode escrever e publicar as suas próprias publicações e tem permissão para editar as suas próprias publicações. | Contribuidores de Conteúdo Internos |
| 4 | Colaborador | Pode escrever conteúdo mas não pode publicá-lo. As publicações são revistas e publicadas por um administrador. | Contribuidores de Conteúdo Internos |
| 5 | Subscritor | Pode iniciar sessão no site e gerir o seu perfil pessoal, mas não pode escrever ou editar conteúdo. | Contribuidores de Conteúdo Internos |
session.cookie_httponly:
; Make session cookies inaccessible to JavaScript
session.cookie_httponly = On
open_basedir:
; Restrict PHP file access to the specified directory
open_basedir = "/path/to/your/web/root"
Exemplo:
open_basedir = "/var/www/html:/tmp"
This configuration allows PHP to access files only within the /var/www/html directory and the temporary directory /tmp.
disable_functions:
; Disable potentially dangerous PHP functions
disable_functions = "system, exec, shell_exec, passthru, mysql_list_dbs, ini_alter, dl, symlink, link, chgrp, leak, popen, apache_child_terminate, virtual, mb_send_mail"
Explicação das Funções Desabilitadas:
system, exec, shell_exec, passthru:
mysql_list_dbs:
ini_alter:
dl:
symlink, link:
chgrp:
leak:
popen:
apache_child_terminate:
virtual:
mb_send_mail: