В ноябре мы писали о том, как злоумышленники используют инъекции JavaScript для загрузки зловредного кода из файлов CSS.
Поначалу незаметно, что эти инъекции содержат что-то, кроме безобидных правил CSS. Однако при более тщательном анализе файла .CSS обнаруживается 56 964 кажущиеся пустыми строки, содержащие сочетания из невидимых символов табуляции (0x09), пробелов (0x20) и переводов строки (0x0A), которые преобразуются в двоичное представление символов, а затем в текст исполняемого кода на JavaScript.
Вскоре мы обнаружили такую же схему использования и во вредоносных программах на PHP. В статье мы расскажем о том, что обнаружил аналитик вредоносного ПО Лиам СмитSmith, работая недавно над сайтом, содержащим множество загружаемых хакерами бэкдоров и веб-шеллов.
Подозрительный файл license.php
Один из найденных Лиамом файлов выглядел немного странно: system/license.php.
Как можно понять из названия, он содержит текст лицензионного соглашения, а именно GNU General Public License version 3.
Этот текст лицензии расположен внутри многострочного комментария PHP. Однако в строке 134 мы видим разрыв между двумя комментариями, содержащий исполняемый код на PHP.
Код на PHP внутри license.php
Сокрытие зловредного кода между блоками комментариев — это распространённый способ обфускации, используемый хакерами.
Код очевидно зловреден, но на первый взгляд не было очевидно, полный ли это текст зловреда, или у него есть в файле и другие части. Легко заметить, что он пытается считать себя и сделать что-то со своим содержимым при помощи
file_get_contents(basename($_SERVER[‘PHP_SELF’])))
. Однако при кратком визуальном изучении файла не обнаружилось никаких других частей, которые можно преобразовать в работающий код на PHP.Анализ видимого зловредного кода
Чтобы понять, что конкретно делает зловредный код, мы проанализировали каждую конструкцию.
Первый фрагмент разделяет содержимое файла на части, отделённые символом точки с запятой, а последнюю часть присваивает переменной
$cache
. Этот код работает с частью файла, находящейся после последней ;
.Оказывается, что последняя точка с запятой в файле также является последним символом лицензионного соглашения: "But first, please read <www.gnu.org/philosophy/why-not-lgpl.html>;". В настоящем лицензионном соглашении последним символом является точка, и это показывает, что файл был намеренно модифицирован злоумышленником.
После этой последней точки с запятой визуально ничего не видно. Чтобы понять, что выполняется оставшейся частью файла, нам нужно проанализировать следующий раздел операторов зловреда.
Декодер разделителей
for($i=0;$i<strlen($cache);$i++){
$out.=chr(bindec(str_replace(array(chr(9),chr(32)),array('1','0'),substr($cache,$i,8))));
$i+= 7;
}
Здесь мы видим, что код считывает остальную часть файла фрагментами по восемь символов за раз (
substr($cache,$i,8)
) и преобразует табуляции (9
) и пробелы (32
) в единицы и нули. Получившаяся двоичная строка затем преобразуется в десятичное число (bindec
), а потом в символ при помощи функции chr()
. Таким образом, октет за октетом, остальная часть разделителей файла преобразуется в видимую строку.На этом этапе строка не имеет никакого смысла и не является исполняемой. Чтобы полностью декодировать и исполнить полезную нагрузку, используется следующее сочетание функций:
base64_decode(str_rot13(gzdecode(…
.В качестве резервного способа исполнения полезной нагрузки зловредный код также пытается сохранить декодированное содержимое в файл с названием " " (просто пробел — так его сложнее заметить в списке файлов) и включает его на лету с помощью
include $cachepart;
. После этого данный файл удаляется, чтобы попытаться избежать обнаружения.Тем не менее, мы получили отчёты о том, что по какой-то причине эти файлы с пустым именем всё равно можно найти на скомпрометированных сайтах.
Раскрытие сокрытой полезной нагрузки
Теперь, когда мы знаем, что это зловредное ПО ищет символы табуляции и пробелы после последней точки с запятой, можно найти и декодировать эту скрытую полезную нагрузку.
Как оказалось, в конце последней строки файла
license.php
содержится почти 300 килобайт невидимых символов табуляции и пробелов. Для сравнения: видимый текст лицензии составляет всего 30 КБ.Эти невидимые символы можно обнаружить, проверив шестнадцатеричный код последней строки или выбрав в текстовом редакторе содержимое после последней
;
(со включенным переносом строк).Последняя строка license.php в шестнадцатеричном виде
Начало невидимого содержимого, выделенное в текстовом редакторе
Хотя эта картинка, как и похожая обфускация из описанного в ноябре зловреда на JavaScript, напоминает код Морзе, в данном примере не используются символы перевода строки (line feed, 0x0A). Это означает, что невидимое содержимое не создаёт огромное количество подозрительных пустых строк в конце файлов.
Использовав алгоритм декодирования разделителей (whitespace) из кода, мы получаем 74-килобайтный файл веб-шелла, предоставляющий хакерам инструменты для работы с файлами и базами данных на сервере, сбора персональной информации, инфицирования файлов и проведения брутфорс-атак. Кроме того, он может работать как консоль сервера или анонимайзер для сокрытия реального IP-адреса злоумышленников.
Декодированный из разделителей веб-шелл
Источник происхождения алгоритма
Как часто выясняется в наших расследованиях, многие используемые в зловредном ПО хитрости и алгоритмы создаются не хакерами. Большая часть кода уже существовала ранее и просто копируется с сайтов наподобие StackOverflow.
Поиск фрагмента кода этого декодера разделителей привёл к статье 2019 года на Хабре. Автор статьи поделился своим proof of concept обфускации PHP при помощи разделителей, вдохновившись статьёй об обфускации 2011 года, в которой рассказывалось о концепции кодирования при помощи только символов табуляции и пробелов.
Автор зловреда просто взял часть с декодером разделителей из этой статьи, не внеся никаких изменений, а затем добавил код для работы с дополнительным слоем обфускации и исполнения декодированной полезной нагрузки.
Аплоудер зловредного ПО
На скомпрометированных серверах довольно редко встречается только один тип бэкдора. Обычно их несколько, и каждый из них отвечает за конкретную задачу.
Например, файл с невинным названием
license.php
должен оставаться невидимым в течение долгого времени, обеспечивая доступ к скомпрометированному сайту даже после обнаружения и удаления всего остального зловредного ПО.Файлы или код, которые злоумышленники изначально внедряют на сервер, чтобы инфицировать сайт — это другой тип бэкдора. Обычно он располагается в мелком файле в скомпрометированном окружении; такие бэкдоры позволяют злоумышленникам или исполнять произвольный код, или создавать определённые файлы. Они не должны быть особо скрытными или сильно обфусцированными — чтобы замести следы, хакеры часто удаляют их после применения.
Конкретно в этом случае мы обнаружили аплоудеры зловредного ПО, создающие фальшивые файлы
license.php
, а также инъецирующие зловредов в файлы .htaccess
и index.php
.Аплоудер зловредного ПО, создающий фальшивые файлы license.php
Заключение
Хотя сокрытие зловредного содержимого от невооружённого глаза кажется хорошей идеей, использованная в этом коде обфускация разделителями далека от идеала. Она содержит легко обнаруживаемый фрагмент PHP и его удаление приводит к невозможности использования невидимой полезной нагрузки. Ещё один недостаток такого подхода — огромный размер файла. Зловред увеличил размер файла в десять раз, из-за чего он стал гораздо более подозрительным.
Техники обфускации стандартно используются хакерами для сокрытия кода и утаивания зловредного поведения. Существуют сотни известных типов обфускации, а злоумышленники всегда ищут новые способы защиты от обнаружения.
К счастью для администраторов сайтов, для удаления зловредного ПО им необязательно декодировать его и чётко понимать принцип его работы. Для обнаружения нежелательных модификаций файлов достаточно простого ПО контроля целостности.
Если при изучении изменений вы не уверены, являются ли они зловредными, то самым безопасным будет откатиться к чистой версии — ведь у вас ведь есть резервная копия?
На правах рекламы
Серверы для разработчиков и не только! Недорогие VDS на базе новейших процессоров AMD EPYC и хранилища на основе NVMe дисков от Intel для размещения проектов любой сложности, создавайте собственную конфигурацию сервера в пару кликов!
bolk
Этой технике уже несколько лет. Например, вот я её реализовывал на нескольких языках: github.com/bolknote/utf-16-trick (2017-й год), а вот похожая: bolknote.ru/all/3556 (2012-й).
Alexufo
Прикрылась лавочка)
Теперь консоль выдает:
Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: «default-src 'none'».
bolk
Ну это политика конкретного сайта работает.