• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья От нуля до RCE: хакаем baseband и крадём LTE трафик с телефонов (Part 1)

tenac1ous

Shellcode
Модератор
Регистрация
22.01.2023
Сообщения
173
Реакции
232
Предисловие
Приветствую всех, давно не виделись :) Рад, что вся шумиха вокруг форума немного улеглась — теперь могу снова приносить уникальный контент. Но сегодня речь не об этом.


Меня уже давно интересуют атаки на сотовые сети. Однако в современных реалиях большинство таких атак потеряли актуальность: 2G везде отключается, а именно с ним было связано большинство векторов атак. Я долго исследовал эту тему, и чего только не пробовал: side-channel атаки на SIM-карты по замерам потребления тока и дифференциальному анализу, атаки на операторские femtocell для получения доступа к внутренней сети оператора и многое другое. Но всё упирается в один ключевой элемент — злополучный ключ Ki.

Ключ Ki — это суть всей безопасности и настоящий «грааль» современных сотовых сетей. Его записывают на SIM-карту так, чтобы даже физически извлечь его было почти невозможно, в защитные меры входит: рандомизация напряжения во время операций, защита от лазерного считывания и другие меры. Брутфорс и криптоанализ этого ключа через посыл рандомных чисел не имеет смысла: во-первых, SIM-карта просто блокируется после определённого количества неверных запросов, а во-вторых, даже квантовые алгоритмы будут подбирать его слишком долго.

По замыслу архитекторов сети, этот ключ никогда не покидает SIM-карту. Он используется для связывания с случайным числом, которое присылает базовая станция, имеющая доступ к HSS. Сеть выполняет ту же операцию у себя, сравнивает результат, и если они совпадают — аутентификация успешна, сеть считается доверенной. В отличие от GSM, обойти такую аутентификацию невозможно: без знания Ki нельзя заставить телефон подключиться к своей eNodeB. Соответственно, перехват SMS и звонков для «обычного исследователя» невозможен. И если у государственных структур с доступом к Diameter ещё есть возможность извлечь ключ KASME (один из сеансовых ключей), то для обычного дрочилы энтузиаста, даже с дорогим SDR, трафик остаётся полностью недоступным.

Но нам этот Ki не так то больно и нужен, если нужда только в пассивном перехвате траффика то будет хватать и session KASME ключа, и к нашему ограниченому счатью его вполне можно достать, если попасть куда надо.

Зачем нужен KASME:
KASME — это корневой сеансовый ключ LTE, из которого выводятся ключи KeNB (для защиты радиоканала), KNASenc/KNASint (для шифрования и целостности NAS) и ключи для дальнейших хэндоверов. Получив KASME, атакующий может:
  • Расшифровывать весь пользовательский трафик LTE-сессии в реальном времени.
  • Подделывать сигнальные сообщения (NAS/RRC) и отправлять их от имени абонента.
  • Проводить MitM-атаки, изменяя или блокируя пакеты до того, как они поступят на application-уровень.
1757948765083.png



Срок действия ключа:
KASME генерируется при каждой процедуре аутентификации (Attach, TAU, периодическая re-authentication) и обычно действует до следующего обновления сеанса или до выхода устройства из сети. В среднем ключ остаётся валидным до нескольких часов (в зависимости от политики оператора и настроек таймеров T3412/T3402). Это означает, что успешное считывание KASME даёт атакующему «окно возможностей» на всё время жизни текущей сессии, пока телефон не выполнит повторный AKA и не получит новый KASME.
Самое прекрасное это то что после аунтефикации, этот ключ сидит в памяти бейсбенда, и имея к нему доступ нам достаточно просто записивать разшифрованый траффик и любоватся переписками жены которая вам изменяет важной для вас информацией.
1757948897768.png

Целью этой серии статтей является разработка и апробация методики удалённого чтения сеансового ключа KASME из памяти baseband без знания Ki и без завершённой AKA, воздействуя на обработчики, которые принимают кадры/сообщения до включения защиты.

В общем надо думать причем довольно нестандартно, как в известной цитате:
1757942460280.png


Глава 0.1 Почему именно low-level и модем как вектор?

