Executando verificação de segurança...
10

O primeiro script (e post no TabNews) da minha vida

Introdução

Fala pessoal,

Como programador iniciante, estou um pouco acanhado de postar aqui, principalmente diante de tanta gente talentosa e experiente, mas como houveram vários incentivos para que eu fosse em frente, aqui estou eu.

Aliás, apesar de apresentar o código que fiz, o objetivo não é necessariamente esse, tanto que no título não coloquei "Script para bloquear requisições XMLRPC", que seria o certo haha Meu objetivo aqui é um pouco mais empírico: quero inspirar aqueles que estão iniciando na área a também resolverem problemas do seu dia-a-dia com a programação! Então, apesar de talvez o conteúdo não ser muito útil para a maioria de vocês, eu quero na verdade estimular o uso da tecnologia na nossa vida. Bora pro conteúdo.

block-xmlrpc-requests

Script para adicionar bloco de código que bloqueia requisições ao arquivo xmlrpc.php, em todas as instalações WordPress de um servidor.

Por que criei esse script?

Como administrador de uma hospedagem de sites, eu estava recebendo muitas mensagens do meu firewall com um aviso semelhante ao seguinte:

Time:     Wed Apr 20 20:28:17 2022 -0300
IP:       185.189.115.108 (CZ/Czechia/pc-coupons.online)
Failures: 5 (XMLRPC)
Interval: 3600 seconds
Blocked:  Permanent Block [LF_CUSTOMTRIGGER]

Numa rápida pesquisa, descobri que conseguiria resolver esse problema apenas implementando o código a seguir no arquivo .htaccess:

<Files xmlrpc.php>
order deny,allow
deny from all
allow from xxx.xxx.xxx.xxx
</Files>

Mas copiar e colar o código em cada um dos sites, de modo manual, me parecia um pouco cansativo. Por isso criei o script.

Observações importantes

  1. É o primeiro código da minha vida hehe por isso, atente-se aos seguintes pontos:
  • Podem existir vulnerabilidades;
  • Podem existir erros ou "pontas soltas";
  • Acho que pode ser escrito de maneira mais limpa;
  • Não tenho experiência suficiente para analisar se consome muitos recursos do servidor (o que também depende do tamanho e capacidade do seu servidor) - ou seja, não tenho certeza se é saudável rodar esse código em outros ambientes (no meu foi tranquilo [eu acho]).

Conto com sua ajuda nos pontos acima :D

  1. O meu ambiente é um CentOS 7 com o painel CWP rodando. Pode ser que em outros ambientes você precise fazer alguma alteração no código (como a estrutura do diretório "home" ou o comando para reinicializar o Apache).

Código

echo "Procurando por instalações WordPress no servidor..."
find /home/ -type f -name "xmlrpc.php" -not -path "*wp-content*" -printf '%h\n' | sort -u >> wps.txt
readarray wps < wps.txt
echo "${#wps[@]} instalações encontradas!"
echo "Procurando por arquivos .htaccess que não contenham o código <Files xmlrpx.php>..."
	for wp in ${wps[@]}
	       	do
			find $wp -maxdepth 1 -type f -name ".htaccess" | xargs -r grep -L "<Files xmlrpc.php>" >> files.txt
                        readarray files < files.txt
		done
rm files.txt wps.txt
nfiles=${#files[@]}
	if [ $nfiles == 0 ]
	then
		echo "Todos os arquivos já contém o código. Até mais!"
		exit
	else
	if [ $nfiles == 1 ]
	then
	echo "01 arquivo encontrado!"
	echo "Adicionando o código no arquivo..."
	else
	echo "${#files[@]} arquivos encontrados!"
	echo "Adicionando o código nesses arquivos..."
	fi
        for file in ${files[@]}
	       	do
		echo "		
#Block WordPress xmlrpc.php requests
<Files xmlrpc.php>
order deny,allow
deny from all
</Files>" >> $file
		echo "Código adicionado em $file!"
        	done
	fi
echo "Pronto!"
while true;
do
        read -p "Necessário reiniciar o Apache para aplicar as configurações. Deseja reiniciar agora? [Y/n]" yn
        case $yn in
     [Yy]*) systemctl restart httpd.service; echo "Apache reiniciado com sucesso."; break;;
     [Nn]*) exit;;
     * ) echo "Entrada inválida.";;
    esac
