Did I ever tell you what the definition of insanity is? Insanity is doing the exact... same ******* thing... over and over again expecting... **** to change... That. Is. Crazy.
(c) FarCry 3
Индустрия периферийных устройств снова гонится за СКОРОСТЬЮ и снова забывает про безопасность.
Размеры медиа-файлов кардинально растут, а вместе с ними растут и требования к скорости носителей. Копировать сотни гигабайт RAW-изображений с обычной, даже высокоскоростной SD-карты стандарта UHS-II стало слишком долго. И вот жалобы фотографов на то, что кофе успевает остыть, пока все данные будут скопированы с карты, дошли до председателей SD Association и CompactFlash Association, и те приняли решительные меры: выпустили стандарт SD Express (и CFexpress).
Наша команда (Positive Labs) занимается исследованием безопасности программно-аппаратных систем и системного ПО. Поэтому мы внимательно наблюдали за развитием событий еще с 2018 года — с момента публикации стандарта, который обещал огромный прирост скорости за счет подключения карты к шине PCIe. Но мы следили не только за бенчмарками скорости, хотя она, конечно, внушительная. Наличие PCIe потенциально опасно из-за возможности доступа к памяти устройства, а это очень интересный вектор атак.Вот только до недавнего времени производители контроллеров и пользовательских устройств не спешили с поддержкой стандарта SD Express. Мы уже даже было обрадовались, что они научились на своих ошибках, и теперь не хотят давать внешним устройствам доступ к памяти (спойлер: нет). А пока расскажем, почему уделяем столько внимания почтенной шине PCI.
Для быстрой навигации по статье
Прелюдия: DMA и особенности перевода с немецкого
У программируемых электронных устройств множество применений. Но делать под каждое назначение отдельное устройство с нуля — со специализированными микросхемами — не оправдано экономически. Вместо этого производители комплектующих выпускают чипы или целые блоки электроники как можно более (но не более, чем нужно!) общего применения. Неважно, идет ли речь о создании умной колонки группой суперпрофессиональных инженеров или о сборке любительского ПК. На плечи создателя возлагается обязанность разобраться в номенклатуре и выбрать лучшие компоненты из доступных: процессор общего назначения, самые подходящие сенсоры и датчики и, возможно, даже самую дешевую микросхему памяти. Затем соединить это все, скрестить пальцы, запустить и вдохнуть волшебный дым обрадоваться.
Но любой, кто когда-либо собирал ПК, не соврет, если скажет, что ему важна СКОРОСТЬ. Есть много факторов, которые влияют на общую скорость работы собранного электронного устройства. Например, скорость центрального процессора — то есть того компонента, который исполняет основную программу. Другой фактор — скорость периферийного устройства: количество байтов, которые может в секунду прочесть диск или отправить сетевая карта. Помимо того, важна также скорость обмена между центром и периферией, и она зачастую становится «бутылочным горлышком».
Проблема скорости работы с периферийными устройствами не сводится только к количеству прокачиваемых по проводнику битов. Кроме неё важны также задержки (latency) и простаивание (I/O wait). Простаивание случается, если процессор не делает ничего полезного во время ожидания данных. Это архитектурная проблема модели доступа к периферии.
Кстати о моделях: рассмотрим две из них, PIO и DMA (наконец-то, вот он, акроним из заголовка!). Не будем спешить. Сначала — коротко про (исторически) первую модель, Programmable Input/Output. В ней процессор всегда выступает инициатором обмена. Он запрашивает данные, он их получает, он их переносит в свою память. При этом с точки зрения разработчика это может выглядеть по-разному. Возможно, запрос данных идет какой-то отдельной инструкцией (inb 0x8,0xFF у x86). Или периферия может быть отражена (замаплена, MMIO) в его адресном пространстве, и остается просто сделать mov. В обоих случаях (железная) логика на стороне ЦПУ — обратиться к периферии, дождаться ответа и положить что-то в основную память. Ожидая ответ, процессор, конечно, может что-то считать, но вот класть в память все равно придется ему. На это уйдет много тактов, особенно если нужно скачать много данных, и одно ядро будет занято только этим [1] [2].
Модель Direct Memory Access (DMA) переносит ответственность за последний шаг — положить результат в память — на другое устройство. Это меняет дело: теперь ЦПУ получит уведомление о готовности, когда все уже лежит в памяти. А это значит, что даже во время передачи огромного массива данных ЦПУ может исполнять какие-то полезные инструкции. Но встает вопрос: какое другое устройство, кроме ЦПУ, достойно полного контроля над памятью?
В индустрии приняли решение выделить для этого специальный блок — DMA-контроллер [3]. Все, что требуется от ЦПУ, — это настроить один из них: указать, по какому адресу ожидается увидеть данные [B]. Подчеркнем: инициатором все еще выступает ЦПУ. А контроллер DMA выступает в роли аппаратного ускорителя memcpy (). И это не совсем шутка — на микроконтроллерах этот принцип иногда используется для копирования внутри оперативки. В качестве менее экзотического примера можно привести серверные платформы Intel Xeon.
Проблемы начинаются с идеи «а не поставить ли нам контроллер DMA прямо на периферийное устройство?», или bus mastering DMA.
Все, что было описано выше, не конкретизировало способ подключения периферии. Пришла пора это исправить. В определенный момент люди пришли к концепции подключения устройств друг к другу шиной..
? В электронику название «шина» проникло из электротехники. Туда оно попало из немецкого: у них «шина» означает и «резина на колесе», и «рельс». А нечто подобное рельсу — длинный закрепленный кусок металла — и используется электротехниками для параллельного подключения. Англоязычный термин для этого «рельса» — «bus», или «busbar». «Bus» уходит в латынь: «omnibus» — «для всех». И получается, что «busbar» — это «брусок, к которому все подключено».
Шина — это подключение, которое позволяет соединить более двух устройств, гарантируя возможность того, что хотя бы одно из них может передать информацию нескольким другим, используя при этом один и тот же способ передачи. Существует небольшая сложность в терминологии: на территории СНГ, говоря «шина», чаще имеют в виду «параллельная шина». А это вещь более конкретная: пространство передачи, разделяемое несколькими устройствами, которое в один момент контролирует только одно из устройств. Параллельной шине требуется наличие арбитража в том или ином виде — способа решать, кто сейчас на нее пишет, то есть контролирует ее. Это отличное от bus mastering понятие, хотя и смежное с ним.
Потом случилась микрокомпьютерная революция, и люди начали делать периферию в виде карт расширения, а то и вовсе подключая ее кабелями. А затем люди решили уйти от подхода «одна фирма делает свое устройство и продает лицензии на изготовление периферии, подходящей только к ней» и все (почти) стандартизировали. Apple в рассылку добавить забыли.
Итого: в мире электроники существуют Стандартизированные Шины Передачи Данных. И обычно обсуждение DMA идет в контексте системы, где используется одна из них.
Вернемся к bus mastering DMA. Установка контроллера DMA [4] прямо на устройство дает ему возможность самому инициировать обращения к памяти. Это может быть полезно, например, для сокращения задержек при обработке сетевых пакетов или при работе с изохронными потоками данных. Но так как сам по себе метод не подразумевает участия или хотя бы уведомления [5] ЦПУ о факте обмена, синхронизация с остальными компонентами системы, в особенности с управляющей программой, ложится на плечи разработчиков.
Что, естественно, создает вектор атак (и просто источник ошибок) на систему в случае, когда об этом не задумались.
Примером шины с поддержкой bus mastering DMA является PCI. Эта шина в силу набора исторических причин (привет отделу аналитики рынка IBM ;) ) стала довольно популярна во времена IBM PC/AT. Классическая шина PCI при этом является параллельной шиной, что только подливает масло в огонь терминологических проблем.
Прежде чем осуждать дизайн этой шины с точки зрения безопасности, нужно понимать контекст принятых ее разработчиками решений. Она разрабатывалась для персональных компьютеров: устройств, мобильность которых сильно ограничена. Важнейшими критериями были доступная СКОРОСТЬ, стоимость, простота разработки и использования (plug-and-play). Да и что касается безопасности: не предполагалось, что физические порты будут доступны без открытия крышки устройства — действия, за которым следит физическая безопасность [C]. Действия, которое доступно только квалифицированным кадрам IT. Возможность DMA-атак если и рассматривалась, то была out of scope — в нашем обзоре мы увидим это еще не раз.
Если не сказано обратное, далее мы будем обсуждать DMA именно на примере шины PCI, стараясь, однако, сохранить общность рассуждений там, где это возможно.
Свечи были дорогие...
А что, если кто-то попробует эксплуатировать этот вектор? Потенциальный нарушитель должен будет либо создать периферийное устройство, либо взломать какое-нибудь существующее.
Но все-таки не любое «какое-нибудь». Одним из критериев будет доступность набора операций, которые устройство может выполнять и до, и после взлома. Этот набор разнится от одного устройства к другому. Нет смысла ломать что-то, что ограничено в запросах на уровне ниже, чем прошивка. [E]
С приходом стандартизации и унифицированных компонентов разработка, конечно, стала дешевле... Но это все еще удел организаций, обладающих редкими компетенциями и большими фондами, не одиночек в капюшонах на скейтах. Этот тип взлома мало того что гораздо сложнее с точки зрения навыков, так еще и требует существования устройства, которое:
умеет все, что нужно атакующим,
имеет помимо PCI какой-то управляющий интерфейс [6],
самим фактом подключения не будет нарушать работу системы.
Получив подобную «злую» периферию, как уже было сказано ранее, нужно будет ее как-то подключить к цели... И что далее? У атакующего появляется доступ к памяти, когда он хочет, и теперь, чтобы добиться реализации недопустимого события, можно либо искать в ней какие-то секреты, либо вмешиваться в работу установленных на устройстве программ. Но тут атакующий сталкивается с рядом проблем.
На целевой машине может быть установлен произвольный набор программ и другой периферии. Знание атакующего о том, как извлекать ключ шифрования из VulnerableEncryptionApp.v1.0.0.exe
, не гарантирует в общем случае такого же для VulnerableEncryptionApp.v1.0.1.exe
или AnotherEncryptionApp.v1.exe
. Масштабируемость стремится к нулю, и это еще до того, как были упомянуты сами операционные системы с автоматическим обновлением! (Или ядрами кастомизированной сборки...)
Эта проблема немного пересекается со следующей — универсальной карты оперативной памяти нет. Атакующему нужно будет каким-то образом понять, какой адрес принадлежит какой программе. Запись (а иногда даже чтение) по проблемному адресу может привести к «падению» системы. Что чаще всего не является целью атаки.
К тому же, несмотря на наличие отдельного стандарта на опциональную поддержку горячего подключения, в обычных ПК никто об этом не задумывался. А значит, цель атакующего либо является серверной машиной, либо ее придется перезапустить. Что сильно сужает количество интересных применений.
Отметим, что пока про механизмы защиты речи даже не шло.
...и в карты играть никто не хотел
Дизайн PCI отлично подходил для своей области применения. Все крышки ПК в офисах были закрыты (иногда и опечатаны!). Хакеры осваивали взломы по все более и более популярной технологии сетевого доступа. А те люди, которым нужно было что-то делать с физическим доступом, фокусировались на эксплуатации куда более простых векторов. Например, на кейлоггерах. Да и помимо них хватало низко висящих плодов. Если компьютер все равно нужно было перезагружать, то проще было считать диск отдельно, так как шанс найти шифрование был крайне мал. Для редких случаев, когда оно все-таки было, цепочка доверенного исполнения почти никогда не была защищена полностью — выполнить свой код было легче, просто положив его куда-то на ПЗУ, чем ковыряясь в ОЗУ.
Проведение DMA-атак оставалось уделом академиков [7] и (наверное) ооооочень богатых и прокачанных APT-группировок.
А значит, о защите никто так и не позаботился.
Первый звоночек — CardBus
Через несколько лет на рынке начали набирать популярность ноутбуки. В отличие от наших дней считалось, что хорошо, когда в них есть много разъемов и опций для апгрейда. Одним из таких разъемов стал PC Card. Типичный PC Card позволял подключить к ноутбуку дополнительный сетевой интерфейс. DMA там был, но контроллер был один на шине — и никакого bus mastering.
Но в 1995 году был выпущен PCMCIA 5.0, также известный как CardBus. Он подключался к системной шине PCI-мостом, и карты CardBus имели возможность инициировать обмен DMA.
Это были первые устройства DMA bus mastering, которые можно вставить в ПК, не разбирая его. Но сложность изготовления, видимо, все еще спасала. Первые публичные упоминания атак через CardBus датируются 2009 годом. В них использовали ComBlock COM-1300-C — отладочную платформу для FPGA на карте CardBus.
Однако результаты экспериментов с проведением атак через CardBus послужили исключительно как нестабильный Proof of Concept (PoC), с ошибками в реализации PCI, при подключении через раз вызывающие ошибку в работе цели.
Помимо того, что полученный PoC был крайне нестабильным, он к тому же был и неактуальным, ведь на момент публикации CardBus уже успел устареть. Так что первой целью публичных исследований стал не он.
Первый пожар: FireWire
Не получив приглашения на встречу, где говорилось, что стандарты — это хорошо, в конце 90-х Apple и Sony разработали собственный интерфейс для БЫСТРОГО обмена данными с периферией. Конкурировали они уже не с PCI, а с USB (которая на тот момент в bus mastering не умела). Их интересовали не карты расширений, а куда более понятный людям рынок аудио- и видеотехники. Как и сегодня, в 2001 году медиафайлы были слишком большими для БЫСТРОЙ передачи стандартными способами. И что, наверное, более важно, чем видеокамеры, — так это то, что на рынок как раз вышел iPod. Синхронизация его огромного диска через USB отняла бы очень много времени.
Поэтому на сцене появляется iLink, он же FireWire, он же IEEE1394. Одним из решений для ускорения FireWire явилось внедрение в него DMA... с bus mastering (!). Отметим, что это независимая от PCI шина! На PowerMac G4, к примеру, есть и PCI, и FireWire, но обе шины подключены к системному контроллеру напрямую и раздельно. Хотя в G5, да и в обычных PC, это уже не так. Но все же от проблемного архитектурного решения не отказались, а повторили его.
В декабре 2004 года, в Берлине, исследователи продемонстрировали атаку на ноутбук при помощи iPod. Это был iPod с прошивкой на базе Linux, на котором была общедоступная библиотека работы с FireWire и несколько скриптов на Python. К ноутбуку он был подключен с помощью кабеля FireWire. А монитор целевой машины гордо рисовал окно с запущенной программой — дефейсом. (Ходят слухи, что позже они поехали на 3C и показали то же самое с Apple PowerBook в качестве цели, но тому не найдено ни одного фото- или видеопруфа.)
Тут публика немного напряглась, и (возможно) по залу начал идти шепот: «Отключите в биосе» и «Заклейте порт». Впрочем, довольно быстро Apple ответила, продемонстрировав и плюсы своего дизайна и собственной экосистемы: они настроили свои чипсеты на прозрачную трансляцию адресов, видимых контроллеру FireWire, в отдельное пространство. Таким образом они потеряли немного в СКОРОСТИ работы, но продолжили использовать свой интерфейс, пока он морально не устарел.
Это наследственное
Марш истории продолжался, на смену PCI пришла PCIe — теперь уже не параллельная шина, а скорее дерево подключений «точка — точка». Впрочем, изменив топологию, в PCISIG решили частично сохранить программную совместимость. Ну и возможность bus mastering тоже осталась.
Интерфейс стал гораздо БЫСТРЕЕ, но оставался целиком и полностью внутренним, предназначенным для ПК и серверных машин. Разве что горячее подключение стало чуть более распространено. Начали появляться альтернативные форм-факторы для коннектора. Что объяснимо: стандартный коннектор для ноутбуков великоват.
Ноутбуки... Но разъемы все еще под крышкой, верно? PCIe — это же все-таки внутренний интерфейс! Значит, модель угроз не изменилась и все по-прежнему хорошо.
Тут можно было бы написать про ExpressCard — продолжение идеи CardBus, только с PCIe вместо PCI. Только вот он оказался гораздо менее популярен: большая часть не особо требовательной периферии ушла на USB, а та, что нуждается в СКОРОСТИ — вроде дисков и модемов, — была помещена под крышку с помощью новых форм-факторов. ExpressCard был так же уязвим, как и CardBus, и его продолжают упоминать, говоря про DMA, но широко известных публичных атак он избежал. Впрочем, были адаптеры с него на FireWire и на CardBus. Что тоже стоит отметить — построение цепей Франкенштейна из адаптеров на адаптеры является неотъемлемой частью проведения DMA-атак.
Малые формы PCIe, а конкретно Mini-PCIe и NGFF (он же M.2), плавно подводят наш исторический экскурс к настоящему времени. Они повсеместно используются сегодня, в том числе и в настольных ПК, и в только что появившемся рынке малых одноплатных встраиваемых компьютеров. Впрочем, они получили в наследство от PC Card кое-что очень неприятное помимо bus mastering. И M.2, и даже Mini-PCIe не являются, строго говоря, форм-факторами PCIe.
Если купить три карты Mini-PCIe с одинаковыми на вид разъемами, одна может оказаться просто забавным USB-устройством, вторая будет уметь в PCIe, а третья окажется вообще mSATA. Что гораздо хуже, если взять три ноутбука со слотом Mini-PCIe, их слоты точно так же могут отличаться поддержкой того или иного.
Почти то же самое повторится с M.2, правда, с одним отличием: в этот раз проблему попытались решить расположением механических ключей на разъеме. Так что гипотетически можно отличить функционал слотов на ноутбуке. Практически же остается множество нюансов, в основном на ключе A-E, который в целом может быть USB-only или подключать устройства Root Complex Integrated.
Собственно, когда эти разъемы применяются правильно, они ничего нового не дают атакующим. Кроме, конечно, необходимости иметь нужный адаптер. Они подключают тот же самый PCIe, что доступен в полном размере.
Хакерам тоже хочется скорости и удобства
Возможно, именно об этом подумали в Intel и Apple, начав разработку интерфейса Thunderbolt, который начал массово появляться на рынке с 2011 года. До третьей своей итерации он был представлен в основном для периферии Mac, но начиная с третьей начал встречаться и на ноутбуках платформы Intel [8]. Можно долго обсуждать низкоуровневые особенности этого интерфейса: перекодировку сигнала, сложнейший контроллер, поддержку оптоволокна, несколько портов upstream-downstream и так далее. Но в нашем случае достаточно сказать, что Thunderbolt позволяет подключить прямо на внутренний PCIe внешнее PCIe-устройство дорогим кабелем.
Естественно, наученные горьким опытом FireWire, разработчики интерфейса озаботились дополнительной защитой…
...со второй версии в Thunderbolt появился режим белого списка и возможность отключить проброс PCIe.
Кроме шуток, это опять-таки было оправдано экономически! Чтобы произвести Thunderbolt-устройство, недостаточно, как ранее, найти где-то документацию. В этот раз контроллеры (целый SoC для хост-контроллера!) были на вес золота и поставлялись только авторизированным партнерам. Никакого больше «купить в Китае тонну чипов»! А все авторизированные партнеры обязаны были проходить строгий контроль качества и получать одобрение Intel. План был неплох, но в нем оказалось четыре слабых места.
В качестве ПЗУ эти чипы использовали обыкновенный отдельный модуль SPI flash-памяти.
Данные, включая сам белый список и ID, хранились в ней без подписи и шифрования.
Авторизированные партнеры сделали множество адаптеров на другие шины.
Одной из киллер-фич TBT было подключение eGPU, который в большей части [9] случаев является просто адаптером на полноразмерный PCIe-слот.
В итоге если перед вами был ноутбук (не Apple) и одобренный, например, диск рядом с ним, можно было, не трогая ноутбук, клонировать ID диска и прошить его в свое устройство (см. Thunderspy). Что еще забавнее, могло оказаться, что производитель одобренного диска использовал одинаковые ID для всех дисков этой модели. А если был ноутбук и стоящий рядом док eGPU, надо было иметь в виду: скорее всего, в этот док можно было воткнуть что угодно, и оно получило бы доступ к памяти. (Apple были не так просты — об этом далее.)
Разработчики попробовали еще раз и с выпуском Thunderbolt 3 добавили дополнительный уровень защиты — белый список с криптографической проверкой. Список одобренных ключей все так же можно было вытащить из микросхемы памяти рядом с разъемом. Но что ж, мы вернулись на шаг назад: снова нужно вскрывать целевое устройство — уже неплохо.
Но оставался еще один недостаток. Thunderbolt поддерживает загрузочные устройства, а значит, запретить его подключение на этапе загрузки — риск. По крайней мере некоторые из моделей ноутбуков до 2019 года риска не боятся — все устройства на загрузке они считают доверенными автоматически. С потерей горячего подключения и незаметности вновь стало возможно проводить атаки формата evil maid.
С четвертой версии тщетные попытки защитить сам порт были отброшены на второй план, и вендоры пошли защищать оперативную память целиком.
Методы защиты
Заметим, что в целом еще с первых ревизий оригинальной шины PCI возможность bus mastering — это опция. Когда хост опрашивает устройства на шине, он читает из регистров периферийного устройства PCI IDs и прочую информацию, на основании которой решает, включать ли устройство вообще и разрешать ли ему bus mastering. Но регистры периферийного устройства — тоже источник не доверенный: никакой подписи содержимого стандарт не предусматривает.
Автор также предполагает, что мало кто при разработке PCI-устройств поддерживал вариант развития событий, при котором его устройству откажут в bus mastering. И разработчики прошивок BIOS решили просто давать доступ всем, кто просит. Возможно, поэтому простого рычажка «безопасно, но медленнее», как со SPECTRE, тут нет. Но это лишь догадки автора.
Конечно же, самый известный способ защиты от DMA-атак — это IOMMU. Идея этого механизма в том, чтобы внедрить (отдельную от ЦПУ) трансляцию адресов для периферийных устройств.
Концепция виртуальной памяти и address mapping, скорее всего, знакома читателям, но напомнить о ней точно не будет лишним. Непосредственно вычислительные устройства не работают с ячейками ОЗУ. Вместо этого абстрактная модель большей части современных ЦПУ общего назначения предполагает существование нескольких линейных пространств адресов, в которых по (почти) каждому из адресов доступен один машинный символ.
Основное из этих адресных пространств — физическое. Несмотря на название, некоторые адреса в нем могут ссылаться на MMIO (см. выше про один из видов PIO) или вообще программно-генерируемые значения. Но в первом приближении можно сказать, что оно хотя бы частично соотносится один к одному с доступными ячейками RAM.
Виртуальные адресные пространства создаются искусственно, отдельным настраиваемым блоком логики. Их размер не имеет отношения к доступному объему RAM — только к доступной процессору длине адреса. В свою очередь, каждое отдельно взятое виртуальное АП задает карту своих адресов в физическое АП. Помимо перевода одного адреса в другой, данная карта позволяет задавать правила доступа к конкретному адресу. Например, по каким-то адресам процессору запрещено писать — можно только читать.
Обычно ЦПУ работает в одном из виртуальных пространств и часто переключается между ними.
Но адресные пространства существуют не только для ЦПУ. Главный контроллер шины PCIe независимо обращается к RAM и имеет свое адресное пространство, которое довольно предсказуемо называют PCI Address Space. В общем случае оно не совпадает с физическим пространством адресов ЦПУ! Ранее мы говорили, что Apple исправили FireWire: они просто транслировали весь PCI AS в один из виртуальных CPU AS. Остальные такого сделать не могли: нужно бы было заставить всех авторов драйверов все переделывать.
Когда «злое» устройство будет обращаться к адресу памяти pci0x10000, блок IOMMU в системной шине вместо этого направит запрос, к примеру, в phys0x90000 (вместо phys0x10000 без IOMMU). А какие-то запросы вообще сможет запрещать. Данный механизм, вообще говоря, был описан достаточно давно: раньше, чем первые известные DMA-атаки. У него существует множество конкретных имплементаций от разных вендоров, а какого-то общего стандарта нет. Реализация от Intel называется VT-d, или DMA Remapping. У AMD это называется AMD-Vi. У Apple — DART. Из примечательных ARM своя реализация есть еще у Allwinner и Qualcomm.
С ростом количества публикаций про DMA-атаки в нулевых и десятых производители довольно быстро стали внедрять все это в свои платформы. Можно ли сказать, что все важные платформы защищены и DMA-атаки полностью обезврежены?
Thunderclap
Нет.
Неожиданно, но для того, чтобы сложная система защиты электронного устройства заработала, недостаточно добавить в процессор блок логики. Нужно еще продумать модель угроз, правильно реализовать вышеупомянутую логику, включить ее и правильно настроить. Все это, кстати, нужно сделать во всей производственной цепочке — от процессора до готового ноутбука, включая разработчиков прошивок и разработчиков операционных систем и драйверов.
До середины 2010-х IOMMU был в большинстве ноутбуков и настольных ПК лишь номинально. Только Apple всерьез использовала технологию и практически только одним кнутом заставляла разработчиков драйверов поддерживать ее. Но даже они не на всех машинах и версиях ОС включали ее по умолчанию. Что уж говорить про ПК! Хорошо, если IOMMU был доступен для включения в BIOS Setup. По умолчанию он был отключен — все ради СКОРОСТИ. Да, любая трансляция адресов добавляет задержку в адресации, особенно с малым кэшем. Но даже включение в настройках не означало защиты. Операционные системы тоже либо не имели поддержки, либо не включали ее по умолчанию. Но что важнее — они не могли позволить себе закрыть трансляцией все устройства. Внушительная часть из них на уровне драйверов не имела поддержки переадресации. Такие устройства либо молча не работали, либо молча отправлялись в исключения и получали карту один к одному. Последнее решение имеет все минусы IOMMU по скорости и ровным счетом никаких плюсов в безопасности.
Помимо Apple, разве что мобильные платформы ARM на телефонах имели хорошую поддержку, но туда с DMA было на тот момент сложно залезть и без этого.
Мы не проводим в данной статье обзор средств для DMA-атак, но нельзя не упомянуть PCILeech — презентованный в 2016 году проект из модифицированной прошивки для удачно найденной PCIe-платы PLX Technologies USB3380 и набора готовых программ для проведения прямо «из коробки». Предположительно, именно он сильнее всего повлиял на изменение подхода вендоров, сместив планку цены атаки к паре сотен долларов. Проект развивается и сегодня, уже на базе подешевевших FPGA.
Впрочем, в 2019 году исследование под названием Thunderclap продемонстрировало, что, даже настроив все правильно, расслабляться нельзя. Атакующий может вести себя как абсолютно легитимное устройство (благо кода для эмуляции много в QEMU): получить свой «загончик» IOMMU. Правильно ответить драйверу системы на все запросы. А затем заменить, например, указатель на функцию, если разработчик по недоразумению поместил драйвер в память, доступную на запись устройству. Или, эмулируя сетевой адаптер, подсматривать трафик и инжектировать пакеты.
Помимо простых программных ошибок, есть еще разница в гранулярности IOMMU. Как и MMU процессора, он работает не поадресно, а постранично. Размер страницы IOMMU варьируется, но суть в любом случае в том, что зачастую она может оказаться слишком большой и в нее может попасть что-то лишнее, особенно с адресов соседних устройств — как убедились разработчики Sony PS4, у которых туда попал стек.
Упомянем еще ATS и состояние гонки. Некоторые устройства для ускорения трансляции могли кэшировать их у себя. В PCIe это называется address translation service capability. Думаю, понятно, что для «злого» устройства это просто бесплатный обход IOMMU. Ну а гонки — классическая слабость компьютерных систем. Даже когда прошивка и операционная система правильно настраивают IOMMU, в момент передачи управления это соблюдается не всегда.
...В общем, IOMMU не решает вопрос защиты полностью.
Хочется отдельно выделить атаку Throwhammer — за комбинирование Remote-DMA и DDR bit flip без нарушения ограничений IOMMU вообще.
SD Express
Длинное историческое отступление закончено. Успели ли вендоры озаботиться безопасностью решения?
Нет.
Но давайте по порядку. Как уже было сказано ранее, прирост скорости обещан за счет подключения карты памяти к шине PCIe. Звучит логично: теоретическая пропускная способность самых быстрых карт SD UHS-III достигает ≈600 мегабайт в секунду, в то время как лишь одна линия старенького PCIe 3.0 выдает под 1000 мегабайт в секунду. Однако способ подключения к шине может быть разный. У карт SD есть свой стек протоколов, который несовместим с таковым у PCIe. От контактов до команд — все отличается. Если карту полностью перенести на PCIe, ни одно старое устройство не сможет с ней работать.
Доступная публично урезанная версия стандарта содержит ответы на эти вопросы. Начнем с того, что карты SD Express имеют аналогичный картам SD UHS-II дополнительный ряд контактных площадок. Без этого на PCIe просто не хватит контактов.
Предполагается, что карты Express будут иметь возможность работы в двух режимах. Первый — режим SDIO, когда карта работает по-старому. Во втором режиме карта преобразуется в устройство PCIe/NVMe [D]. Но даже с дополнительным рядом контактов под отдельный PCIe все равно не хватает.
Дизайн-гайд SD Express указывает, что проводники дифференциальных пар (LVDS) — основная медь, по которой летят данные в PCIe, — подключаются к хосту независимо от линий SD. А вот управляющие сигналы коммутируются с линиями SDIO.
Это может помешать осуществить атаку, если хост-контроллер откажется переключать режим. Спецификация гласит, что вендоры хост-контроллеров вольны сами выбирать, в каком режиме инициализировать подключенное устройство, но им НАСТОЯТЕЛЬНО рекомендуют начинать с SDIO. Карты должны поддерживать оба варианта, но как будет на самом деле? Было бы очень удобно просто спаять переходник, который просто пробросит наше PCIe-устройство через SD-разъем, но похоже, что надежды на это мало.
Мы решили, что нужно проверять, как это на самом деле делают вендоры. Итак, мы нашли на рынке четыре хост-устройства. Первое — внешний кардридер, подключаемый к хосту по... USB3?
Подождите-ка. Периферия USB3 не умеет в bus mastering. Тут либо какая-то ошибка, либо идет странное мультиплексирование диффпар с USB на PCIe, подумали мы. Но оказалось, что все гораздо проще. Используемый контроллер JMicron JMS581LT реализует PCIe-хост, частично либо полностью, и общается с картой по PCIe, но вот со своим хостовым устройством он общается по USB 10 Гиб/с, эффективно ограничивая скорость. Интересно в качестве реализации PCIe-хоста, но неинтересно в качестве точки входа для DMA-атак.
Второе устройство — ноутбук ThinkPad с неким Realtek PCIe SD CardReader (как он себя определяет). Осмотр порта SD-карты показал наличие дополнительного ряда линий, требуемого для SD Express! Linux даже грузит для него драйвер rtsx_pci, в котором есть код для проброса PCIe... Только вот оказалось, что стоит в нем чип RTS525A, который SD Express не поддерживает. К сожалению, даташитов на Realtek в открытом доступе найдено не было, так что выяснять это пришлось читая код того самого драйвера.
Третье устройство, ноутбук от MSI, гордо носит в себе контроллер RTS5261, который точно поддерживает SD Express — настолько, что его брошюра даже висит на сайте SD Association. Хотя он сам представляется точно так же, как и 5A, отличаясь только device_id. Установка в него карты SD Express вызвала очень интересную метаморфозу. После события hotplug в дереве устройств PCIe, в том же месте, где был сам контроллер SD Card, появляется некий NVMe-контроллер.
Быстрая проверка спецификации SD Express показывает, что NVMe-контроллер должен стоять в самой карточке. Хммм...
Так как распаивать и реверсить саму карту в планы (в тот день) не входило, встал вопрос о подключении вместо настоящей карты чего-нибудь более интересного. Например, того же PCILeech. Но хотя у нас и есть гора адаптеров для него и мы даже сами разработали универсальную плату-адаптер для подключения M.2, которую показывали на PHDays 2, соорудить что-то из подручных средств не получилось — адаптеров для SD пока никто не делал.
Отсутствие готовых решений стало вызовом, и этот вызов был принят. Мы быстро накидали новый переходник для своей платы-адаптера. Получилось вот такое.
Собственно, переходник прямо с пылу с жару был использован в попытке получить доступ к памяти. Ничего. PCILeech сообщает об ошибке — наше устройство не пронумеровано на шине.
Почитали документацию, подумали протестировать возможность подключения логическим анализатором на линии SDIO настоящей карты. В результате обмен данными начинался все равно в режиме SD. Хост-контроллер посылал карте команду CMD8 с запросом ее возможностей и только после получения правильного ответа начинал переключение в режим PCIe. Это все немного усложнило... Но ничего про криптографию или проверки реквизитов в снятом трафике не было. Было решено попробовать припаять линии управления SD с настоящей карты, а линии диффпар PCIe — с нашего PCILeech.
На удивление, в этот раз PCILeech получил доступ к памяти. Заработало! Произошло событие горячего подключения, экран моргнул, и в диспетчере устройств мы увидели вместо PCIe Card Reader некий (наш) неопознанный Ethernet Controller без драйверов. Систему это ничуть не удивило.
Дальнейшие простые попытки подтвердить возможность какого-либо взлома через полученное подключение свелись к тому, что мы оказались ограничены IOMMU. Значит, разработчики всей этой системы отдали всю безопасность на откуп этой технологии. Между делом мы проверили работу не только на этапе операционной системы, но и в UEFI. Горячего подключения там, конечно, нет, но вот доступ к системе есть — хоть в испытываемом ноутбуке он тоже ограничен IOMMU.
Следующее устройство — портативная игровая консоль AYANEO Air Plus. Она оснащена microSD Express — той же технологией, только в меньшем размере. Впрочем, размер важен, так как адаптеров пришлось делать два вида.
Но зато адаптер показал себя хорошо — в этом устройстве никакого сопротивления от IOMMU мы не встретили. Учитывая популярность PCILeech у читеров, ждем появления его компактной версии в формате SD Card для портативных консолей. (Мы купим пару штук — для исследований, конечно же.)
Избавляемся от проводов
Конечно, в качестве proof of concept полученное решение уже работает. Но все же необходимость иметь на руках ненадежно запаянную настоящую карту немного портит картину — особенно если учесть, что, скорее всего, не каждый хост-контроллер нормально отнесется к такому. Было решено попробовать проэмулировать необходимое взаимодействие. Оказалось, для этого не нужно даже железного SD-контроллера: все можно сделать обычным «ногодрыгом» с помощью Pi Pico, даже без использования аппаратного блока pIO (не путать с PIO/DMA!).
Начиная с SD 7.0, два резервных бита в CMD8 стали кодировать поддержку SD Express и поддержку подачи питания 1V8 с хост-контроллера соответственно. Для обеих наших работающих целей оказалось нужным ответить на нее с этими битами во взведенном состоянии.
Кроме этого, после ответа хост опускает PERST#-линию, которая изначально находилась в логической единице, как только хост опускает эту линию, было необходимо опустить линию CLKREQ в ноль. После этих манипуляций инициализируются PCIe-линии.
Новая ревизия адаптеров на SD Express и microSD Express отправилась в производство уже с посадочным местом под Pi Pico.
Эпилог
Резюмируя: мы видим, что история сделала виток и DMA-атаки снова получили точку входа, которую мы назвали DaMAgeCard.
Единственное отличие в том, что 15 лет назад общедоступных инструментов — ни в железе, ни в программах — не было.
Сегодня же множество открытых проектов предоставляют готовые решения для извлечения и анализа образов памяти, обхода авторизации в современных ОС, атак на криптохранилища. В то время как исследования спокойно из года в год показывают новые методики обхода единственного метода защиты, который и полноценной защитой-то не является. Все это на фоне того, что на руках у пользователей сотни тысяч устройств, которые теперь уже никто не защитит.
А что будет дальше?
SD Express и CFexpress [A], скорее всего, укрепятся на рынке — прирост СКОРОСТИ огромен, и уже сегодня интернет полон восторженных отзывов фотолюбителей. А значит, рано или поздно эта технология из high-end-сектора ноутбуков общего назначения проникнет и в middle-сегмент, и в бизнес. И в другие ниши тоже, как показывает AYANEO. Игровым консолям к аппаратным атакам не привыкать, но есть еще смартфоны и профессиональные видеокамеры... И другие устройства, куда Thunderbolt особенно не впихнуть — в силу форм-фактора или бессмысленности. Возможно, в скором времени мы увидим возможность атаки DaMAgeCard и на них.
Примечания
[1] Мы держим в уме конвейер, суперскалярность и SMT, но они к теме не относятся.
[2] У этой модели есть множество плюсов и помимо безопасности, таких как простота имплементации, кэширования, использования и даже скорость на малых объемах данных.
[3] Это не означает «отдельная плата расширения» или даже «отдельная микросхема», ядро DMA-контроллера может быть прямо на ЦПУ, более того — таких контроллеров в систему может быть установлено несколько.
[4] Если быть дотошным, контроллер DMA тут и ранее, конечно, различаются.
[5] Речь не идет о НЕВОЗМОЖНОСТИ уведомления — лишь о том, что отправка того же прерывания — это то, о чем нужно задуматься разработчикам, тогда как в PIO или «простом» DMA ЦПУ знает о факте транзакции by design.
[6] Это, конечно, не строгое требование. Но учитывая ограниченные ресурсы оборудования, обычные для периферии, без его выполнения эксплуатация будет сильно затруднена: кодировать всю логику проведения атаки целиком в имплант для чужой прошивки — плохо масштабируется, не говоря уже о минимуме места для сохранения извлеченных данных.
[7] Которые разработали железку под названием Tribble в 2003 году — не для атак, а только для съема всей памяти.
[8] Да, именно Intel, а не x86_64, и именно в ноутбуках — к AMD и на настольные ПК оно пришло позже, а разгадка в том, что контроллеры производил только сам Intel.
[9] Странным экспериментальным исключением явилась eGPU от Lenovo для линейки ThinkPad.
[A] Кстати, если фотоаппарату не нужно работать на скорости PCIe, не факт, что то же самое верно для видеокамер. Атаки на камеры?
[B] Тут, конечно, утрирование — скорее всего, понадобится указывать размер данных, настраивать прерывания, режимы транзакций, vectored I/O…
[C] Под физической безопасностью тут понимается комплекс мер по охране имущества, сотрудников и территории предприятия, то есть наем круглосуточной охраны, пломбирование корпуса, tampering protection и взыскания за его нарушения и так далее.
[D] Тут встает дополнительный вопрос: используется ли хост-контроллер SD как PCIe мост, или подключение идет напрямую через другой выделенный под это мост, или… Документация тут не ограничивает производителей.
[E] Как такое возможно? Даже делая чипы с нуля, производители используют заготовки IP-ядер. Они обычно проприетарные и дорогие и могут быть просто устаревшими. Хороший пример — адресация в 32 бита или в 64. Старое устройство отлично работает как работало, но, если кому-то удастся его взломать, в старшие адреса взломщик направлять запросы не сможет.
boingo-00
Это что получается, в новых устройствах можно будет относительно легко вывести PCIe линии?
15432
Ага, похоже, что возвращаемся к временам ExpressCard, "подошёл и воткнул"
strvv
ИМХО, в зависимости от используемого моста, но скорее всего всем будет пофиг на безопасность.