Аналитики полагают, что в настоящее время в мире существует порядка 10 миллиардов устройств из области «интернета вещей» (IoT). Иногда эти устройства завоевывают свое место на рынке, буквально взбираясь вверх по человеческим задницам. Как оказалось, дешевые и маломощные радиочипы не только отлично подходят для домашней автоматизации — они также меняют способ взаимодействия человека с секс-игрушками. В этом докладе мы погрузимся в мир теледильдоники, технологии секса на расстоянии, при которой осязательные, температурные и прочие ощущения передаются между партнёрами через двустороннюю линию связи. Докладчик расскажет, что безопасность радиоэлектронных анальных секc-игрушек Buttplug может противопоставить злоумышленнику, который находит и использует уязвимости на каждом уровне стека. В конечном счете это позволяет компрометировать и сами секстойз, и устройства, к которым они подключаются.



Хакер под ником smea, или Smealum, начал свою карьеру как разработчик видеоигр для таких игровых консолей, таких как Nintendo DS, попутно пытаясь их взломать. В какой-то момент консоли обзавелись серьезными системами безопасности, и Smea перешел от доморощенного ПО к разработке техник его взлома. Smea известен своей «работой» над Nintendo 3DS и Wii U, хотя также внес вклад в разработку эксплойтов для популярнейших веб-браузеров и стеков виртуализации. Вероятно, теперь он увлекся взломом «умных» анальных пробок.

Конференция DEFCON 27. Buttplug: подлинное тестирование на проникновение. Часть 1



Безусловно, можно управлять входящими сообщениями даже при такой малой длине строки. Например, 30 символов вполне достаточно для выполнения вредоносного JavaScript. На этом слайде показан пример тега длиной 30 символов для изображения из несуществующего источника <img src=a onerror='alert(1)’>, который заставляет приложение вывести сообщение об ошибке. Это сообщение будет выводиться всякий раз, когда загрузка изображения действительно невозможна. На скриншоте видно, что подключение через скомпрометированный донгл позволяет выполнить вредоносный JavaScript.



Ограничение в 32 символа напрягает, потому что при этом трудно реализовать объемную полезную нагрузку, но это вполне возможно. Итак, вы видите, что мы успешно скомпрометировали приложение с помощью USB-ключа и теперь находимся на полпути к тому, чтобы совершить обратный взлом, то есть скомпрометировать приложение с помощью хакерского баттплага. На участке донгл-компьютер взлом может происходить двумя способами: через компьютер можно скомпрометировать донгл, а через донгл можно скомпрометировать компьютер.

Донгл действует как маленький мостик между баттплагом и приложением. Возникает вопрос: можно ли использовать эту же уязвимость, чтобы скомпрометировать приложение на компьютере непосредственно через баттплаг. К сожалению, ответ на этот вопрос отрицательный, и причина в том, что существует еще одно ограничение длины символов сообщений, которые приходят от баттплага к приложению.



Донгл просто запаковывает сообщения баттплага и пересылает их приложению, и на этом шаге можно вставить в них свой HTML-код. Однако за раз он может принять сообщение длиной не более 20 байтов, чего не достаточно для проведения атаки методом XSS. Однако в прошивке донгла есть баг: отсутствует проверка нуль-терминатора в конце строки. Поэтому если вы сможете разместить некоторые неинициализированные данные после окончания 20-ти символьной строки, то вам удастся отправить приложению более 20 символов. К сожалению, я не нашел способа использовать эту уязвимость на практике, но такую возможность стоит иметь в виду.

Таким образом, проблема состоит в том, что, вероятно, вы не сможете использовать эту уязвимость, чтобы заставить приложение выполнить код, полученный непосредственно от баттплага. Это печально, но еще печальней то, что если посмотреть на прошивку донгла, видно, что она в принципе ничего не делает с полученными данными, а просто копирует их в новую строку и отправляет дальше. Поэтому мы не сможем использовать его уязвимость для атаки способом переполнением буфера памяти. Однако если нельзя осуществить взлом приложения напрямую с баттплага, возможно, получится это сделать по цепочке баттплаг-донгл-компьютер?
Хорошо то, что микросхема донгла позволяет разместить гораздо больше кода, чем требуется для оригинальной программы разработчиков Lovense Hush.