done

Explicação do código

Procura por diretórios em /home que contenham o arquivo xmlrpc.php, excluindo as subpastas wp-content e armazena os valores num array:

find /home/ -type f -name "xmlrpc.php" -not -path "*wp-content*" -printf '%h\n' | sort -u >> wps.txt
readarray wps < wps.txt

Para cada diretório encontrado no comando anterior, executa uma busca por arquivos .htaccess que não contenham o código <Files xmlrpc.php>, adiciona-os a um arquivo temporário e armazena os valores num array:

Reconheço que aqui existe uma "ponta solta" no sentido que apenas a primeira linha do código está sendo buscada no arquivo, enquanto deveria ser todo o trecho. Porém, ainda não consegui resolver esse empecilho, então considere apenas um começo e conto com sua participação para melhorá-lo.

for wp in ${wps[@]}
    do
    find $wp -maxdepth 1 -type f -name ".htaccess" | xargs -r grep -L "<Files xmlrpc.php>" >> files.txt
    readarray files < files.txt
done

Faz uma verificação do tamanho do array (ou seja, quantos arquivos foram encontrados) e, se for igual a zero, finaliza o código:

nfiles=${#files[@]}
if [ $nfiles == 0 ]
	then
		echo "Todos os arquivos já contém o código. Até mais!"
exit

Se tiver um ou mais arquivos encontrados, adiciona o bloco de código a cada um deles:

else
	if [ $nfiles == 1 ]
	then
	echo "01 arquivo encontrado!"
	echo "Adicionando o código no arquivo..."
	else
	echo "${#files[@]} arquivos encontrados!"
	echo "Adicionando o código nesses arquivos..."
	fi
        for file in ${files[@]}
	       	do
		echo "		

#Block WordPress xmlrpc.php requests

<Files xmlrpc.php>
order deny,allow
deny from all
</Files>" >> $file
		echo "Código adicionado em $file!"
        	done
	fi

Simples validação, com interação do usuário, para reiniciar o Apache após a execução das tarefas:

while true;
do
        read -p "Necessário reiniciar o Apache para aplicar as configurações. Deseja reiniciar agora? [Y/n]" yn
        case $yn in
     [Yy]*) systemctl restart httpd.service; echo "Apache reiniciado com sucesso."; break;;
     [Nn]*) exit;;
     * ) echo "Entrada inválida.";;
    esac
    done

Considerações finais

Não hesite em deixar suas críticas ou sugestões. Estou aberto a melhorias!

Fiz esse código por hobbie e para exercitar meu conhecimento em programação, mas espero de coração que ele seja útil a alguém. Se for, deixe eu ficar sabendo, por favor! :)

Dica: você pode implementar como um cronjob para executá-lo de tempos em tempos automaticamente no seu servidor (aqui eu vou deixar 1 vez por mês).

Meus próximos projetos