В 3G/4G аутентификация двухсторонняя, однако сигнальные уязвимости сохранялись: ошибки в NAS/RRC-процедурах (Attach/TAU, RRC Setup/Reconfiguration), приводившие к утечке идентификаторов/DoS на реализациях отдельных вендоров. Эти аспекты хорошо документируются стандартами 3GPP (например, TS 36.331 для RRC и TS 24.301 для NAS), но конкретные реализации расходятся и в деталях могут «спотыкаться»

Нас именно интересуют уязвимости на низких уровнях протокола (L1/L2). На это довольно много причин, эти уровни не шифруются и не аутентифицируются, модем также обязан обрабатывать фреймы ещё до того, как сеть решит, доверять ли источнику. Значит, атакующий может сформировать один "правильный" единственный радиопакет, который вызовет краш модема — или, при удачном стечении обстоятельств, RCE.

Исследование KAIST (2025) показало, что специально сформированный пакет может полностью «уронить» коммуникационный процессор смартфона.
1757943985162.png


В 2024-м был продемонстрирован рабочий RCE на модемах Samsung через баг в RLC reassembly, уязвимость классифицирована как переполнение буфера при сборке данных.

Модем (baseband) является привлекательным вектором атаки, потому что именно он первым обрабатывает радиосигнал, ещё до включения шифрования и аутентификации, что позволяет злоумышленнику доставить некорректный кадр напрямую в парсер протокола без участия пользователя. Атака возможна полностью «по воздуху», без взаимодействия жертвы, а радиус действия может варьироваться от сантиметров в экранированной лаборатории до сотен метров в реальных условиях. Baseband работает с высокими привилегиями, имеет доступ к памяти и управляет связью, поэтому его компрометация открывает путь к эскалации на application-процессор или как минимум к перехвату и саботажу связи. Кодовая база модема огромна, сложна и разнородна у разных вендоров, что повышает вероятность ошибок обработки границ, переполнений и рассинхронизаций состояния, а защитные механизмы (ASLR, NX, stack canaries) исторически внедрены неполностью или слабо. Логи baseband труднодоступны, EDR и антивирусы их не видят, а сбои часто воспринимаются как «глюки сети», что усложняет детекцию атак. Дополнительно усугубляет ситуацию медленный цикл обновлений — патчи зависят от вендора чипсета, OEM и оператора, а миллиарды устройств остаются уязвимыми годами. Даже без RCE атака на модем может приводить к DoS, трекингу или даунгрейду связи, что уже серьёзно для жертвы. Всё это делает baseband одним из самых мощных и опасных векторов атаки

1757948794673.png


Но также стоит обсудить ограничения и сложности которые мы сейчас имеем:

1. Разнообразие архитектур модемов
Baseband-процессоры от разных вендоров (Qualcomm, Samsung, MediaTek, HiSilicon) используют разные RTOS, разные форматы прошивок и разные реализации протоколов. Эксплойт, работающий на одной платформе, почти наверняка не будет переносим на другую — его придётся адаптировать под конкретный SoC. Более того, даже внутри одного вендора разные поколения чипов (Snapdragon 855 vs Snapdragon 8 Gen 3) имеют разные адресные пространства, разные схемы защиты памяти (ASLR/NX/CFI) и различную обработку сигнализации.

2. Сложность поиска уязвимости
Ошибки на L1/L2 редки и сложны для воспроизведения. Требуется глубокое понимание 3GPP-спецификаций, синхронизации состояния протокола и структуры кадров. Случайный фаззинг почти всегда отбрасывается модемом на раннем этапе.

3. Сложность эксплуатации
Даже после нахождения бага нужна полноценная эксплуатация: подготовка ROP-цепочек, обход ASLR, работа с ограниченным временем исполнения. Payload приходится загружать многоэтапно.

4. Риск нестабильности
Некорректные пакеты могут приводить к крашу модема или его soft-brick, что в реальных условиях может «вывести» устройство из строя, а не дать доступ к трафику.

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

Глава 0.2 Создание лабораторного стенда
Основная задача стенда — создать среду, в которой можно генерировать, мутировать и отправлять радиокадры на тестовый UE, наблюдать реакцию модема, локализовать баги и перейти от краша к контролируемому чтению памяти.

Это предполагает три направления работы:
  1. Инфраструктурное: железо + софт (SDR, eNB, EPC, мониторинг).
  2. Реверсное: анализ прошивки, поиск интересных функций и структур.
  3. Динамическое: фаззинг и последующая эксплуатация.