Во флэш-памяти донгла имеется область, зарезервированная под загрузчик DFU, область для самого приложения Lovense и закрытая область SoftDevice для драйвера «железа» BLE- чипа Nordic Semiconductor. Здесь обрабатывается сам BLE-протокол. Например, когда приложение хочет отправить игрушке BLE-сообщение, оно обращается к SoftDevice через SVC-вызов. Кроме этих 3-х областей, в донгле имеется неиспользуемая область флэш-памяти достаточного большого объема.
Чтобы найти уязвимость в стеке BLE SoftDevice, нужно использовать реверс-инжиниринг, поскольку это не open-source. Таким же образом я поступил, чтобы найти уязвимость прошивки баттплага. В данном случае очень просто проследить за потоком данных, потому что там тоже нет ASLR, и легко определить код, который будет обрабатывать эти сообщения.



Справа на слайде вы видите обработчик входящих пакетов GATTC (профиль общих атрибутов), которым, по сути, является донгл. В частности, это обработчик чтения по типу ответных пакетов. Я не являюсь специалистом по Bluetooth-устройствам, но думаю, что суть здесь заключается в том, что донгл считывает тип периферийного устройства и задействует обработчики для всех вариантов атрибутов, связанных с этим типом. Это означает, что фактически за раз можно получить больше 1 атрибута, причем размер каждого обработчика пары данных атрибутов кодируется как поле внутри пакета, что позволяет ими управлять.



На слайде показан образец такого пакета. Клиенты GATT могут отправлять пакет запроса «read by type”, который содержит тип и диапазон дескрипторов для чтения. Серверы, которые отвечают на запрос „read by type”, возвращают данные, связанные с обработчиками, в пределах диапазона, соответствующего этому типу. Количество пар дескриптор/данные определяется путем деления длины оставшегося пакета на длину поля пары дескриптор/данные, причем это поле всегда составляет 0x7 или 0x15.



На слайде показана работа интересующей нас функции: вы видите, как пакет заполняется данными массива атрибутов, причем под них выделяется фиксированная длина буфера. Сюда помещается значение дескриптора, а затем связанный с ним указатель. Массив атрибутов представляет собой двоичные данные, которые размещаются внутри буфера в шестнадцатеричном формате. Данные выделены синим цветом, а рядом с ними размещается дескриптор 0D и связанный с ним указатель 00, они выделены оранжевым цветом. Аналогично выглядит пакет второго и третьего обработчика.

Уязвимость состоит в следующем. Если прочесть расположенный справа код, можно увидеть помещенный в фиолетовую рамку параметр attribute_data_length – длина входящего сообщения, значение которого полностью контролируется потенциальным злоумышленником. Если разместить там нулевое значение, мы получим бесконечный цикл.



Бесконечным цикл становится потому, что код не проверяет, находятся ли данные, которые он записывает в выходной буфер, внутри этого выходного буфера. В результате мы получаем классическое переполнение буфера стека, поскольку в устройстве нет ASLR или DEP, а сразу же происходит выполнение кода.

Присвоив нулевое значение и получив бесконечный цикл, вы фактически заменяете мусором все данные RAM. Однако это неудачное решение, так как оно наверняка вызовет сбой устройства. Но если использовать значение, равное 1, то оно ограничит количество байтов, которые находятся внутри входящего сообщения. Это означает следующее — вы сможете слегка переполнить этого буфер, а затем буфер, который базируется на стеке, получит возможность повредить все, что находится рядом с ним.



Посмотрим, как выглядит стек до переполнения. Желтым цветом выделен массив атрибутов буфера, о котором мы говорили, синим – сохраненные регистры, а оранжевый — это обратный адрес. Установив длину атрибута, равную 0х01, мы можем вызвать переполнение множество пар указателя дескриптор/данные. Дескрипторы состоят из 2 байтов, но при этом два верхних байта DWORD дескриптора не очищаются. Буфер, который мы переполняем, находится в стеке, не имеющем ни кукиз, ни ASLR, ни DEP.



Далее мы испытываем систему: посылаем пакет, полный байтов 0хDA с длиной атрибута 0х01. Получается, что мы переписываем обратный адрес указателем на наши атрибутивные данные. Поскольку здесь нет DEP, это означает, что каждый раз при возврате функции будет исполняться код, который находится внутри нашего пакета. Единственное ограничение – нам нужно, чтобы обратный адрес имел установленный младший значащий бит LSB, поэтому код выполняется в режиме Thumb, так как процессор Cortex M0 не поддерживает ARM-режим.



Мы также переписываем несколько локальных переменных, при этом нужно следить за тем, чтобы не переписать что-нибудь используемое на обратном пути. В принципе, мы получаем классический бэкдор-пакет. Если вы обратите внимание на данный стек, то увидите, что переписанное не соответствует границе, что вызовет сбой программы.

Есть еще одно требование, касающееся сохраненных регистров. Это локальные переменные, которые тоже переписываются при возврате функции.



