Атака на доверие
13.1. Человек
Человек – самое слабое звено. Это расхожий, но верный штамп. Человек требует от противника меньше всего работы. Обычно хватает телефона и получаса. А нужный человек уже обладает всеми возможностями, необходимыми для достижения поставленной цели.
Социальной инженерией называют получение доступа или сведений через убеждение человека, без взлома технических средств.
Держится она не на глупости жертвы, хотя пострадавшим потом говорят именно это. Работают обычные служебные рефлексы, без которых организация не смогла бы работать вовсе.
Авторитет. Звонит начальник, служба безопасности, налоговая, полиция. Проверять полномочия собеседника не принято, а спорить с начальством не принято тем более.
Срочность. Решение нужно принять сейчас, проверять некогда. Спешка убирает ту самую паузу, за которую человек успел бы засомневаться.
Страх. Со счета прямо сейчас списывают деньги, на компанию подан иск, доступ вот-вот заблокируют.
Вежливость. Отказать живому человеку, который вежливо просит, неудобно. На этом же держится проход в здание следом за сотрудником с пропуском.
Знакомый контекст. Письмо приходит от коллеги, ссылается на реальный проект и настоящую переписку. Сведения для этого берут из утечек и открытых источников.
Знакомый почти всем классический пример: звонящий представляется сотрудником банка, называет имя, отчество и последние цифры карты, чтобы разговор начался с доверия. Дальше сообщает о попытке списания и просит не класть трубку: линия под контролем, вы сорвете операцию, вас переключат на сотрудника полиции. Просьба не класть трубку – сердцевина всей схемы, потому что единственная проверка, которая тут работает, состоит в том, чтобы разговор прекратить и перезвонить в банк по номеру с оборота карты.
Людей можно учить, обучение действительно снижает долю тех, кто попадается, но не доводит ее до нуля. Нападающему хватает одного человека. В организации на тысячу сотрудников один процент ошибающихся – это десять открытых дверей (причем каждый год новых, потому что люди приходят и уходят).
Хуже того, половине сотрудников нельзя дать выполнимое правило. Кадровик обязан открывать резюме от незнакомых людей, бухгалтер – счета от незнакомых контрагентов, менеджер по продажам – заявки от кого угодно. Правило «не открывайте вложения от неизвестных отправителей» для них означает «не работайте», и обходной путь появляется в первый же день.
Чтобы понять, насколько велика в организации эта дыра, службы безопасности рассылают сотрудникам поддельные письма и отслеживают реакции. Проверка показывает и число попавшихся, и то, какой подход сработал лучше других. Распространенная ошибка в том, что попавшихся наказывают, а они после этого перестают сообщать и о настоящих письмах (промолчать и понадеяться, что обойдется, безопаснее, чем признаться). В результате организация узнает о происшествии позже, чем узнала бы вообще без всякой проверки. Надежная система должна выдерживать ошибку человека, а не рассчитывать на то, что ее получится избежать.
Ошибку человека выдерживают несколько известных мер:
- Второй фактор, который нельзя передать голосом. Код из сообщения жертва продиктует, ключ, лежащий в устройстве, продиктовать невозможно.
- Ограниченные права. Учетная запись одного сотрудника открывает то, что нужно ему, и не открывает всю систему.
- Второй человек на важных операциях. Крупный платеж и смена реквизитов подтверждаются кем-то еще, и обмануть приходится уже двоих.
- Дешевое сообщение об ошибке. Понятный адрес или телефон, куда сообщают о подозрительном письме, и отсутствие последствий для сообщившего. Чем раньше узнали, тем меньше противник успел.
Необходимость подтверждений, вынужденные задержки и невозможность быстро сделать исключение для важного клиента отнимают у людей часть самостоятельности. В результате замедляется работа, и там, где скорость ценят выше надежности, такие меры быстро начинают игнорировать со словами «мы же взрослые люди».
Обучение делает ошибку реже. Устройство системы делает ее менее значимой. Первое обходится дешево и не заканчивается никогда, второе требует переделки и работает без напоминаний.
13.2. Атака на процесс разработки
Проникновение в систему через доверенный канал отличается тем, что средства обнаружения обычно не спасают, поскольку проверяют условия, которые и так выполняются. Например, если через него внедряется скомпрометированный код, он приезжает законным порядком, с верной подписью, из того самого места, откуда его и ждут.
В современной программе мало своего кода. Приложение подключает десятки библиотек напрямую, каждая из них тянет свои, и в готовой сборке чужого кода оказывается больше, чем собственного. Он исполняется с теми же правами, но никто из разработчиков, как правило, его не читает.
Цепочкой поставок программы называют совокупность заимствований чужого кода. Сюда входят библиотеки и их зависимости, средства сборки, хранилища пакетов и т.д.
Вопрос о корне доверия, актуальный для цепочки удостоверяющих центров, возвращается в применении к людям и к их работе.
Попасть в чужую цепочку поставок можно по-разному.
Опечатка в имени. В хранилище пакетов кладут библиотеку с именем, отличающимся от популярной одной буквой. Разработчик промахивается при наборе, сборка проходит успешно, а в продукт приезжает чужой код. Прием называют тайпсквоттингом (точно так же регистрируются поддельные сайты с именами, похожими на существующие). Отдельного кринжа в эту тему навалили языковые модели. Подсказывая код, модель иногда называет библиотеку, которой не существует, и делает это устойчиво: одно и то же выдуманное имя повторяется от запроса к запросу. Злоумышленнику остается зарегистрировать такое имя в хранилище пакетов и подождать, пока кто-нибудь установит библиотеку не глядя.
Захват учетной записи сопровождающего. Украденный пароль дает право выпустить новую версию популярной библиотеки от имени ее автора, и версия эта разойдется всем, кто обновляется автоматически.
Вход в доверие. Долгий и законный путь: участвовать в проекте, исправлять ошибки, отвечать в переписке и получить права сопровождающего обычным порядком.
Подмена при сборке. Исходный текст остается чистым, а закладка попадает в двоичный файл на той машине, которая его собирает. В хранилище проекта при этом все в порядке, и читать там нечего.
В 2021 году в проект xz, библиотеку сжатия, входящую почти в каждый дистрибутив Linux, пришел новый участник. Больше года он исправлял ошибки и вел переписку, а параллельно на прежнего сопровождающего со специально созданных учетных записей шло давление: проект застоялся, ошибки не чинятся, пора передавать дела. В конце 2022 года новый участник получил права сопровождающего, а в феврале 2024 года внес закладку.
Закладка лежала в файлах, которые попадают в готовый архив с исходниками, но отсутствуют в хранилище проекта, и оживала только при сборке пакета для распространенных дистрибутивов на определенной архитектуре, так что в исходном коде заметить ее было нельзя. Собранная библиотека подменяла проверку в службе удаленного доступа, и обладатель нужного ключа входил на любую машину с этой версией.
Совершенно случайно инженер, замерявший производительность базы данных, обратил внимание, что вход по SSH стал расходовать заметно больше процессорного времени, и разобрался почему. Он написал об этом в рассылку по безопасности в конце марта 2024 года, когда испорченные версии дошли до экспериментальных веток нескольких дистрибутивов, но в стабильные выпуски попасть не успели.
Проверить эту историю техническими средствами было нечем. Подпись стояла верная, потому что подписывал законный сопровождающий. Хранилище проекта было чистым. Репутация набиралась настоящей работой, и исправления, которые новый участник вносил два года, действительно исправляли ошибки. Ни одна проверка не отличает сопровождающего, работавшего два года ради проекта, от сопровождающего, работавшего два года ради одного коммита.
Наиболее эффективные меры обеспечения безопасности снижают не вероятность реализации угрозы, а ее негативные последствия
К мерам, ограничивающим последствия атаки на разработку, относятся:
- Фиксация версий. Сборка описывается списком, где у каждой зависимости указаны точный номер и отпечаток содержимого. Обновление становится отдельным решением, а не побочным следствием пересборки. Эта мера не должна приводить к застоям в обновлении зависимостей (чем реже они обновляются, тем дольше в продукте живет уже известная и уже исправленная дыра, разбор которой опубликован и доступен противнику).
- Опись состава. Перечень всего, что вошло в готовый продукт, нужен затем, чтобы в день объявления уязвимости ответить на вопрос, есть ли она у вас, за минуты, а не за неделю.
- Воспроизводимая сборка. Два независимых сборщика из одного исходного текста получают побайтно одинаковый результат. Подмена на сборочной машине после этого перестает быть незаметной. Этой машиной нередко оказывается рабочий компьютер инсайдера, который пишет код.
- Отделение выпуска от написания. Сборку выпускает не тот, кто писал код, и собирается она не на его машине, а на отдельной, которая берет исходный текст из хранилища.
Читать весь чужой код непрактично и, как правило, неосуществимо, но доверять ему полностью нельзя. Проверяют в цепочке сборки не все, и вопрос в том, что именно, кем и как часто.
13.3. Межсайтовый скриптинг
Доверенный канал принимает различные формы, и в каждой полезно отдавать себе отчет, чему оказано доверие и на каком основании.
Подпись сопровождающего говорит, кто выпустил пакет, и ничего не говорит о том, что внутри. Адрес страницы говорит, с какого сервера она приехала, и ничего не говорит о том, из чего она собрана. Браузер доверяет адресу. Все, что пришло с одного адреса, для него одинаково «свое».
Почти всякий сайт показывает посетителям то, что ввели другие посетители. Комментарии под статьей, отзывы о товаре, имя рядом с сообщением, город в профиле. Текст приходит с формы, ложится в базу, а потом возвращается на страницу.
Страницу браузер получает одной строкой. Разметка и содержимое в ней перемешаны, а разбирает эту строку программа, которая умеет не только показывать текст, но и исполнять скрипты.
Пусть посетитель оставит такой комментарий:
<script>
отправить признак входа посетителя на чужой сервер
</script>
Сервер сохранит это в базу и вставит в страницу так же, как вставил бы любой другой комментарий. Дальше каждый, кто откроет статью, получит страницу с чужим скриптом внутри, и браузер этот скрипт выполнит. Отличить скрипт, написанный разработчиком сайта, от скрипта, приехавшего из поля комментария, браузеру нечем: и тот и другой пришли с одного адреса, одной строкой, в одинаковых угловых скобках. Атака называется межсайтовым скриптингом.
Выполненный скрипт работает так, будто его написал сам сайт. Он видит все, что есть на странице, отправляет запросы от имени открывшего ее человека и читает ответы. Браузер хранит признак того, что посетитель вошел в систему, и подставляет его в каждый запрос к этому сайту, а скрипт этот признак забирает и отсылает куда угодно, после чего противник заходит на сайт как жертва. Впрочем, воровать необязательно: скрипт может нарисовать поверх страницы форму входа и подождать, пока в нее введут пароль.
В инъекциях из прошлой лекции противник бил по той самой системе, с которой разговаривал. Теперь его строка проходит сквозь сервер и срабатывает у постороннего человека, который ничего никуда не вводил и вообще ни при чем. Сервер оказался не жертвой, а средством доставки.
Комментарий, осевший в базе, достанется каждому, кто откроет страницу. Тот же прием работает и без базы: если сайт показывает введенное слово прямо в результатах поиска, вроде «по запросу такому-то ничего не найдено», достаточно подсунуть жертве ссылку с подготовленным запросом.
Прием из прошлой лекции здесь не поможет. Отдельного канала для разметки не существует, страница уезжает браузеру одной строкой, и в этом вся ее природа. Разделять нечего.
Поэтому границу восстанавливают в другом месте, в момент вывода. Перед тем как вставить чужой текст в страницу, угловые скобки, кавычки и амперсанды заменяют на безобидные обозначения, которые браузер покажет как обычные символы, но разметкой не сочтет.
Опасность символа зависит от того, куда его вставляют. В тексте абзаца кавычка безвредна, а угловая скобка опасна. Внутри значения атрибута опасна как раз кавычка: она закрывает атрибут, и дальше можно дописать свой. Внутри скрипта правила третьи, а в адресе ссылки четвертые, и опасной там оказывается вообще не пунктуация, а схема javascript.
Чистить данные на входе бессмысленно. В ту минуту, когда посетитель нажал кнопку, еще неизвестно, куда его текст потом вставят, и один и тот же комментарий может попасть и в абзац, и в подсказку атрибута, и в адрес ссылки. Спрашивать, опасны ли данные, надо не там, где они пришли, а там, где уходят наружу.
Точек вывода на большом сайте сотни, и в каждой надо знать контекст. Человек, пишущий страницы, помнит об этом первые полгода. Поэтому работу отдают шаблонизатору: он подставляет значения сам, видит, в какое место страницы подставляет, и экранирует по месту. Разработчик перестает принимать это решение, а вместе с решением исчезает возможность его забыть.
Второй рубеж – политика безопасности содержимого. Браузеру заранее сообщают, скрипты из каких источников ему разрешено выполнять, и пропущенный где-то чужой скрипт не запускается, потому что пришел не оттуда. Требует это настройки и обычно переделки страниц, на которых скрипты написаны прямо в разметке.
13.4. Вредоносное программное обеспечение
Вредоносной называют программу, которая устанавливается на компьютер без ведома владельца и делает то, чего он не хотел. Одна и та же программа удаленного управления может выступать как рабочим инструментом администратора, так и средством нападения, смотря по тому, кто ее поставил и знает ли об этом хозяин машины.
В такой программе различают две части. Одна отвечает за распространение, вторая делает то, ради чего все затевалось, и ее по традиции называют начинкой. Это относительно независимые компоненты (один способ доставки годится для разных начинок, а начинка легко сохраняется при изменении способа доставки).
Путь вредоносной программы в чужой системе состоит из четырех шагов.
- Проникновение. Сначала надо попасть на машину и запуститься. Это именно те способы, которые рассмотрены выше.
- Уговорить человека, чтобы запустил сам: вложение в письме, программа с привлекательным описанием, «потерянная» флешка.
- Воспользоваться уязвимостью в чем-то, что смотрит наружу.
- Приехать вместе с обновлением того, чему на этой машине уже доверяют.
- Закрепление. Чтобы пережить перезагрузку, программа должна устроить все так, чтобы стартовать вместе с системой. В Windows для этого десятилетиями служит ветка реестра с говорящим именем Run (а также полтора десятка менее известных способов).
- Сокрытие. Программа работает, пока ее присутствие не замечено. Для этого имена файлов мимикрируют под системные, программа прячется в папки, где сотни таких файлов, используется перехват обращений к диску, чтобы показывать проверяющему чистую картину (приемы этого рода называют стелс-технологиями), шифрование собственного тела новым ключом в каждой копии вместе с переписыванием расшифровщика, чтобы два экземпляра не совпадали ни в одном байте (полиморфизм). Предельный вариант – не оставлять файла вовсе: бесфайловые программы работают в памяти, а нужные действия выполняют тем, что в системе уже есть и разрешено, встроенным языком сценариев или штатными административными утилитами.
- Начинка. Собственно, ради чего все делалось.
Ранняя история вредоносных программ – это эволюция способов размножения. Решение задачи оказаться на чужой машине и получить на ней управление зависело от того, чем и как обменивались пользователи в соответствующую эпоху. Вслед за новым способом обмена появлялось новое поколение вредоносных программ.
- Файловые вирусы (1980-е). Обмен шел исполняемыми файлами на дискетах, а программу пользователь запускал сам. Отсюда и решение: дописать свое тело к чужой программе и получить управление вместе с ней. Уговаривать при этом никого не требуется, человек запускает то, что и так собирался запустить.
- Загрузочные вирусы записывают короткий код в загрузочный сектор дискеты или другого запоминающего устройства, откуда он считывается при включении компьютера и передает управление телу вируса. Загрузочный сектор диска получает управление раньше операционной системы, а значит, и раньше любой проверки. Прием «встать раньше проверяющего» с тех пор воспроизводится постоянно, от руткитов до современных буткитов.
- Макровирусы (середина 1990-х). Дискеты уступили место обмену документами, и заражать стало нечего: документ – это данные, а данные не исполняются. Так считали все, включая авторов защитных средств. Между тем, с легкой руки Microsoft текстовые и табличные редакторы научились исполнять макросы, вложенные прямо в документ, и открытие файла превратилось в точку запуска. Макровирусы прятались в документах, и понадобилось некоторое время, прежде чем их тоже стали проверять.
- Почтовые черви (конец 1990-х). Массовая электронная почта дала сразу и носитель, и точку запуска. Червь скрывается во вложении в электронном письме, а письмо это приходит со знакомого адреса (ведь способ размножения заключается в том, что, попав на машину, он берет адресную книгу и рассылает себя по ней). Так работал ILOVEYOU в мае 2000 года. Вместо технической уязвимости работает социальный граф – и скорость расползания обгоняет скорость выпуска антивирусных обновлений.
- Сетевые черви (2000-е). Постоянное подключение к сети и службы, слушающие порты, позволили убрать из цепочки человека и перейти к проникновению через код, доступный снаружи. Ни письма, ни вложения, ни щелчка мышью: червь сам находит уязвимую машину и сам получает на ней управление. Slammer в январе 2003 года удваивал число зараженных узлов каждые несколько секунд и забил каналы связи собственным трафиком. Ограничением служила пропускная способность сети, и именно эти эпидемии сделали своевременное обновление системы и закрытие лишних портов обязательными мерами.
Каждое поколение использовало знание о том, чем сейчас обмениваются пользователи и что умеет запускаться само, при этом защита, как правило, была настроена на предыдущий ответ. Но в настоящее время эволюция размножения остановилась. Массовое расползание перестало окупаться. Копии расходятся широко, образец быстро попадает к тем, кто пишет антивирусы, и жизнь всей затеи оказывается короткой. Управлять расползающейся программой автор не может: ни направить, ни остановить. Попадает она большей частью на машины, где взять нечего.
Изменился противник. Сложность средств защиты уже не позволяет справиться с ними школьнику, жаждущему самоутверждения. Написать действенную вредоносную программу теперь не проще, чем промышленный продукт: нужна команда профессионалов и деньги.
Соответственно, изменились и задачи. Нападающему нужна либо конкретная организация, либо много одинаковых домашних машин с сохраненными в браузере паролями. В обоих случаях доставку выгоднее устроить самому, и место вируса занял троянский конь – программа, которая не размножается вовсе, а притворяется чем-то нужным. В этом виде она и приходит: реклама на посещаемом сайте, поддельная страница обновления браузера, взломанный установщик популярной утилиты, письмо конкретному сотруднику.
В то время как начинка вирусов 90-х часто сводилась к примитивному уничтожению файлов случайных пользователей, современные начинки развиваются в направлении эффективного заработка.
- Вымогатель. Шифрует файлы на диске и предлагает купить ключ. Схема известна с девяностых, а массовой стала тогда, когда появился способ получать выкуп, не раскрывая себя. Позже к шифрованию добавилось копирование: данные сначала забирают, а потом угрожают опубликовать, и жертву с исправными резервными копиями это касается наравне с остальными.
- Инфостилер. Собирает то, что легко продать: сохраненные в браузере пароли, признаки входа в открытые сеансы, ключи от кошельков, переписку. На зараженной машине живет обычно один сеанс, задерживаться ему незачем.
- Ботнет. Объединяет зараженные машины в управляемую сеть. По отдельности хозяину машины почти не мешает, поэтому годами и не лечится, а вместе они рассылают почту, перебирают пароли, накручивают показы рекламы или обрушивают чужой сайт потоком запросов.
13.5. Противодействие вредоносным программам
Антивирус решает задачу, обратную задаче автора вредоносной программы: отличить чужое от своего, не имея заранее списка чужого.
Основные способы обнаружения вирусов:
- Сигнатурный поиск. Сигнатура – характерная последовательность байтов, которая встречается в известном образце и не встречается в обычных программах. Антивирус сравнивает файлы с базой сигнатур, которая непрерывно обновляется. Выделение сигнатуры – тонкое искусство, в 2000-е два антивируса на одном компьютере вводили систему в ступор, пытаясь «вылечить» друг друга. Сегодня метод считается достаточно точным, но работает только против того, что кто-то уже поймал, разобрал и описал. Именно против него придуман полиморфизм – если каждая копия зашифрована своим ключом, а расшифровщик переписан заново, общих байтов у двух экземпляров не остается.
- Анализ поведения. Смотрят на действия программы. Если она открывает на запись чужие исполняемые файлы, прописывается в автозапуск, подряд шифрует документы пользователя или рассылает письма по адресной книге, закрадывается подозрение. Перечень подозрительных действий универсален, поэтому метод срабатывает и против новой угрозы. При этом важно различать ложные срабатывания (архиватор тоже шифрует, установщик тоже прописывается в автозапуск). В идеале не дожидаться, пока программа попробует подозрительные действия в рабочей среде, а запустить ее в изолированной песочнице. Разумеется, авторы вредоносных программ стараются в свою очередь распознать песочницу (мало памяти, пустая история браузера, свежий профиль, мышь не двигается и т.д.). В таком окружении программа ведет себя смирно. Некоторые просто выжидают сутки, потому что столько времени песочнице никто не даст.
- Репутация. Решение принимают не по содержимому файла, а по тому, сколько машин в мире его видели и как давно. Программа, встреченная за час трижды и нигде не подписанная, подозрительна сама по себе. Прием работает против одноразовых сборок, которых сегодня большинство, и требует, чтобы антивирус спрашивал сервер производителя, то есть отправлял туда сведения о том, что на машине запускается.
- Белый список. Исполняется только заранее разрешенное, все прочее не запускается вовсе. Способ самый надежный и самый неудобный. В массовом виде он живет как магазины приложений и обязательная подпись кода: на телефоне посторонняя программа по умолчанию не установится. Вопрос при этом смещается к тому, кто ведет список и по каким правилам в него попадают.
Любое узнавание запаздывает: образец надо сначала где-то встретить.
Поэтому меры, которые не зависят от узнавания, для обычного пользователя важнее самого узнавания. Таких мер три.
- Обновления. Большинство путей проникновения, разобранных выше, ведет через известную уязвимость в браузере, в почтовом клиенте или в самой системе. Известную – значит уже исправленную, и между выходом исправления и его установкой лежит окно, которым и живет нападающий. Установка обновлений в тот же день закрывает больше, чем любой антивирус.
- Обычная учетная запись. Программа получает права того, кто ее запустил. Запущенная под администратором, она распоряжается всей машиной; запущенная под обычным пользователем, портит только его файлы. Повседневная работа прав администратора не требует, а на те редкие действия, где они нужны, система спросит подтверждение.
- Резервные копии. Мера, направленная на устранение последствий. Главное условие, определяющее ее эффективность: модель угроз резервной копии не должна совпадать с моделью угроз системы (простыми словами, все копии не должны лежать там, где зараженная машина уничтожит или зашифрует их вместе со всем остальным). Кроме того, копия должна регулярно проверяться восстановлением, чтобы в нужный момент не обнаружилась ее негодность.
Все три меры объединяет то, что они не зависят от того, какая именно программа пришла и умеет ли ее кто-нибудь узнавать. Поэтому они и не устаревают вместе с ней.
Настоящее нападение редко состоит из одного приема. Письмо убеждает человека открыть вложение, вложение приносит программу, программа закрепляется через неисправленную уязвимость, а уязвимость приехала в продукт вместе с чужой библиотекой. Разделение на типы нужно обороняющемуся как список, по которому он проверяет себя. Поведения нападающего оно не описывает.
Защиту ставят там, где ее удобно поставить и где потом виден результат. Входят там, где меньше работы. Совпадают эти места редко, а разницу между ними обороняющийся своими глазами не видит, потому что смотрит на систему изнутри и знает, как она задумана.
Модель нарушителя заставляет перечислить способы проникновения, а не средства защиты. Закрывать необходимо их все, потому что воспользоваться достаточно одним.
