Скрытые каналы в автомобильной сети: не только для атак (часть 5)

Как правило, скрытые каналы используются для совершения атак на систему – для утечки информации или, в более редких случаях, для передачи команд внедренному агенту. Но есть и другое применение: скрытые каналы можно использовать для защиты. Конкретно — для аутентификации сообщений в сетях, где на дополнительные байты в сетевых пакетах нет места.
Проблема: CAN-шина не знает, кто говорит
Протокол CAN разрабатывался в 1980-х для промышленных и автомобильных сетей. Он простой, надёжный и быстрый, но не безопасный. CAN шина представляет собой витую пару, с ее помощью все ЭБУ в автомобиле соединены в единую информационную сеть. Каждый ЭБУ отправляет пакет в сеть с идентификатором сообщения, и любой другой ЭБУ может его прочитать. При этом, в пакете отсутствует поле «отправитель».


Это не было проблемой, пока автомобили не были подключены к сети Интернет. Теперь же количество точек входа внутрь автомобиля возросло. А значит, автомобиль в целом перестал быть доверенной систем. При этом, для CAN сетей актуально множество атак:
Инъекция пакетов — злоумышленник отправляет команду от имени любого ЭБУ, при условии что возможность проверки легитимности команды отсутствует.

Флудинг — нагружает шину высокоприоритетными пакетами, что приводит к отказу в обслуживании конкретного ЭБУ или всей сети в целом.

Одновременная передача — вызывает коллизии, увеличивает счётчик ошибок у легитимного ЭБУ, в итоге тот замолкает.

Возможные последствия атаки:
Перевод ЭБУ в состояние ошибки или отключение шины
Запрет другим ЭБУ доступа к шине и удаление сообщения
Подделка сообщений, имитирующих реальные сообщения от конкретных ЭБУ с определенными функциями, для нелигитимного выполнения или изменения данных функций. К примеру, нелигитимное включение тормозов.
Решение: MAC поверх скрытого канала по времени
Раз мы не можем добавить подпись внутрь пакета, добавим её снаружи – в задержки между пакетами.
Отправитель кодирует данные в интервалах между отправкой сообщений. Получатель смотрит не только на содержимое пакетов, но и на время их прихода.
Конкретная схема выглядит так:
Отправитель формирует обычное сообщение M1 (payload).
Вычисляет MAC = MAC(ключ, счётчик, данные).
Добавляет задержку перед отправкой M1 – она кодирует цифры счётчика.
Отправляет M2 = MAC.
Получатель принимает M2.
Измеряет задержку.
Проверяет: пришедший MAC == ожидаемый?
Если нет – то декодирует из задержки значение счётчика.
Проверяет: пришедший MAC == ожидаемый с синхронизированным счетчиком?
Если нет — отбрасывает сообщение.

Злоумышленник, который не знает ключ, не может правильно выставить задержку и сформировать корректный MAC – его пакет будет отброшен.
Стенд для тестирования
Чтобы исследовать поведение канала, можно поднять стенд без реального автомобиля, для этого нам необходима виртуальная CAN-шина в Linux (vcan).

Проблема: шум
CAN-шина – среда с непредсказуемыми задержками. Трафик на шине влияет на время доставки каждого пакета. Если злоумышленник (или просто нагруженная шина) вносит случайные задержки, получатель не сможет правильно декодировать счётчик.

Атака выглядит так: злоумышленник начинает флудить шину в момент, когда ожидается аутентификационное сообщение. Задержки «расплываются», счётчик декодируется неверно, MAC не сходится, канал блокируется.
Таким образом, любой скрытый канал по времени устойчив ровно настолько, насколько хорошо учтён шум реальной системы и влияние атак внедрения пакетов в трафик: конкретно в этом примере скрытого канала на CAN-шине без запаса на джиттер и защиты от целенаправленного флуда счётчик и MAC рано или поздно рассинхронизируются. Именно эта атака легла в основу задачи, которую мы предложили школьникам на Национальной Технологической Олимпиаде (НТО) в треке «Информационная безопасность».
Задача на НТО: школьники декодируют скрытый канал
Давайте рассмотрим решение задачи для Национальной Технологической Олимпиады (НТО) в треке «Информационная безопасность».
Легенда задачи:
В ходе исследования сетевого трафика между двумя ЭБУ автомобиля было замечено, что в задержках между пакетами содержатся скрытые данные. Злоумышленник внедрил шум, чтобы запутать передачу. Ваша задача – проанализировать задержки и извлечь закодированное сообщение. Цифра n кодируется задержкой n × d. Участникам выдавался .pcapng-файл с трафиком CAN FD.
Шаг 1. Разобраться со структурой трафика.
Трафик устроен группами по 4 пакета. В каждой группе нас интересует задержка между пакетами приложения и пакетами MAC от этих сообщений приложения. При анализе трафика выявляем, что все пакеты были задвоенными, для анализа оставляем только пакет приложения и следующий за ним:
from scapy.all import *
packets = rdpcap('covert_canfd.pcapng')
data = []
for i in range(0, len(packets), 4):
pkt1 = packets[i]
if i+2 >= len(packets): break
pkt2 = packets[i+2]
delta = float(pkt2.time) - float(pkt1.time)
data.append({'pair_num': i//4 + 1, 'delta': delta})Шаг 2. Обнаружить шум.
При построении графика задержек, видны аномальные выбросы – это внедрённый шум. Они существенно больше остальных значений.

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

Рассмотрим распределение задержек без шума, убирая пакеты, которые дают скачки в задержках.

Шаг 3. Найти базовую единицу d.
Применяем метод локтя для K-means кластеризации задержек. Оптимальное число кластеров – 4 (цифры 0, 1, 2, 3). Находим центры кластеров и вычисляем среднее расстояние между ними – это и есть d. Но на самом деле уже по предыдущему графику понятно, что у нас 4 кластера.
from sklearn.cluster import KMeans
import numpy as np
clean_delays = df[df['delta'] < threshold]['delta']
X = np.array(clean_delays).reshape(-1, 1)
kmeans = KMeans(n_clusters=4).fit(X)
centers = sorted(kmeans.cluster_centers_.flatten())
d = np.mean([centers[i+1] - centers[i] for i in range(3)])
Шаг 4. Декодировать сообщение.
Каждая задержка делится на d и округляется до ближайшего целого:
result_df = df[df['delta'] < threshold]
deltas = result_df['delta'].tolist()
quantized = [round(delta / d) for delta in deltas]
result_str = ''.join(str(int(n)) for n in quantized)
for i in range(0, len(result_str), 26):
print(result_str[i:i+26])Результат: 30233012021310130012302332...
Это и есть флаг. Задача требует понять структуру трафика, заметить шум, применить кластеризацию и разобраться в принципе кодирования.
Заключение
Мы много говорили про скрытые каналы как угрозу безопасности любой системы, в которой присутствует чувствительная информация, и про то, как от этой угрозы защищаться. Однако, на любую проблему можно взглянуть под разными углами, и теперь вы знаете, что скрытые каналы не всегда угроза, а иногда весьма интересный и необычный способ повысить уровень защищенности системы. Использование скрытых каналов для передачи в них аутентификационной информации в сетях, где увеличить размер пакета – дорого либо вообще невозможно, лишь один из таких примеров.
Надеемся, вам было интересно. Следите за обновлениями блога!
Предыдущие статьи цикла:
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.