1. Железка
В качестве основной SDR-платформы выбран USRP B210 — дуплексный приёмопередатчик с полосой до 56 МГц и поддержкой диапазонов LTE (700–2700 МГц).
1757949084504.png


Для стабильной работы необходим:
  • ПК с USB 3.0, 4+ ядерным CPU (Ryzen 5/Intel i5), 16 ГБ ОЗУ;
  • аттенюаторы (например, 30 dB), чтобы избежать перегрузки входов при прямом подключении модема;
  • экранированная среда (Faraday cage) или направленные антенны, чтобы не мешать сетям оператора нашими кривыми попытками.
  • тестовый телефон с инженерной SIM (известный Ki), подключённый через кабель в экранированной коробке.
  • Внешний OCXO/GPSDO, для длительного слежения без дрифта частоты.

2. Выбор стека​

srsRAN (бывший srsLTE) остаётся оптимальным решением для ресёрча:
  • поддерживает полный стек LTE (eNodeB + EPC + UE);
  • легко компилируется из исходников и модифицируется;
  • имеет понятные конфигурационные файлы и API для автоматизации.
Скачиваем и устанавливаем:
Bash:
git clone https://github.com/srsRAN/srsRAN_4G.git
cd srsRAN_4G
mkdir build
cd build
cmake ../
make
make test


sudo make install
srsran_install_configs.sh user

3. Модифицируем стек под наши больные фантазии
Реализации srsRAN написаны на C/C++, чтобы обеспечивать эффективность и использовать оптимизации компилятора и архитектуры. Компиляция занимает от нескольких минут до часов, поэтому по возможности любые модификации PDU лучше делать вне самого стека RAN. Основная идея модификаций — вытащить «сырые» PDU с максимально низкого уровня (уровень MAC), пересылать их в Python через очередь ZeroMQ, а затем — обратно в драйвер SDR через другую очередь ZMQ.
Такой подход позволяет один раз скомпилировать реализацию RAN, а дальше переключаться между:
  • прозрачной пересылкой трафика (pass-through),
  • и любыми изменениями PDU на любом из уровней OSI.
Это уже не полноценный «задуманный» srsRAN — вряд ли получится обслуживать больше 5 устройств одновременно. Поэтому падение производительности из-за маршрутизации трафика через Python не критично.
Чтобы всё заработало, нужно скачать исходный код реализации RAN, которую вы планируете использовать, и найти файлы обработки PDU для eNB/gNB.
В srsRAN они называются:
  • pdu.h (/lib/include/srsran/mac/)
  • pdu.cc (/lib/src/mac/)

4. Модифицируем pdu.h​

В начало заголовочного файла добавляется новая функция:
C++:
int init_zmq();


5. Модифицируем pdu.cc​

В начало файла добавляются контекстные переменные и реализация функции init_zmq:

C++:
namespace srsran {

zmq::context_t     zmq_ctx_push;
zmq::socket_t      zmq_sock_push(zmq_ctx_push, zmq::socket_type::push);
static const char* zmq_args_push = "tcp://127.0.0.1:5550";

zmq::context_t     zmq_ctx_pull;
zmq::socket_t      zmq_sock_pull(zmq_ctx_pull, zmq::socket_type::pull);
static const char* zmq_args_pull = "tcp://127.0.0.1:5557";

int init_zmq()
{
zmq_sock_push.bind(zmq_args_push);
zmq_sock_pull.connect(zmq_args_pull);
return 0;
}
}

Два сокета на портах 5550 и 5557 используются для передачи данных в Python и получения обратно модифицированных или «прозрачно» пропущенных данных.

Далее модифицируется функция, которая добавляет MAC-заголовок к финальному пакету перед передачей на PHY и драйвер SDR.
В srsRAN она называется sch_pdu::write_packet. В конце функции добавляется:

C++:
zmq::message_t zmq_msg;
zmq_sock_push.send(zmq::message_t((void**)buffer_tx->msg, buffer_tx->N_bytes), zmq::send_flags::dontwait);
zmq_sock_pull.recv(zmq_msg, zmq::recv_flags::none);


return static_cast<uint8_t*>(zmq_msg.data());

6. Инициализация ZMQ​


В main.cc нужно инициализировать очереди ZMQ:
C++:
if (srsran::init_zmq()) {
    cout << "Error INITIALIZING ZEROMQ" << endl << endl;
}
else {
    cout << "ZMQ Fuzzing socket created" << endl << endl;
}