Один из них используется для разыменования 32-х битной границы, и несоответствие содержимого границе вызовет сбой программы. Поэтому нужно сделать так, чтобы saved_arg_3 =0, saved_arg_4 соответствовал DWORD, то есть находился в пределах границы, и чтобы был установлен LSB.

Поэтому нам нужно убедиться в работоспособности данного пакета. К счастью это действительно легко, потому что способ, которым SoftDevice распределяет эти входящие пакеты, представляет собой кольцевой буфер без каких-либо принудительных требований выравнивания. Whiteshark дал возможность убедиться в том, что можно контролировать выравнивание последующего пакета путем изменения длины предыдущего пакета.



Желтым и синим цветом выделены 2 пакета, которые отправляются до того, как будет отправлен пакет эксплойта. Это позволяет мне контролировать выравнивание последнего пакета и сделать его таким, чтобы он не вызвал сбой программы, чего мы и добиваемся.

Замечу, что существует некое инженерное препятствие: Nordic SoftDevice не предоставляет интерфейс для отправки необработанных BLE-пакетов. Для его обхода можно использовать 2 варианта: реализовать свой собственный стек BLE или взломать некоторые хуки в оригинальных пакетах. Поскольку я ленив, то выбрал 2 вариант.

Эти хуки достаточно просты, но требуют некоторого реверс-инжиниринга. Способы взлома можно найти на github, интерфейс получается довольно «грязный» и нет никаких гарантий, что это сработает, но у меня все получилось. Вам все же лучше использовать BTLEJack.

void ble_outgoing_hook(uint8_t* buffer, uint8_t length);

Этот указатель SoftDevice вызывает всякий раз, когда отправляет пакет BLE, поэтому его можно заранее модифицировать:

int ble_incoming_hook(uint8_t* buffer, uint16_t length);

Этот хук SoftDevice вызывает всякий раз после получения пакета BLE. Возвращаемое значение определяет, должна ли быть пропущена нормальная обработка SoftDevice.

int send_packet(void* handle, void* buffer, uint16_t length);

Так выглядит функция отправки необработанного пакета данному BLE-соединению.

Как можно обработать более 4-х байтов кода за раз? Нужно послать несколько пакетов! Справа вы видите кольцевой буфер входящих пакетов BLE. Зеленым цветом показан первый пакет: код оболочки, который выполняет вызов функции с управляемыми параметрами и затем возвращается «чистым». Желтым цветом показан второй пакет – это буфер данных, который может быть использован вызовом функции. Синим цветом изображен третий пакет — буфер, содержащий значения параметров вызова функции, а оранжевым – пакет, запускающий уязвимость с помощью инструкции С1 E7.



После возврата чистой функции мы можем снова отправить этот пакет. Отправка этих 4 пакетов выполняет любой произвольный кусочек кода внутри донгла, и это можно проделывать снова и снова.



Это удобно, потому что таким образом я действительно могу просто вызывать memcpy несколько раз, чтобы скопировать более объемный бинарник кода оболочки в RAM. Затем мы вызовем эту функцию, чтобы пропатчить оригинальный код донгла в памяти, и используем это для компрометации установленного на компьютер приложения. Поскольку полезная нагрузка XSS велика, мы не отправляем ее, а генерируем в коде оболочки на самом донгле. Шелл-код выглядит следующим образом.



В результате этих манипуляций получается следующее: если мы можем контролировать приложение, то можем контролировать донгл и баттплаг.



На участке баттплаг-донгл возможны 2 способа взлома: донгл может скомпрометировать игрушку, а баттплаг – скомпрометировать и донгл, и компьютер. Бонусом идет то, что уязвимость Nordic BLE присутствует не только в изделиях Lovense, но и в любых устройствах, использующих SoftDevise S110, S120 или S130 для клиентской части BLE.

Итак, у нас есть возможность скомпрометировать приложение с помощью баттплага. Как это можно использовать? Мы все еще просто исполняем код JavaScript внутри приложения Lovense, и вопрос в том, что это нам дает? Оказывается, то, что приложение lovense.exe запускается на Medium IL и работает на Windows, предоставляет поистине неограниченные возможности: даже не обладая полномочиями администратора, можно получить доступ к файлам на компьютере, можно выполнить произвольный код, можно внедрить XSS, получить доступ к сети и так далее.



