Bloquear a execução de PHP em modules/ com .htaccess (PrestaShop 1.7 e 8)
No PrestaShop 8 e anteriores, qualquer ficheiro .php dentro de modules/ pode ser pedido por URL. O PrestaShop 9 já o recusa de origem. Explicamos como aplicar essa proteção na sua loja, como deixar exceções e que outras pastas convém fechar.
Uma das melhorias de segurança menos faladas do PrestaShop 9 está num ficheiro de uma dúzia de linhas: o .htaccess que a pasta modules/ traz de origem. Com ele, o Apache responde 403 a qualquer pedido direto a um .php de um módulo, antes de o PHP chegar a arrancar.
No PrestaShop 1.7 e 8 esse ficheiro não existe. Qualquer .php que esteja dentro de modules/, seja de um módulo instalado, de um desinstalado ou de uma porta traseira, pode ser pedido por URL e é executado. Este artigo explica como levar essa proteção à sua loja sem estragar nada.
Porque é importante
Quase tudo o que um módulo moderno faz passa pelo dispatcher do PrestaShop: os controladores front são pedidos como index.php?fc=module&module=nombre&controller=accion (ou pelo seu URL amigável), e os de administração passam pelo back office. Nenhum desses caminhos precisa de pedir diretamente um .php de modules/.
O que é pedido diretamente são:
- Ficheiros antigos de módulos velhos:
ajax.php,validation.php, scripts de cron ou de importação que arrancam o PrestaShop por conta própria. Alguns têm vulnerabilidades conhecidas. - Ficheiros de módulos órfãos, que continuam no disco apesar de o módulo ter sido desinstalado.
- Portas traseiras deixadas na pasta de um módulo, muitas vezes com um nome que parece estar lá desde sempre.
Recusar os .php diretos fecha de uma vez as três coisas. O que fica aberto é apenas o que passa pelo dispatcher, que é muito mais fácil de rever.
O que faz exatamente o PrestaShop 9
O ficheiro de origem usa um FilesMatch que recusa por extensão, com as diretivas do Apache 2.2 e do Apache 2.4. Recusa .php e também outros ficheiros que nunca deveriam ser servidos dali: .log, .txt, .lock, .json, .yml, .yaml, .tpl, .twig, o config.xml de cada módulo e as suas variantes por idioma. Os CSS, JavaScript e imagens dos módulos continuam a ser servidos normalmente.
Como aplicá-lo no PrestaShop 1.7 e 8
- Faça uma lista do que é pedido diretamente. Antes de fechar, reveja os registos de acesso do servidor das últimas semanas à procura de pedidos a
/modules/que acabem em.phpe respondam 200. Essa é a lista do que poderia estragar. - Classifique cada um. Retornos de gateways de pagamento, crons agendados no painel, chamadas Ajax de algum módulo antigo. Cada um é ou uma exceção justificada ou algo que convém substituir.
- Crie o ficheiro
modules/.htaccesscom uma recusa dos.phpe das extensões de configuração, à imagem do do PrestaShop 9. No Apache 2.4 a regra essencial é<FilesMatch "\.(php|phtml|phar|php[0-9])$"> Require all denied </FilesMatch>. Incluirphtml,phare as variantes numeradas evita que passe um ficheiro com outra extensão que o servidor também execute. - Acrescente as exceções na pasta de cada módulo, não na geral. Por exemplo, em
modules/mipasarela/.htaccess:<Files "notificacion.php"> Require all granted </Files>. Assim a exceção vale apenas para esse ficheiro desse módulo, e não para qualquer ficheiro com o mesmo nome noutra pasta. - Confirme com pedidos reais. Peça um
.phpqualquer de um módulo (deve dar 403), peça o da exceção (deve responder) e faça uma encomenda de teste com cada método de pagamento. - Reveja os crons. Se um cron do painel chamava
modules/x/cron.php, agora vai falhar sem avisar. Troque-o pelo URL do controlador do módulo, se o tiver, ou deixe-o como exceção.
Limitações que convém conhecer
- Não protege os controladores front. Um
controllers/front/é servido através deindex.php, por isso o.htaccessdemodules/não o tapa. Se um módulo instalado tiver um controlador vulnerável, continua vulnerável. Para isso não há atalho: atualizar ou retirar o módulo. - O Nginx ignora os
.htaccess. Se o seu servidor for Nginx puro, a recusa faz-se com um blocolocationna configuração do servidor, que normalmente cabe ao seu alojamento. - Depende de o servidor ler os
.htaccess(diretivaAllowOverride). Confirme-o pedindo um.phpdepois de criar o ficheiro; não o dê por adquirido. - Um atacante com permissão de escrita pode apagá-lo. Se alguém pode escrever em
modules/, pode retirar o.htaccess. O seu desaparecimento não tem nenhuma causa legítima, por isso vigiar a sua presença é em si um alarme útil.
As outras pastas: upload/, img/, var/
upload/ e download/
É aí que ficam os ficheiros que os clientes carregam nos produtos personalizáveis e os produtos descarregáveis. O PrestaShop serve-os através de um controlador, não por acesso direto. No PrestaShop 9, download/ recusa tudo e upload/ recusa os ficheiros com o nome interno que o PrestaShop lhes dá. Nenhuma das duas deveria conter um .php, por isso acrescentar nelas uma recusa de PHP é seguro. Se, além disso, a sua loja não serve nada de upload/ por URL direto, pode recusar tudo, mas confirme antes.
img/
No PrestaShop 9 recusa tudo exceto as extensões de imagem, vídeo, PDF e ícones. Em versões anteriores, veja o que traz o seu img/.htaccess: pode ter regras próprias, por isso acrescente a recusa de PHP no fim, sem substituir o que lá está. E quando regenerar o .htaccess da raiz a partir do back office, confirme depois que os seus blocos continuam onde os deixou.
var/ e cache/
Desde a 1.7, var/ traz uma recusa total. Confirme que o ficheiro continua lá: um var/logs acessível revela caminhos, erros e às vezes dados de clientes. Nas lojas 1.6, a pasta equivalente é cache/, e não deve servir PHP.
A raiz
Confirme também que não há cópias de segurança (.zip, .sql, .tar.gz) nem registos de erros do alojamento acessíveis na raiz. Um dump da base de dados descarregável é pior do que qualquer shell.
Como resolvê-lo no PrestaShop
O RKR Security Alert tem um painel de blindagem das pastas de dados que confirma que o .htaccess de upload/, download/, img/ e outras pastas não só existe como bloqueia de facto a execução, e avisa se aparecer algo executável onde só deveria haver dados. Pode escrever o bloco de recusa por si, acrescentando-o no fim do ficheiro existente e guardando uma cópia. Para modules/, verifica que extensões o .htaccess recusa realmente e cruza-as com os pontos de entrada que encontra, e cada achado do scanner indica se é alcançável por URL ou está fechado. Se preferir não mexer nisso, com um pacote de horas de suporte da Rekire revemos os registos, definimos as exceções necessárias e testamos com encomendas reais.