Tenho diversos projetos em mente e vou colocar alguns aqui para tentar te inspirar ainda mais. Lembre-se: a ideia não é ser necessariamente útil para todo mundo, e sim resolver problemas na sua vida que possam ser automatizados. Com o tempo, pode ser que a ideia de ouro surja ou, no mínimo, você terá um portfólio legal para apresentar no seu currículo. Divirta-se!

  1. Um app para controle de gastos de veículo próprio utilizado a trabalho. Estou fazendo corridas no iComida como extra (não sei se posso citar marcas registradas aqui), e marcando a quilometragem diariamente de modo manual para contabilizar os gastos. Seria bacana automatizar esse processo.

  2. Um web app que sirva como uma "ponte pix" para quem deseja cobrar seus clientes de maneira profissional e rápida. A ideia é que seja super prático de se cadastrar e usar, e tenha uma página semelhante ao Linktree porém exibindo apenas informações de pagamento. Penso em fazer um formato tipo (app.io/user/{valor}) onde no valor o usuário poderá digitar um int e, se possível, já apresentar o código pix e outras integrações abaixo relacionado ao valor digitado (o PicPay já meio que faz isso atualmente).

  3. Instalação limpa de um novo site WordPress. Repito diversas tarefas toda vez que crio um novo site: registrar domínio, criar conta no servidor, adicionar domínio na CloudFlare, configurar DNS e SSL, instalar o WP, configurar o WP (idioma, fuso-horário, permalinks...), instalar plugins, apagar o Hello World. Seria muito massa poder apenas digitar um domínio no terminal e deixar ele fazer todo esse processo, me liberando tempo e energia para focar na parte criativa.

Agradecimentos

Spoiler: puxação de saco ao Filipe kkk

Filipe, eu te agradeci publicamente no meu repositório do GitHub por me inspirar a trabalhar com tecnologia, e como não consegui postar no YouTube, não poderia perder esta oportunidade :D

Ah, e se você quiser apoiar: link do repositório no GitHub

Abraços!

4

Que massa, Lucas! Parabéns!!

Li tudinho visse, top demais! Mesmo não entendendo muito sobre o assunto, eu li porque quando falam em automação eu já tô dentro! hahah É muito legal o processo de automatizar algo importante ou uma tarefa chata.

Eu planejo fazer um post tipo esse seu, mas seria de uma ideia de projeto, que até o momento só tem o repositório no Github, meio que só o nome registrado hehe. Daqui a uns dias devo postar por aqui no TN!

Esse post realmente me inspirou para que eu cuide logo para fazer a minha ideia sair do papel! Obrigado, Lucas!!

4

É verdade amigo, automatizar processos é muito legal! Principalmente quando é você que faz e você mesmo que se beneficia hahahha dá um orgulho sabe hahhaa

Pois faça logo! Estarei ansioso para ver. Eu também demorei a fazer essa parada aí, foi coisa de alguns meses recebendo aqueles emails do Firewall. Eu até criei um filtro no gmail para excluir essas msgs pois estava recebendo centenas por dia. Mas convenhamos que nao é muito legal deixar uma vulnerabilidade aberta, independentemente de o firewall estar fazendo o trabalho dele.

Porém, quando conheci o Filipe e o canal, fiquei inspirado e fui caçando os códigos e montando o quebra-cabeça. Depois de feitos os testes, a execução levou uns 20 segundos no máximo, trabalho que eu faria em um dia inteiro.

Trabalho feito = brecha tapada = zero emails = Lucas feliz e orgulhoso kkk essa sensação que quero passar à turma

Então FAÇA LOGO ESSE PROJETO!!!

2

cara o mais legal é que você fez seu primeiro script para resolver um problema real seu, para mim isso é que define ser um bom programador resolver problemas, continue assim parabéns

2

Muito obrigado Gusttavo! Pois é, e era um problemão para mim. Não tenho muuuuuitos sites no servidor, mas tem mais de 50. E a preguiça? kkk

Ver o script rodando e fazendo tudo em menos de 1 minuto - e ainda me ensinando lições valiosíssimas - foi muito satisfatório.

Abraço irmão

2
1

Simplesmente sensacional Lucas e muito obrigado pela citação no final 😍 vamos para cima que temos muito código e softwares para criar 🤝 💪

Em paralelo, dentro da sua postagem sugiro declarar a linguagem no bloco de código, como por exemplo ```php porque daí o código fica assim:

echo "Procurando por instalações WordPress no servidor..."
find /home/ -type f -name "xmlrpc.php" -not -path "*wp-content*" -printf '%h\n' | sort -u >> wps.txt
readarray wps < wps.txt
echo "${#wps[@]} instalações encontradas!"
echo "Procurando por arquivos .htaccess que não contenham o código <Files xmlrpx.php>..."

// ...