Короткий ответ

Сайт на host.example (nginx/Apache) или IIS заменили витрину: снимите копию webroot и логов, отрежьте запись (FTP/SFTP/CMS/deploy), не редактируйте дефейс в проде «вернуть текст». Откат — из git tag / проверенного backup, не из памяти дизайнера. Ищите, как писали: учётная запись CMS, ключ deploy, RCE в приложении, webshell. Не выкладывайте PoC эксплуатации.

Если параллельно спам с того же дерева — WordPress. Секреты CMS — ротация.

Симптомы и как отличить

  • Клиенты: «у вас на сайте флаг/реклама/порноссылка».
  • index.html / index.php размер и mtime не как вчера.
  • HTTPS жив, сертификат ваш — это не обязательно подмена DNS (но DNS тоже проверьте).
  • IIS: C:\inetpub\wwwroot изменён учёткаю пула.
КартинаНе дефейсКуда
Свой деплой сломал вёрсткуchangegit diff, не IR malware автоматически
Паркинг регистратораNS/expireDNS, не webroot
Только один прокси кеширует староеCDNpurge после фикса
Подмена hosts на WS-042 Иванаклиентне сервер

Возможные причины

  1. Украден FTP/SFTP/SSH deploy-ключ.
  2. Слабый пароль CMS/админки, без MFA.
  3. Webshell от старой дыры приложения (не выдумываем CVE — смотрим mtime и неизвестные файлы).
  4. Компрометация CI, который публикует в prod.
  5. Доступ в webroot с WS-042 заражённого админа.
  6. Ошибка тома/реплики, отдала старый «шуточный» стенд (редко).

Диагностика

1. Копия состояния

sudo mkdir -p /var/ir/deface
sudo tar -C /var/www -czf /var/ir/deface/www-$(date -u +%Y%m%dT%H%M%SZ).tar.gz html
sudo cp -a /var/log/nginx /var/log/apache2 /var/ir/deface/ 2>/dev/null || true
sudo find /var/www/html -mtime -7 -type f -printf '%TY-%Tm-%Td %TH:%TM %p\n' | sort | tail -50

IIS:

New-Item -ItemType Directory -Force C:\IR\deface | Out-Null
Compress-Archive -Path 'C:\inetpub\wwwroot\*' -DestinationPath C:\IR\deface\wwwroot.zip -Force
Get-ChildItem C:\inetpub\wwwroot -Recurse | Sort-Object LastWriteTime -Descending | Select-Object -First 40 FullName, LastWriteTime
Copy-Item C:\inetpub\logs\LogFiles C:\IR\deface\iislogs -Recurse -ErrorAction SilentlyContinue

2. Как писали

sudo grep '10.0.10.55' /var/log/nginx/access.log | tail
sudo last -F | head
sudo grep -E 'Failed|Accepted' /var/log/auth.log | tail

IIS W3C: cs-username, c-ip, cs-uri-stem PUT/POST на .aspx/.php.

FTP/SFTP журналы, ключи authorized_keys пользователя деплоя.

3. Неизвестные файлы

Ищите недавно изменённые .php, .aspx, .jsp, .phtml вне пакета. Не запускайте их. Hash:

sudo find /var/www/html -type f \( -name '*.php' -o -name '*.aspx' \) -mtime -14 -exec sha256sum {} \;

Сравнение с git:

cd /var/www/html && git status && git log -1

Если git нет — только backup.

4. DNS и сертификат

Убедитесь, что A/AAAA всё ещё ваш host.example. Дефейс при чужом IP — это уже захват DNS, другой runbook (регистратор), но webroot всё равно снимите.

Решение

Сдерживание

  1. Выключить FTP, ограничить SSH деплоя, перевести сайт в maintenance после копии.
  2. WAF/firewall: временно только известные admin IP на /wp-admin, /iisadmin — не вместо ротации паролей.
  3. Не оставлять webroot writable для www-data шире, чем нужно, после отката (в инциденте сначала копия).

Откат

# пример: известный чистый тег
cd /var/www/html
sudo git fetch --all
sudo git checkout -f v1.4.2

Или restore файлов из backup в новое дерево, переключить корень, не original overwrite единственной копии.

IIS: appcmd stop сайта, подмена каталога из backup, start.

Сценарий: нет git и backup

Тогда честный статус «витрина потеряна», поднимайте заглушку, разбор диска. Не собирайте сайт копированием с ноутбука дизайнера как «чистый» без проверки.

Несколько origin, CDN и учётка деплоя

Дефейс на host.example при двух нодах за балансировщиком требует копии обоих webroot: откат одной оставит вторую «флагом». CDN: после git checkout сделайте purge, иначе клиенты сутки видят грязь. Ключ деплоя ivan.petrov в authorized_keys www-data — ротация, даже если «это удобно CI». FTP, если жив, выключите до разбора: протокол с паролем в plain в 2026 не «временный канал дизайнера».

Проверьте, не подменён ли A-запись (регистратор). Если IP чужой — параллельный инцидент DNS, webroot всё равно архивируйте: при возврате NS вы должны знать, что лежало на диске. Не открывайте найденный .php с WS-042 в браузере. Хеш и копия. Пароли CMS, соли wp-config/machine keys IIS — сразу, иначе откат без ротации = повтор дефейса к утру.

Как проверить, что проблема устранена

  • Внешний curl отдаёт ожидаемый HTML, не дефейс.
  • CDN purge сделан.
  • Нет записи в webroot с чужих IP.
  • Неизвестные скрипты удалены после копии.
  • Секреты сменены, FTP выключен если не нужен.
  • mtime дерева стабилен после отката.

Если не помогло

  • Дефейс вернулся — webshell или CI всё ещё публикует грязь; ищите запись после checkout.
  • Только часть зеркал — балансировщик, несколько webroot.
  • HTTPS чужой сертификат — смотрите прокси/hosting, не только файлы.
  • WordPress спам параллельно — соседняя статья, тот же host.

Профилактика

  • Деплой только CI по ключу, не FTP.
  • Git как источник истины, backup webroot+БД.
  • MFA на CMS, закрытый admin path.
  • WAF, минимальные права на каталоги.
  • Алерт на изменение index.* вне окна деплоя.

FAQ

Можно ли просто залить вчерашний ZIP с ноутбука?

Только если это известный артефакт сборки. Случайный ZIP с WS-042 может быть уже грязным.

Нужно ли выключать весь сервер?

Обычно достаточно отрезать запись и HTTP на время отката. Выключение — если шифровальщик/неясный root.

Правка одного index.html руками

Не решение: бэкдор в другом файле останется. Откат дерева + поиск mtime.

IIS и Linux на одном инциденте?

Два webroot — две копии. Не лечите только nginx, забыв второй сайт на 8080.

Сообщать ли публично?

Шаблон IR / бизнес. Технически сначала origin и секреты. Не обещайте «взлома не было», если index меняли.