Следующий вопрос: если можно создать программу — вымогатель, которая не просто заражает баттплаг, но и компьютер пользователя, существует ли способ распространить ее дальше, сделав вирусной? Сейчас мы имеем взлом на локальном уровне, но для хакера намного полезнее было бы получить контроль над множеством пользовательских компьютеров через интернет. Как нам это сделать? Социальные функции игрушки, такие как видеочат, текстовый чат, передача картинок и само дистанционное управление существенно расширяют поверхность атаки.

Удаленное управление представляет собой отличную цель, потому что если разработчик хочет использовать проприетарную программу, в ней обязательно будут баги и уязвимости. Как этим воспользоваться? Например, можно отправить партнеру JSON –объект, содержащий команды, к примеру, команду «Vibrate:10»:

{
cate: "id",
id: {
DEADBABEBEEF: {
v: 10
}
}
}

При этом приемник анализирует входящий JSON, генерирует команду для игрушки и отправляет ее дальше, причем здесь существует 2 режима. Первый режим «id:» посылает команду одной конкретной секс-игрушке, второй режим «all: » посылает команду всем удаленным игрушкам.
Правильно ли проверяются входящие данные? Поскольку JSON очень гибок, код, ожидая число, может вместо него получить целую строку. Если мы можем контролировать команды, посылаемые игрушке, то, вероятно, мы сможем использовать баг парсера донгла. На следующем слайде оранжевой рамкой выделено, где используются input- данные, а синей – где они проверяются.
Этот баг состоит в том, что приложение не проверяет должным образом, что input для такой команды, как vibrate, на самом деле является целым числом. В данном случае в режиме «id:» проверяется лишь то, что показатель интенсивности вибрации n>=0, и если вы передадите целое число 12, которое больше нуля, этот параметр пройдет проверку. Даже если передать строку, то есть число в кавычках “12”, система ее примет. Не примет она только строку в виде комбинации чисел и букв, например, “12test”.



Как видите, эта проверка не позволяет нам ввести текстовую команду. Однако если вы посмотрите на нижнюю часть кода, то увидите такую же проверку, только на этот раз приложение проверяет условие n<0. Теперь, если мы введем “12test”, то не пройдем проверку, поскольку приложение посчитает, что данное выражение в виде строки не меньше 0. Но если мы введем строку с проверкой неравенства вида !(“12test” < 0), система посчитает его верным, не смотря на то, что это не целое число и вообще не число, а буквенно-числовая комбинация. По сути это означает, что мы можем ввести в этой команде произвольную строку, которая будет отправлена донглу. Это позволяет нам отправить код эксплойта точно так же, как мы проделали это ранее для компрометации донгла через парсер JSON. Единственная разница состоит в том, что теперь это можно сделать через интернет.



Итак, благодаря багу в реализации фильтра проверки входящих данных мы получили возможность удаленно по интернету, через приложение Lovense скомпрометировать донгл, через который, в свою очередь, можем взломать компьютер пользователя. Взлом донгла является отличной штукой, но условием успеха является согласие партнера передать замаскированному злоумышленнику удаленный контроль над игрушкой. Это удобно для целевой атаки, но совершенно непригодно для вирусной.

Однако текстовый чат и картинки не требуют никаких разрешений, что прекрасно позволяет провести классическую XSS-атаку, отослав в текстовом сообщении чата вредоносный HTML-код. Рассылка вируса становится тривиальной: просто создайте нужную функцию JavaScript и заспамьте своих друзей.



На этом этапе мы можем выполнить код только путем отправки сообщения и в основном достигли своей цели. Конечная полезная XSS-нагрузка работает так:

  1. Сделай все, что должно происходить на машине жертвы.
  2. Захвати объект JavaScript, который позволит получить доступ к чату.
  3. Отправь полезную нагрузку XSS, которая загрузит этот скрипт на компьютеры всех твоих друзей.


Таким образом, мы скомпрометировали каждый узел сети от баттплага до интернета. Теперь можно скомпрометировать любое устройство с любого устройства — мы создали butt worm, или вирус под названием «червь задницы».



Как я и обещал, сейчас я продемонстрирую вам живое видео. Первое, что я покажу – это использование BTLE jack для перехвата соединения между баттплагом и обычной виртуальной машиной Windows, к которой подключен донгл. Сейчас я попробую включить баттплаг – надеюсь, вы все слышите звуки вибрации! (смех в зале). Итак, это сработало, сейчас я попробую добавить свою игрушку в панель управления приложения. Видите, что программа нашла Hush, но подождите минутку! Я забыл запустить процесс BTLE jack. Единственная причина, по которой в данном режиме нужно использовать BTLE jack заключается в том, что это облегчает живое демо, но на практике вы можете перехватить существующее соединение без необходимости сниффинга. Так что я запускаю эту штуку, просто чтобы упростить эксперимент. Повторим все сначала. Вы видите, что соединение с игрушкой установлено.



Сниффер слева показывает, что обнаружил это соединение. Итак, у нас есть приложение, которое связано с нашей секс-игрушкой. Не знаю, слышите ли вы, что я действительно могу управлять баттплагом (smea сдвигает ползунок вверх, после чего слышен усиливающийся звук вибрации). Теперь я выключу эту штуку (двигает ползунок вниз, звук вибрации исчезает). Сейчас мне нужно взломать это соединение. Для этого я копирую несколько параметров, вставляю их в строку smea@ubuntu и в конце ввожу параметр t — команду для перехвата соединения.



Если это сработает, то убьет связь с приложением. Как видите, в окне приложения появилось сообщение, что связь с устройством потеряна. Спасибо BTLE jack за отличный инструмент! Баттплаг отключился от приложения и теперь управляется через ubuntu виртуальной машины. Теоретически мы должны быть в состоянии дистанционно заставить его вибрировать. Я набираю команду Vibrate 20, и как видите, все работает – нам удалось дистанционно управлять баттплагом без помощи официального приложения (аплодисменты зала). Теперь я собираюсь перевести его в режим DFU, и если это сработает, то надо будет остановить эту штуку. Я ввожу соответствующую команду, и вибрация прекращается.



Сейчас я беру свой смартфон и проверяю, смогу ли снова подключить игрушку через приложение. Я нахожу среди своих приложений обновление прошивки баттплага и выбираю цель DfuTarg – устройство, на котором необходимо обновить прошивку, а фактически – внедрить в него вредоносный эксполйт.



Вы видите, как проходит процесс обновления. На экран выводится сообщение, что прошивка устройства успешно обновилась. Теперь я снова попробую подключить баттплаг к приложению, установленному на мой компьютер, и вы видите, что при этом происходит: на экране появляется заставка-вымогатель (аплодисменты зала)!



«Упс, ваша анальная пробка зашифрована! Заплатите за восстановление доступа к этой важной игрушке $50 биткойнами в течение 3-х суток, иначе через неделю вы навсегда ее утратите». Вот как это работает!

Итак, вы выполнили код на донгле, затем на компьютере и через интернет добрались до баттплага. Как видите, в отношении безопасности эта анальная пробка очень слаба, наверное, она сделана Северной Корее. Вы увидели, что у меня была установлена виртуальная машина, которая запускала приложение, не будучи при этом соединенной с донглом или другим железом. Эта ВМ была просто подключена к интернету и будто бы связана с компьютером моего друга. Так что мы успешно добились вирусного распространения вымогателя.

Думаю, что из всего сказанного можно извлечь пару полезных уроков. На примере этого устройства мы рассмотрели, насколько может быть уязвим мир интернета вещей. Некоторые девайсы используются для жизнеобеспечения, и люди не осознают, насколько уязвимы эти новые технологии. Взломав одну «умную» вещь, можно через интернет подцепить на крючок и другие «умные» устройства в вашем доме. Надеюсь, что результат моего исследования применим не только к секс-игрушкам. Кроме того, я намерен изучить весь код этой штуки, так что присоединяйтесь ко мне в Twitter. Я также собираюсь сегодня опубликовать свои инструменты на GitHub на случай, если вы захотите начать взламывать свои собственные баттплаги.



Хочу поблагодарить всех своих друзей, которые помогли мне в пентестинге и познакомили с миром баттплагов, являясь геями-экстремалами. Я не буду называть имен, но Аарон, ты сам знаешь, кто ты такой (смех в зале). Спасибо, ребята, это было круто!


Немного рекламы :)


Спасибо, что остаётесь с нами. Вам нравятся наши статьи? Хотите видеть больше интересных материалов? Поддержите нас, оформив заказ или порекомендовав знакомым, облачные VPS для разработчиков от $4.99, уникальный аналог entry-level серверов, который был придуман нами для Вас: Вся правда о VPS (KVM) E5-2697 v3 (6 Cores) 10GB DDR4 480GB SSD 1Gbps от $19 или как правильно делить сервер? (доступны варианты с RAID1 и RAID10, до 24 ядер и до 40GB DDR4).

Dell R730xd в 2 раза дешевле в дата-центре Equinix Tier IV в Амстердаме? Только у нас 2 х Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 ТВ от $199 в Нидерландах! Dell R420 — 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB — от $99! Читайте о том Как построить инфраструктуру корп. класса c применением серверов Dell R730xd Е5-2650 v4 стоимостью 9000 евро за копейки?