Исследования — это неотъемлемая часть моего рабочего процесса. Я исследую ПО, исходные коды, ОС, железки — все, до чего дотянутся руки (ну или руки начальства, тут как повезет). Но не все исследования проводятся по заказу, иногда что-то просто делаешь для души (что, наша компания в общем-то поощряет). Это исследование началось с разговора о шифровании, а закончилось обходом DLP и выносом данных за контролируемый периметр.
Я очень не люблю DLP-системы. Моя неприязнь основана на маркетинговой стратегии продуктов, представляющих свои решения в виде этакой «серебряной пули», которая может предотвратить все утечки данных в любой компании. Не может. По моему мнению, реально DLP помогает в 2 случаях — предотвратить утечку данных из-за кривых рук (типа отправки платежных данных вместо ali@domain.mail на all@domain.mail) и помочь провести расследование, кто же унес данные (постфактум, естественно). Я изначально был уверен, что специалист, владеющий достаточными знаниями о Windows, например, сможет преодолеть почти любые фильтры. А мотивированный инсайдер сможет найти такого специалиста и обучиться нескольким трюкам. Но проверять разные трюки на конкретных комплексах довольно скучно, поэтому надо было придумать, как разом обойти их все.
Мне близки идеи криптоанархизма и я люблю криптографию. Даже вне интернета нас окружает так много всего, что ее использует — от банальных пропусков и транспортных билетов, до пластиковых карт, которыми мы расплачиваемся. Я бы с радостью подписывал свои сообщения в социальных сетях и мессенджерах, если бы это было удобно сделано — отдельное поле для указания электронной подписи, автоматическая проверка, удобный экспорт подписи и открытых ключей для внешних проверок. Я не питаю иллюзий — массовыми такие изменения никогда не будут. Надо начать с себя. Так или иначе, именно эта кривая дорожка мечтаний о том, как доставить самому себе побольше проблем ради сомнительных ощущений безопасности, привела к забавной мысли — а что если катапультой... встроить шифрование в клавиатуру?
Придумалось, что можно добавить на клавиатуру несколько дополнительных кнопок. Одна, например, провоцирует клавиатуру «напечатать» открытый ключ, или, даже сразу, сертификат. Другая переводит клавиатуру в режим шифрования — печатаемый текст не передается на компьютер, он сначала шифруется, а уже зашифрованный «печатается на экране».
Даже учитывая мою большую любовь к раскидыванию граблей на пути, по которому предстоит бежать в ближайшее время, я понимал нежизнеспособность такой клавиатуры. Это осознание пришло где-то сразу после необходимости собственного экрана для такой клавиатуры — без него нельзя посмотреть на текст до шифрования и отредактировать тоже, только вслепую.
Кроме того, пришел на ум вопрос: как компьютер может передать информацию такой «клавиатуре»? Решение этого вопроса необходимо для ввода ключей и сертификатов.
Вариантов много:
- внешний usb на клавиатуре для флешки;
- специальный режим, в котором клавиатура распознается не только как клавиатура, но и еще как, например, mass storage;
- указания пользователю ввести специальную комбинацию клавиш (ага, пусть пользователь печатает сертификат в base64, мне не жалко) и множество других способов.
Один из забавных вариантов — использовать моргания светодиодов (индикаторов num lock, caps lock, scroll lock). Именно компьютер контролирует состояние светодиодов на клавиатуре и передает ей указания зажечь те или иные светодиоды. Можно воспользоваться этим каналом передачи информации в своих целях. Именно об этом мы и поговорим дальше.
На данном этапе я понял, что делать криптографическую клавиатуру мне уже не интересно. А реализовать атаку на DLP-системы, наоборот, очень даже интересно. До свидания, криптографическая клавиатура, здравствуй, устройство извлечения информации.
Чиним то, что не сломано
Передача информации из компьютера через моргание светодиодов — не новая идея. Я даже затрудняюсь указать наиболее ранний источник. Например, литературно такой способ был увековечен в «Криптономиконе» Нила Стивенсона в 1999 году. А технический пост есть по ссылке от 29 октября 2012 года. Тем не менее я пошел по пути изобретения собственной поделки, поскольку художественное описание было недостаточно точным, а ссылку об идее, похожей на мою, я нашел существенно позже создания готовых прототипов.
Задача ясна и состоит из двух частей. Простая часть — написать программу, которая будет представлять заданный файл в виде моргания светодиодов клавиатуры. Сложная — сделать нечто, что представляется клавиатурой и ловит «сообщения» от программы.
Программу я решил особо не усложнять и для начала сделать максимально прямолинейный метод кодирования. Num lock и Caps Lock кодировали два бита (включенный светодиод — 1, выключенный — 0), Scroll Lock служил маркером сохранения, каждый байт разбивался на 4 группы по 2 бита. Подразумевалось, что будущий приемник, получив данные о том, что нажат Scroll Lock, сохранит очередные 2 бита.
Предстояло сделать приемник. Тут мне на помощь пришел один из клонов Малинки, а именно — nano pi m1. Заказывал я его заранее — просто поиграться, тут так совпало, что и применение нашлось.
В качестве ОС я использовал Armbian, который довольно хорошо работал на железке. Сам проект предоставляет довольно простые и удобные скрипты для сборки образов. Пару дней я потратил на разбор того, как работают usb-гаджеты и тестирование HID-гаджета клавиатуры, который идет в комплекте с ОС. Гладко было только в манах. m1 успешно представился клавиатурой и правильно эмулировал нажатия кнопок. Но считывание состояния светодиодов не работало. HID-пакеты прилетали, но содержали некорректные данные. USB-сниффер на стороне обычного компьютера показывал, что пакеты вылетали правильные, но что с ними происходило в железке уже непонятно. Я потратил примерно неделю на попытки отладить работу драйверов, связанных с usb, но безуспешно. Возможно, если бы я взял обычную raspberry pi то все бы завелось сразу. Или может в Armbian все уже подперто костылями и работает сейчас. Уточню, что с момента опытов прошло примерно полтора года и проверок на актуальной версии я не проводил.
Основной причиной того, что я прекратил ломать железку, голову и исходники ОС, стало то, что я нашел решение моих проблем. Забавно, что нашлось оно на Хабре — Пастильда. Вдвойне забавно, что моя идея так сильно пересеклась с идеей аппаратного менеджера паролей. Правда я считаю, что такой менеджер обречен на несуществование в той же степени, как и изначальная идея о шифрующей клавиатуре. Ну да не принципиально… Ребята собрали плату и написали прошивку. 90% работы, которая требовалась мне, была уже сделана.
Попытки достать Пастильду не сразу увенчались успехом. Директор «Третьего пина» потерял ко мне интерес сразу после того, как я сказал, что мне нужна всего одна плата. И я не могу его в этом обвинять — поштучное производство крайне накладное, я надеялся на наличие хотя бы опытных образцов. Так или иначе, но железку я все же достал.
Я никогда не имел дел с написанием прошивок для устройств, только издалека видел. Но мне и не требовалось с нуля писать — код прошивки был на гитхабе. Коллега научил меня собирать его и заливать в железку (#яжнепрограммист, хотя еще точнее будет: «Как я перестал быть программистом и стал программировать в два раза больше»). Дальше было просто — я нашел код, отвечающий за обработку HID-пакетов, и написал сборку битовых последовательностей для записи во внутреннюю память.
И вот долгожданный момент проверки принципиальной работоспособности! Мне удалось корректно «выморгать» светодиодами не очень длинные байтовые последовательности. Во время функциональной проверки несколько проверяемых DLP и СЗИ не увидели ничего интересного в моих действиях и спокойно выпустили данные за периметр. На данном этапе я решил называть данную атаку Radiance, от английского «сияние», «светимость».
Награждение непричастных
Как только эйфория от успешных испытаний прошла, наступило время проводить статистические замеры.
Здесь я уже расстроился, потому что скорость и надежность моего решения были довольно посредственные. Я намерял 5 байт за 4 секунды, т.е. 1,25 б/с.
Это очень медленно. Лучше, чем ничего, но таким образом можно выносить только небольшие файлы, типа документов. Самое время вспомнить о исследователях, которые утверждают, что можно мигать светодиодами и снимать эти моргания фототехникой так, что скорость будет более 1000 бит в секунду. Даже без аналоговых преобразований (хоть я везде и говорю «моргнуть светодиодом», на самом деле обрабатываются только цифровые данные) я не видел способа теоретически поднять скорость выше 10 байт в секунду. Более того, чем меньше я делал задержку по времени между миганием светодиодов, тем больше ошибок кодирования я получал — возможно срабатывали какие-то ограничения операционной системы и часть «миганий» терялась, а может пакеты как-то по-другому формировались или еще какой-то вариант. Это неудивительно, но все же неприятно. В итоге я решил оставить задержку на уровне тех самых 5 байт и на этом успокоиться — эксперимент длительностью в час показал, что на такой скорости ошибок не было.
Но фиксирование паузы между сигналами не означало, что я не буду бороться за скорость.
Одним из замедляющих факторов я видел тот факт, что передача даже двух битов требовала нескольких команд. Представим, что мне нужно передать два единичных бита, и все светодиоды в начальный момент погашены. В моей системе кодирования, чтобы их передать, нужно зажечь все 3 клавиатурных светодиода. Мне потребовалось три раза вызвать функцию, которая зажигает светодиод, эмулируя нажатия кнопки на клавиатуре. Если бы можно было сразу отправлять состояние всех светодиодов за раз, то получилось бы существенная экономия времени. Более того, в HID-пакете передается состояние не 3 светодиодов, а аж 5. Собственно, мне так и виделось увеличение скорости до 10 байт/секунду — отсутствие промежуточных выставлений светодиодов и передача 5 бит за одну посылку.
Но эту оптимизацию я не успел проверить. Потому, что придумал еще более сильную! Забегая вперед похвастаюсь, что скорость достигла 600 байт в секунду без ошибок кодирования. Оказалось, что состояние всех светодиодов действительно можно выставлять программно, отправляя HID-пакеты. А почему бы не отправить HID-пакет своего формата? На самом деле все не так просто.
Есть такая штука — «дескриптор отчетов». Это специальная структура, которая передается клавиатурой при инициализации устройства. Она указывает описание формата общения клавиатуры с компьютером. В общем случае она указывает, что от клавиатуры в компьютер будут уходить пакеты по 6 байт, а принимать она будет пакеты по одному байту, причем 3 бита будут фиксированы. Чтобы не нарушать баланс вселенной, посылая пакеты, не предусмотренные дескриптором, я просто добавил в дескриптор указание, что иногда в клавиатуру будут прилетать пакеты по 32 байта. Ну и стал их отправлять. Этого было достаточно для достижения вышеупомянутых 600 байт в секунду. Потенциально, DLP системы могли бы проверить, что изменился HID-дескриптор и так обнаружить атаку, но основные дескрипторы usb я не трогал — с точки зрения всех систем, какая была клавиатура, такая и осталась — серийный номер и прочие идентификаторы остались прежними.
Новый подход порадовал не только скоростью, но и стабильностью: не было ошибок кодирования, можно было спокойно пользоваться клавиатурой даже во время передачи данных (в предыдущем способе тоже можно было, но это сопровождалось спецэффектами).
Тут подошло время Zeronights 2016 (да-да, я полтора года ленился написать эту статью), на которой и демонстрировал всем желающим работу устройства.
Там же на нее посмотрели представители некоторых DLP и вроде даже обещали добавить защиту. Надо будет при случае все же проверить.
В завершение хочется добавить еще немного слов о развитии этого устройства, которое я делать не буду (конечно не буду, полтора года прошло — хотел бы, уже сделал). К железке можно было бы приделать что-то беспроводное для передачи сигнала — вифий, Bluetooth или даже 3g-модем. Это существенно упростило бы вынос информации.
Другое улучшение лежит в совершенно особой плоскости — а что если я скажу, что для проведения такой атаки вообще не нужно отдельное устройство? Ни raspberry, ни Пастильда. У нас у каждого есть мобильных телефон. У некоторых это даже телефон с ОС Android. Которая, между прочим, недальняя родственница ОС linux. Я больше скажу, вспоминая мои эксперименты с nano pi m1, на Android’е (на рутованном, конечно) есть возможность установить модуль ядра, который будет представляться клавиатурой. Подобный модуль есть в версии Kali для мобильных телефонов, так что все реально. Теперь атака почти бесплатная и как ее еще улучшить я уже не представляю.
Страшилка на ночь
Хочется отвлечься от основной темы статьи и немного удариться в теории заговора и паранойю. Давайте зададим себе очень простой вопрос — что мы первым делом набираем на клавиатуре после включения компьютера? Кто-то изредка заходит в биос настройки UEFI, кому-то нужно выбрать операционную систему из списка, но все-таки большинство пользователей вводят учетные данные для входа в ОС. А что если производители клавиатур добавят в свои устройства, в прошивку код, который будет собирать статистику о пользователе? Довольно легко такая клавиатура получит данные о том, как загрузить ОС и войти от имени пользователя. Потенциально, по клавиатурным нажатиям можно сделать существенные предположения об ОС. Условно говоря, нажатия типа ctrl+alt+f1 и частые нажатия caps lock (о, ирония) свойственны линуксу, а win+m, win+d — уже виндовсу.
Анализируя время, когда компьютер включен, но клавиатура не используется, устройство может сделать предположения о том, когда компьютер остается без присмотра. Вместе с таким знанием, уже подготовлено все для атаки — компьютер без присмотра, если заблокирован, то разблокируем — учетные данные известны, известна ОС — можно выбрать подходящую полезную нагрузку для закрепления в системе. И даже если атака будет замечена, то маловероятно будет обвинена клавиатура, более вероятно, что все будет списано на «вирус». Практически идеальная атака.
Написанное выше выглядит как полностью теоретические измышления. Но долго ли осталось до подобной практики?
Другие статьи блога
→ UAC Bypass или история о трех эскалациях
Исследование механизмов защиты Windows, с обходом запроса UAC.
→ Жизнь без SDL. Зима 2017
Пока разработчики повсеместно не используют SDL у меня всегда будет работа.
Автор: Кравец Василий