Атака по SMS. Как мы нашли уязвимость в популярном GSM-модеме и раскрутили ее до RCE

Содержание статьи

  • Исследуем модем
  • Общаемся с модемом удаленно
  • Переполнение кучи
  • Что делать с black box окружением?
  • Поиск примитива записи
  • Реализация записи в память на практике
  • Особенности обработки каждого WAP-сообщения
  • Собираем все вместе
  • Исполнение кода
  • Разблокируем память
  • Запускаем свое приложение, без регистрации, но через SMS
  • Возможные риски

В прош­лом году моя я и моя коман­да иссле­дова­ли модем Cinterion EHS5. Мы обна­ружи­ли в его про­шив­ке уяз­вимость перепол­нения кучи при обра­бот­ке сооб­щений про­токо­ла Secure UserPlane Location (SUPL), переда­ваемых в виде SMS. Этот баг поз­воля­ет выпол­нить про­изволь­ный код на уров­не опе­раци­онной сис­темы модема с мак­сималь­ными при­виле­гиями — дос­таточ­но отпра­вить все­го пять SMS через сеть опе­рато­ра.

Най­ден­ная уяз­вимость впос­ледс­твии получи­ла иден­тифика­тор CVE-2023-47610 и высокую оцен­ку кри­тич­ности.

Pentest Award

Этот текст получил пер­вое мес­то на пре­мии Pentest Award 2024 в катего­рии «Девайс». Это сорев­нование еже­год­но про­водит­ся ком­пани­ей Awilix.

warning

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

Мо­демы Cinterion сто­ят в огромном чис­ле самых раз­ных устрой­ств. Даже при­мер­ный спи­сок девай­сов сос­тавить слож­но, пос­коль­ку модель модема не всег­да ука­зана в докумен­тации. Мы изу­чали сай­ты про­изво­дите­лей и таможен­ные дек­ларации импорте­ров раз­ных изде­лий и уста­нови­ли, что такие модемы мож­но встре­тить в умных устрой­ствах, бан­коматах, индус­три­аль­ных шлю­зах, авто­моби­лях и даже медицин­ском обо­рудо­вании.

Ре­зуль­татами иссле­дова­ния мы уже делились на кон­ферен­циях OffensiveCon и Hardware.io.

warning

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

 

Исследуем модем

Итак, наш модем — это модуль в форм‑фак­торе LGA (Land Grid Array), пред­назна­чен­ный для встра­ива­ния в печат­ные пла­ты. Сам модуль сос­тоит из baseband-про­цес­сора Intel X-Gold 625 (XMM 6260), мик­росхе­мы NAND-флеш‑памяти (сов­мещен­ной с 512 Мбит памяти LPDDR), мик­росхе­мы RF-уси­лите­ля и тран­сивера. Модем под­держи­вает стан­дарты GSM, GPRS, EDGE, UMTS и HSPA+.

Что­бы получить про­шив­ку, мы сня­ли защит­ный экран и выпа­яли мик­росхе­му флеш‑памяти, пос­ле чего счи­тали дан­ные с нее на прог­рамма­торе и вос­ста­нови­ли логичес­кие бло­ки из сырого обра­за.

 

Общаемся с модемом удаленно

Cinterion EHS5 под­держи­вает геопо­зици­они­рова­ние с помощью под­систе­мы SUPL. Она отве­чает за обмен спе­циаль­ными сооб­щени­ями меж­ду H-SLP (Home SUPL Location Platform) и SET (SUPL Enabled Terminal). Сам модем при этом — это объ­ект типа SET.

Для ком­муника­ции исполь­зует­ся бинар­ный про­токол ULP. Его дан­ные в сети GSM переда­ются при помощи push-сооб­щений через стек про­токо­лов WAP (Wireless Application Protocol).

На уров­не push-сооб­щений WSP (Wireless Session Protocol) в про­токол ULP заложе­на воз­можность фраг­мента­ции переда­ваемо­го сооб­щения. Это сде­лано для того, что­бы мож­но было переда­вать боль­шие бинар­ные сооб­щения через огра­ничен­ный канал переда­чи SMS. Что­бы фраг­менти­рован­ные пос­лания мож­но было соб­рать на сто­роне SET, они индекси­руют­ся. При этом в самом начале SUPL-сооб­щения ука­зыва­ется еще и раз­мер все­го сооб­щения.

При­мер пер­вой SMS

При­мер пос­леду­ющих SMS

С помощью ста­тичес­кого ана­лиза мы изу­чили час­ти кода ОС модема, а имен­но, учас­тки, отве­чающие за реали­зацию это­го про­токо­ла. Преж­де все­го мы выяс­нили, что в модеме исполь­зует­ся опе­раци­онная сис­тема ThreadX, затем — наш­ли фун­кции соз­дания про­цес­сов и в одном из них обна­ружи­ли код обра­бот­ки тех самых «магичес­ких» зна­чений из SMS-сооб­щений со скрин­шотов выше.

Пос­ле это­го мы углу­бились в изу­чение алго­рит­ма работы.

 

Переполнение кучи

Изу­чая драй­вер, отве­чающий за обра­бот­ку фраг­мента­ции ULP-сооб­щений, мы наш­ли уяз­вимость перепол­нения кучи.

На скрин­шоте выше перемен­ная ULPSizeFromPacket отве­чает за раз­мер все­го пакета ULP, а за раз­мер при­нято­го WAP-сооб­щения — перемен­ная wapTpduLen. Обра­бот­ка WAP-сооб­щений зак­люча­ется в пос­ледова­тель­ном копиро­вании фраг­ментов ULP-сооб­щения в буфер, раз­мер которо­го равен ULPSizeFromPacket.

В соот­ветс­твии с про­токо­лом переда­чи перемен­ные ULPSizeFromPacket и wapTpduLen вычис­ляют­ся незави­симо. Эти перемен­ные име­ют отно­шение к раз­ным уров­ням пред­став­ления дан­ных и кос­венно свя­заны толь­ко в час­ти алго­рит­ма при­ема WAP-сооб­щений: сум­ма раз­меров всех при­нятых WAP-сооб­щений одно­го UPL-сооб­щения не дол­жна пре­вышать ULPSizeFromPacket. Но в алго­рит­ме при­ема WAP-сооб­щений отсутс­тву­ет такая про­вер­ка. Соот­ветс­твен­но, при­нятое WAP-сооб­щение раз­мера wapTpduLen будет безус­ловно копиро­вать­ся в буфер раз­мера ULPSizeFromPacket. Это клас­сичес­кая уяз­вимость типа Heap-based Buffer Overflow.

Мы сфор­мирова­ли соот­ветс­тву­ющее SMS-сооб­щение и с пер­вой же попыт­ки выз­вали перепол­нение буфера на сто­роне модема, что при­вело к его пол­ной перезаг­рузке.

 

Что делать с black box окружением?

Мы наш­ли перепол­нение буфера, и это хорошо. Но нам неиз­вестен его кон­текст, и это пло­хо. У нас нет никакой воз­можнос­ти хотя бы про­читать память модема (RAM), что­бы разоб­рать­ся в про­исхо­дящем… или есть?

При перепол­нении буфера мы получа­ли ста­биль­ный Hardware Fault и перезаг­рузку модема, а в качес­тве обратной свя­зи смог­ли извлечь толь­ко адрес мес­та падения и сос­тояние регис­тров про­цес­сора с помощью AT-коман­ды AT+XLOG.

Что­бы прод­винуть­ся в экс­плу­ата­ции, нуж­но было про­ана­лизи­ровать мес­то падения, получить кон­текст исполне­ния (сос­тояние опе­ратив­ной памяти на момент падения) и разоб­рать­ся в устрой­стве менед­жера кучи опе­раци­онной сис­темы ThreadX. Мы не мог­ли читать память или отла­живать про­шив­ку, одна­ко мы обна­ружи­ли, что при падении в регистр R0 попада­ют кон­тро­лиру­емые нами дан­ные.

Даль­нейший ана­лиз кода про­шив­ки показал, что падение про­исхо­дит внут­ри фун­кции malloc, ког­да прог­рамма пыта­ется разыме­новать ука­затель, содер­жащий кон­тро­лиру­емый нами адрес в регис­тре R0.

Зна­чение 0xFFFFEEEE — «магичес­кое» и озна­чает начало сво­бод­ного бло­ка памяти в куче. В слу­чае если блок занят, в Curr_Chunk[1] вмес­то магичес­кого зна­чения будет ука­затель на струк­туру, опи­сыва­ющую гло­баль­ное сос­тояние менед­жера кучи (HeapBase).

Ес­ли выз­вать перепол­нение таким обра­зом, что­бы в регис­тре R0 ока­зал­ся кор­рек­тный адрес памяти модема, то падения в этом мес­те не про­изой­дет и в R0 сох­ранит­ся зна­чение из памяти по это­му адре­су. Одна­ко если зна­чение не ока­жет­ся кор­рек­тным адре­сом, то прог­рамма упа­дет и зна­чение, записан­ное ранее в R0, мож­но будет про­читать пос­ле перезаг­рузки коман­дой AT+XLOG. Модем заг­ружа­ется всег­да по одно­му сце­нарию, поэто­му меж­ду перезаг­рузка­ми его опе­ратив­ная память будет иметь приб­лизитель­но оди­нако­вый вид.

Эта наход­ка поз­волила нам очень мед­ленно, со ско­ростью 4 бай­та в минуту, счи­тывать память модема путем отправ­ки SMS-сооб­щений, вызыва­ющих перепол­нение кучи. Для авто­мати­зации про­цес­са мы соб­рали стенд, и в ито­ге счи­тыва­ние инте­ресу­ющих областей памяти таким изощ­ренным спо­собом заняло нес­коль­ко недель.

 

Поиск примитива записи

По­ка память счи­тыва­лась, мы занялись деталь­ным изу­чени­ем устрой­ства кучи в ОС ThreadX с целью най­ти при­митив записи. Мы пол­ностью про­ана­лизи­рова­ли код фун­кций malloc и free и опре­дели­ли, что единс­твен­ное под­ходящее мес­то, в котором про­исхо­дит запись в память через двой­ное разыме­нова­ние, находит­ся в коде free, и свя­зано это с осо­бен­ностя­ми ее реали­зации.

Источник: xakep.ru

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *