«В умных устройствах мы доверяем «облакам» и серверам, но именно там — в ленивых кэшах, разорванных транзакциях и молчаливом доверии к промежуточным идентификаторам — кроются самые опасные бреши. Эта история не про хакера, а про архитектора API, который разделил проверку и действие, и про то, как эта щель десятилетиями остаётся открытой.»
Архитектура безопасности IoT и её слепые зоны
Защита умных устройств строится на нескольких уровнях. Связь шифруется, пользователь проходит аутентификацию, API закрыт от публичного доступа. Всё внимание обычно приковано к локальным угрозам: перехвату сигнала между телефоном и замком, физическому взлому. Но настоящая проблема часто прячется не на периферии, а в центре — в официальном приложении и облачном бэкенде. Они становятся доверенными посредниками, и сбой в их логике может обнулить все остальные меры защиты.
Рассматриваемая уязвимость была не академической. Она позволяла из любой точки мира открыть чужой замок, зная лишь его публичный серийный номер. Не требовалось ни перехватывать пароли, ни взламывать шифрование. Проблема была заложена в логику работы централизованного облачного сервиса.
В основе лежала классическая ошибка проектирования: разделение проверки прав доступа и непосредственного исполнения действия. Стремление к оптимизации и гибкости API привело к разрыву единой операции на два независимых вызова, создав окно для атаки, которую стандартные сканеры легко пропускают.
Разорванная транзакция: как работает уязвимость
В нормальном режиме цепочка действий предсказуема: пользователь входит в приложение, получает токен сессии, отправляет команду на сервер, где проверяются его права на управление конкретным устройством.
В уязвимой реализации для ускорения работы список устройств кэшировался локально в приложении. Для обращения к API использовался публичный серийный номер замка — его можно было увидеть на коробке, в интерфейсе приложения или получить при сканировании Bluetooth.
Критичная команда «открыть» была разбита на два отдельных шага:
- Подготовка команды — вызов, проверяющий права пользователя на целевое устройство.
- Исполнение команды — вызов, инициирующий отправку сигнала непосредственно на замок.
После успешной проверки на первом шаге сервер создавал запись в своей очереди задач и возвращал клиенту её уникальный идентификатор — task_id.
Сбой в разделении обязанностей
В этом разделении и скрывалась брешь. Первый вызов (/api/v1/command/prepare) действительно выполнял проверку прав. Второй вызов (/api/v1/command/execute), запускающий команду, этой проверки уже не содержал. Его логика была примитивна: найти задачу по переданному task_id и выполнить её. Разработчики исходили из предположения, что task_id является секретным, так как выдается только авторизованному пользователю.
Это предположение оказалось ошибочным. Зная публичный серийный номер (device_id) чужого замка, злоумышленник мог:
- Создать легитимную задачу на открытие своего собственного замка, получив валидный
task_id. - В запросе на исполнение (
/api/v1/command/execute) оставить этотtask_id, но подменить параметрdevice_idна серийный номер замка жертвы.
Сервер, обрабатывая второй запрос, видел существующую задачу и отправлял команду «открыть» на устройство, указанное в этом запросе. Привязка задачи к исходному устройству не перепроверялась. Проверка прав произошла один раз и на неправильном уровне абстракции, оставив бэкенд слепым к подмене контекста. По сути, это атака на непоследовательное состояние (state) распределённой транзакции.
[ИЗОБРАЖЕНИЕ: Схематичная диаграмма, показывающая два параллельных потока: «Легитимный запрос» (токен, device_id=мой, task_id=123, команда идёт на мой замок) и «Вредоносный запрос» (токен, device_id=чужой, task_id=123, команда перенаправляется на чужой замок). Бэкенд изображается как единый блок с двумя отдельными модулями «Проверка прав» и «Исполнение», между которыми нет связи.]
Сценарий реальной эксплуатации
Для осуществления атаки требовалось:
- Собственный аккаунт и замок той же марки (источник валидного токена сессии).
- Публичный серийный номер целевого замка. Его можно было получить, например, прослушав эфир Bluetooth или найдя в открытых источниках.
- Возможность анализа сетевого трафика мобильного приложения для изучения структуры API.
Атака сводилась к следующему алгоритму:
- Разведка. Анализируются запросы приложения при открытии двери. Выявляются два ключевых эндпоинта: для подготовки (
/prepare) и исполнения (/execute) команды. - Получение легитимного task_id. Атакующий отправляет запрос на
/prepareдля своего замка. Сервер возвращаетtask_id(например,abc123). - Подмена устройства. Формируется запрос на
/execute. В нём остаётся полученныйtask_id(abc123), но параметрdevice_idменяется на серийный номер замка жертвы. - Неавторизованное исполнение. Сервер находит задачу
abc123и, не проверяя её исходную привязку, отправляет команду «открыть» на устройство, указанное в текущем запросе. - Открытие двери. Команда через облачный message broker доставляется на замок жертвы.
Вся операция выполнялась за секунды. Владелец атакуемого замка не получал уведомлений, так как со стороны бэкенда команда выглядела как часть легитимной, ранее авторизованной операции.

Архитектурные и организационные причины
Этот случай — пример системного сбоя в проектировании распределённых IoT-систем. Ошибки носят как технический, так и методологический характер.
| Просчёт | Почему это опасно | Как исправить |
|---|---|---|
| Разделение проверки прав и исполнения команды | Создаёт окно для атаки на подмену контекста (IDOR на уровне бизнес-логики). Нарушает принцип атомарности транзакции. | Критичные операции должны быть идемпотентными и выполняться в рамках единого вызова API. Если разделение неизбежно, состояние транзакции (привязка пользователь-устройство-задача) должно храниться и проверяться на сервере. |
| Использование публичных идентификаторов в критических операциях | Превращает устройство в легко обнаруживаемую мишень. Знание номера становится половиной успеха для атаки. | Для авторизации использовать внутренние, случайные идентификаторы (UUID), не связанные с публичными данными устройства. Публичный номер не должен фигурировать в запросах на изменение состояния. |
| Отсутствие контроля соответствия между частями состояния (task_id и device_id) | Позволяет злоупотребить легитимным процессом, «перенаправив» задачу. Это ошибка контроля доступа на уровне бизнес-логики. | Каждая задача в очереди должна быть жёстко привязана к устройству и пользователю. При исполнении эти привязки необходимо проверять повторно, сравнивая с данными входящего запроса. |
| Слепая вера в «секретность» промежуточных идентификаторов | Идентификаторы (task_id) могут утекать в логи, быть предсказуемыми или перебираемыми. | Знание идентификатора не должно быть единственным доказательством права. Эффективнее использовать криптографически подписанные токены, где подпись валидирует всю цепочку (пользователь, устройство, действие). |
Организационные предпосылки
Подобные уязвимости часто возникают на стыке зон ответственности. Команда разработки, ориентированная на UX и скорость, дробит операции для повышения отзывчивости. Специалисты по безопасности проводят автоматизированные тесты на стандартные уязвимости (SQLi, XSS), но могут упустить специфичные сценарии, связанные с состоянием распределённых транзакций в IoT. Отсутствует процесс, который рассматривал бы всю цепочку исполнения — от нажатия кнопки в UI до срабатывания физического механизма — как единый поток данных, требующий сквозной валидации. Без моделирования угроз для конкретных бизнес-процессов такие бреши остаются незамеченными до реального инцидента.
Что делать: рекомендации для пользователей и разработчиков
Пользователям устройств, связанных с физической безопасностью, стоит придерживаться практик, снижающих риски даже при наличии ошибок в облаке:
- Принцип эшелонированной защиты. Умный замок — это дополнение, а не замена механическому. Они должны работать в паре.
- Контроль цифрового следа. Избегайте публикации фото упаковки или интерфейса приложения, где виден серийный номер.
- Включение полного аудита. Активируйте журнал всех событий и настройте push-уведомления на любые операции с замком.
- Дисциплина обновлений. Регулярно обновляйте прошивку замка и мобильное приложение — фиксы уязвимостей часто выходят именно так.
Для производителей и интеграторов выводы более системны и затрагивают процессы:
- Security by Design для распределённых транзакций. Архитектура API для критичных операций должна изначально проектироваться с акцентом на целостность транзакции. Если разделение вызовов неизбежно (например, для длительных операций), каждый последующий запрос обязан повторно проверять все параметры безопасности, а не полагаться на состояние, установленное предыдущим вызовом.
- Тестирование логики контроля доступа (авторизации). Помимо стандартного пентеста, необходимо проводить тестирование бизнес-логики (Business Logic Testing). Сценарии должны включать попытки авторизованного пользователя манипулировать параметрами легитимных запросов для выхода за пределы своих прав.
- Принцип минимальной раскрываемой информации. Публичный серийный номер и внутренний идентификатор для авторизации — это разные сущности. Их смешение — прямая дорога к уязвимостям.
- Ориентация на отраслевые практики. Для устройств, затрагивающих физическую безопасность, необходимо учитывать не только общие рекомендации OWASP, но и отраслевые стандарты, которые предъявляют жёсткие требования к архитектуре, управлению доступом и аудиту.
Уязвимость, превращающая API-оптимизацию в удалённый отмычек, — симптом более глубокой проблемы: механического переноса подходов из мира веб-приложений в область, где ошибки мгновенно переводятся в физический мир. Безопасность умного устройства — это свойство всей экосистемы, от датчика до облака. Пока она не проектируется и не тестируется как единое, неделимое целое, дверь для подобных атак будет оставаться приоткрытой.