Вся схема должна выглядеть как то так:
1757951718266.png


После того как мы начали получать полные MAC-PDU и можем их изменять, «мир открыт» — можно делать всё, что угодно, вот базовые примеры для разминки:

RRC ConnectionSetup​

RRC ConnectionSetup — одно из критических начальных сообщений, которое содержит настройки DCCH и позволяет UE перейти в RRC Connected.

Python:
#Fuzzing RRC ConnectionSetup package
if b'\x60\x12\x9b' in message:
loc = message.find(b'\x60\x12\x9b')
pdu = message[:loc]
sdu = message[loc:]
fuzzed = rad.fuzz(sdu) # опционально seed
p1 = pdu[0:2]
pduLength = len(pdu+fuzzed)
p2 = pdu[3:]
assembled = p1+pduLength.to_bytes(1,'little')+p2+fuzzed[0:1]+len(fuzzed).to_bytes(1,'little')+fuzzed[2:]
pushSocket.send(assembled)  
fh.write(f"{now} | rd | {assembled} \r\n")
fh.flush()
print(now, "Fuzzed packet sent")


DLInformationTransfer, Security Mode Command​

Python:
#Fuzzing DLInformationTransfer, Security Mode Command
if b'\x08\x00\x81' in message:
loc = message.find(b'\x08\x00\x81')
pdu = message[:loc]
sdu = message[loc:]
fuzzed = rad.fuzz(sdu)
p1 = pdu[0:1]
pduLength = len(pdu+fuzzed)
p2 = pdu[2:]
assembled = p1+pduLength.to_bytes(1,'little')+p2+fuzzed
pushSocket.send(assembled)
fh.write(f"{now} | rd | {assembled} \r\n")
fh.flush()
print(now, "Fuzzed packet sent")

DLInformationTransfer, Auth Request​


Python:
#Fuzzing DLInformationTransfer, Auth request package
if b'\x08\x01\x20' in message:
loc = message.find(b'\x08\x01\x20')
pdu = message[:loc]
sdu = message[loc:]
fuzzed = rad.fuzz(pdu)
p1 = fuzzed[0:1]
pduLength = len(fuzzed+sdu)
p2 = fuzzed[2:]
assembled = p1+pduLength.to_bytes(1,'little')+p2+sdu
pushSocket.send(assembled)
fh.write(f"{now} | rd | {assembled} \r\n")
fh.flush()
print(now, "Fuzzed packet sent")

На этом пока все, в следущих частях мы займемся реверсом прошивки модема, найдем интересные уязвимости, а потом на основе нашего стенда будем пытатся их эксплуатировать удаленно, а пока я буду рад любым обсуждениям и вопросам.
1757952487626.png
 
Последнее редактирование:
PoC для чтения/извлечения KASME или аналогичных сессионных ключей из памяти публично еще не демонстрировался.
Статья выглядит как перспективный подход к такому исследованию и очень интересно, что получится в итоге!​
 
PoC для чтения/извлечения KASME или аналогичных сессионных ключей из памяти публично еще не демонстрировался.
Статья выглядит как перспективный подход к такому исследованию и очень интересно, что получится в итоге!​
Почти все существующие атаки на стек LTE довольно таки скучные, даже государственные комплексы (вау вы собрали 40 тонный кластер из ПЛИСок для того что бы крякнуть A5/3 который уже упокоен вместе з стандартом GSM), поэтому надо приносить что то новое в комьюнити, разность архитектур конечно является проблеммой для именно массового применения НО к счастью сам концепт поиска дыр з этим принципом атаки вполне себе переносимы на другие модемы. В моих влажных мечтах это создание фреймворка который покрывает QUALCOMM/Samsung/Apple модемы большинства популярных телефонов. Иронично но сам процесс считывания KASME относительно тривиальный.
 
Последнее редактирование:
3к баксов стоит на маркетплейсах охуеть само железо но вопрос в монетизации
Железо в подобных атаках это самое дешевое звено, учитывая стоимость цепочки эксплойтов которые могут выполнять RCE на самом модеме (например того же айфона), дампить ключи из памяти а потом посылать их по uplink на нужный приемник, то за эти деньги можно купить неплохой себе домик, где то в Австрии, еще и на лексус останется. Все подобные знания это годы опыта, экспериментов, своего кода и софта, поэтому подобные ценники в 200-500к+ вполне себе оправданны.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх