18 декабря 2013 в 20:16

История одного бэкдора из песочницы

Предыстория


Жил-был один старый-старый сайт. Родители от него отказались, и на втором десятке лет существования он попал к нам. Он представлял из себя джунгли PHP кода, разбросанного по папкам. Все это было написано в разное время, с использованием разных паттернкостылей, в разных кодировках (до 3ёх кодировок в пределах одного файла). MVC тогда, наверное, еще не было известно, да и о шаблонизаторах разработчики не слышали, так что не стоит удивляться внезапному
<? if (cond) { ?>
в HTML разметке. Я провел не один час в увлекательных поисках нужного
<? } ?>
Разработчики не забывали и про бэкапы: в корне можно было найти index.php, index_old.php, index.php.bak. Но несмотря ни на что, это чудо работало. А что работает — не трожь.

Завязка


Эта история началась, когда солнечным декабрьским утром специалист по продвижению с удивлением обнаружил ссылки на чужеродные сайты в футере. Немного покопавшись выяснилось 2 вещи:
  1. это сапа;
  2. заказчик недоумевает.


Недоумение заказчика можно понять: у него этих ссылок не видно.

Расследование


Поставили задачу — найти, разобраться и уничтожить. Найдя искомое место в HTML-разметкеподключаемом PHP-файле было получено имя функции, делающей кому-то хорошо. Результат поиска по ~60k файлам кода не принес положительного результата — такой функции нигде не объявлено. Пошел в ход перебор всех файлов, подключаемых в искомой точке входа. В процессе глаз цепляется за файл следующего содержания:



Ничего не понятно, но искреннее спасибо тому человеку, который не убрал аннотацию в шапке. Я начинаю гуглить ''Zend Oрtimizer'', справедливо полагая, что он приведет к расшифровке этого трэша. Поиск рабочего декодера заканчивается тут. Особо порадовала капча:



С некоторым геморром, связанным с запретом копирования результата, я получил следующее:



Я с недоверием отношусь к сложным регулярным выражениям, а тут и вовсе потух. Начинаю вспоминать как работает preg_replace(). И чем больше читаю, тем больше недоумеваю. Само регулярное выражение должно идти первым параметром, а во втором — то, на что заменяют. Посмотрел еще раз на то, что было дано. получается, в строке «x» заменяется "#x#e" на ту длинную штуку. Причем в функции preg_replace() используются модификаторы x и e. Но не дадим себя запутать: все, что помещено между # — экранируется, так что x - это на самом деле то, что следует заменить в строке «x» , т.е. все, а модификатор e позволяет исполнить результирующее выражение как PHP код. При внимательном взгляде на строку замены становится понятно, что большая ее часть — это шум.



Если убрать комментарии, получится
@eval(base64_decode($I0));
На этом месте мне пришлось погуглить значение "@" перед вызовом функции. Далее, спасибо онлайн декодерам, я получил следующую порцию загадок.



Тут я впервые увидел функцию chr(). Позалипал на
$ll = @explode(chr(187) , @implode('', @array_map('trim', @file($ll))));
Загуглил array_map(). В общем тут используется кусок из того самого первоначального файла, зашифрованного Zend Optimizer. Вот уж не знаю какой там алгоритм, но произведя перестановку символов и взяв уже становящийся привычным base64_decode() я получил крипто-функцию:



Дальше ком стал разрастаться экспоненциально, и после нескольких итераций файл достиг 2к строк. Структуру файла после всего этого расследования я оставил на завтра, а пока пара забав:


позволяет остаться незамеченными с терминалов внутренней подсети.


Интересно, они там сразу делают шифровку такую, или это уже кто-то постарался спецом для нас?

Вместо послесловия


Если верить времени создания файлов — на дворе был суровый 2009. Только вот мне даже немного жаль времени тех людей, которые это все зашивали так упорно, потому как я уверен, что этот процесс занял у них времени поболее, чем обратный. И ведь всё это было бы невозможно, если бы только не осталась аннотация о Zend Optimizer.
Кричко Алексей @sand_alkr
карма
10,0
рейтинг 0,0
Web developer
Похожие публикации
Самое читаемое Разработка

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

  • +29
    времени у них это заняло минут 5, они готовым инструментом пользовались, скорее всего
  • 0
    Может это сайт был не единственным, значит профит они все-таки получили.
    • +4
      За пять лет работы — на хлеб с маслом хватит точно.
  • +1
    Если убрать ©Zend и т.д. то ничего работать не будет.
  • 0
    Там ещё должен быть хеш юзера. Думаю можно написать тех. поддержку sape и, может быть, ему что-то сделают…
    • 0
      Там он даже не один. На выбор _SAPE_USER_, _LINKFEED_USER_, _ML_ID в дополнение к _LNK_USER, который и шлется на сапу для получения ссылок.
  • +3
    Вот вы любопытный.

    Я бы сделал бэкап, удалил подозрительный код и проверил — на месте ли ссылки?
    • +1
      Простите, а Вы кем работаете?
    • 0
      Гораздо интереснее узнать то, как он там появился, на мой взгляд.
  • +21
    Мне попадался шелл в котором был копирайт с запретом на реверс инжиниринг =)
    А дальше все примерно похоже как у вас.

    Интересно было читать. Правда тот факт, что @ и array_map пришлось гуглить мне немного поставил в тупик.
    • +1
      И незаурядное регулярное выражение /x/e

      preg_replace( "#x#e", ....
      

      Я с недоверием отношусь к сложным регулярным выражениям, а тут и вовсе потух.

      • +1
        При первом чтении детали опускаются. Сначала заметил preg_replace(), и глаза сразу начинают искать что-то похожее на регулярное выражение. Вот так, в спешке, особо не разбираясь в порядке параметров, принял странного вида второй параметр за регулярное выражение. И вот оно-то меня и впечатлило. Видимо вы чаще меня пользуетесь регулярками, потому и в заблуждение вас ввести сложнее.
        • 0
          Да, я так, в качестве шутки. Рад что удалось раскурить код :)
    • +7
      Солидарен с вами, у меня так же возник вопрос об уровне владения php автором.
  • НЛО прилетело и опубликовало эту надпись здесь
    • +4
      1. подломали 5 лет назад, и сейчас уже не найти правды;
      2. чтобы что-нибудь сделать было бы неплохо выкинуть всю ту попахивающую кучу неподдающегося рефакторингу исходного кода, переехать на сервер с современными версиями apache/php и доступом, отличным от FTP. Но заказчику такое решение дастся очень тяжело, так что только хардкор. А по поводу конкретно этой проблемы — решением является выпиливание злокачественного файла, с попутным общением с техподдержкой sape.ru в надежде выйти на того, кто это соорудил.
      По поводу банальности — хорошо, если для вас они являются таковыми. На разрабатываемых мною проектах такого пока не было. Уверен, что найдется отличное от нуля число разработчиков, которым такое никогда и не встретится.

      Если вы уже сталкивались с чем-то подобным и исходя из своего опыта сможете предложить способы нахождения/закрытия дыр — не стесняйтесь оставлять советы.
      • 0
        да вы знаете, компьютер это такой черный ящик, почти как мишна Тьюринга… совершенно непонятно как посмотреть куда он там лезет и на какие сайты и зачем ходит. Можно даже подумать что компьютер живет какой-то своей жизнью а Вы, как несчастный разработчик, вынуждены расшифровывать какой-то мутный код написаный вирусней в архейскую эру :sarcasm:
  • +12
    Погуглив как работает конструкция if…
  • +2
    А где обещанный криптоанализ? Тут только про обфускацию написано.
  • +10
    Простейший обфусцированный троянец, коих тысячи в день раскидывают скрипты автоматического взлома через популярные уязвимости, даже не бекдор.
    Статья о том как вы узнали основы PHP.
    • +2
      Причём самые основы
  • +3
    Новичок в php разбирает банальнейший код. мда. На вашем месте я бы всерьез задумался откуда там взялся троян, а не то как он работает, нашел бы уязвимость на сервере. да и в сапу неплохо было бы сообщить, дабы забанили хулигана.
  • 0
    Не обязательно, что скрипт залили через уязвимость.
    К сожалению, встречаются непорядочные разработчики, которые оставляют на всех разрабатываемых сайтах закладки для простановки ссылок и рассылки спама.
  • 0
    Смотрим мануал php:
    Взято отсюда: pcre modifiers
    preg_replace("#x#e", ..); :
    e (PREG_REPLACE_EVAL)

    Предостережение
    Использовать этот модификатор не рекомендуется, так как это может легко добавить уязвимости в системе безопасности

    Приведенный выше код может быть легко скомпрометирован путем передачи такой строки как <h1>{${eval($_GET[php_code])}}</h1>. Это дает атакующему возможность исполнить произвольный PHP-код и по существу предоставляет ему почти полный доступ к вашему серверу.
  • 0
    Грустно.

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