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

Пара слов о фаззинге

Преж­де чем раз­бирать­ся с сетевы­ми про­токо­лами и, тем более, писать код, погово­рим о фаз­зинге в целом.

Фаз­зинг — одна из тех­ник авто­мати­зиро­ван­ного тес­тирова­ния, при которой цели (прог­рамме, про­токо­лу, сер­вису и так далее) пода­ются на вход иска­жен­ные, неп­равиль­ные, неожи­дан­ные или даже слу­чай­ные дан­ные в попыт­ке сло­мать прог­рамму.

По­чему имен­но такие дан­ные? Все очень прос­то: прог­раммис­ты нечас­то про­думы­вают «неп­равиль­ные» сце­нарии исполь­зования прог­рамм, полага­ясь на то, что поль­зователь будет дей­ство­вать разум­но. Прог­рамме же все рав­но: что было написа­но, то и будет исполне­но.

В резуль­тате слиш­ком длин­ная стро­ка, пус­тое поле или несов­мести­мые парамет­ры могут при­вес­ти к впол­не реаль­ным сбо­ям в работе, которые могут не толь­ко нарушить логику исполне­ния, но и открыть дос­туп к воз­можнос­тям, которых быть не дол­жно (если ты понима­ешь, о чем я).

info

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

 

Для чего используют фаззинг?

На дан­ный момент для сле­дующих задач:

  • По­иск уяз­вимос­тей — самый оче­вид­ный вари­ант. Боль­шинс­тво багов сегод­ня (осо­бен­но с уче­том раз­раста­ющей­ся кодовой базы серь­езных про­ектов) находят­ся имен­но с помощью фаз­зеров.
  • Стресс‑тес­ты — неожи­дан­но, но край­не при­ятно быва­ет знать, что твой условный сер­вер WebDAV не упа­дет пос­ле пер­вого пус­того зап­роса от curl.
  • Об­наруже­ние не кри­тич­ных, но неп­рият­ных багов — сог­ласись, мало радос­ти, если твой сайт ста­нет падать пос­ле какого‑нибудь «неп­равиль­ного» зап­роса.
 

Виды фаззинга

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

По спо­собам генера­ции дан­ных методы фаз­зинга делят­ся на сле­дующие виды:

  • Dumb fuzzing (он же фаз­зинг слу­чай­ными дан­ными) — один из самых при­митив­ных под­ходов: переда­ча цели слу­чай­ных зна­чений. К сожале­нию, сей­час такое сра­баты­вает ред­ко, но, как извес­тно, «раз в год и пал­ка стре­ляет».
  • Mutational fuzzing (мутаци­онный фаз­зинг) — наибо­лее популяр­ный на сегод­няшний день под­ход, осно­ван­ный на мутации (изме­нении) при­меров вход­ных дан­ных по все­му диапа­зону воз­можных зна­чений.
  • Generation-based fuzzing (генера­тив­ный фаз­зинг) — не самый популяр­ный, тем не менее нуж­ный вид, поз­воля­ющий получить наибо­лее пол­ное пок­рытие всех допус­тимых сос­тояний.

Ес­ли же делать клас­сифика­цию по пол­ноте обратной свя­зи, то получа­ется сле­дующая кар­тина:

  • Greybox fuzzing (фаз­зинг методом серого ящи­ка) — фаз­зер получа­ет от прог­раммы обратную связь (чаще все­го это пок­рытие кода), что поз­воля­ет умнее и быс­трее находить баги.
  • Blackbox fuzzing (фаз­зинг методом чер­ного ящи­ка) — иног­да быва­ет такое, что из обратной свя­зи есть толь­ко информа­ция, про­дол­жает ли цель фун­кци­они­ровать пос­ле оче­ред­ной пор­ции дан­ных. При отсутс­твии дру­гих вари­антов это луч­ше, чем ничего.

И наконец — раз­деление фаз­зинга по целям иссле­дова­ния:

  • Binary fuzzing (бинар­ный фаз­зинг) — в качес­тве цели выс­тупа­ет бинар­ный файл (прог­рамма).
  • Network fuzzing (сетевой фаз­зинг) — то же самое, но в качес­тве цели — сетевой про­токол.

Да­вай рас­смот­рим пос­ледние два вида попод­робнее.

 

Бинарный фаззинг

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

Чем же бинар­ный фаз­зинг так хорош?

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

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

Глав­ные мас­тодон­ты бинар­ного фаз­зинга — это AFL и AFL++.

Вот что про­исхо­дит во вре­мя их работы:

  1. Ком­пиляция прог­раммы со спе­циаль­ными встав­ками‑фла­гами, необ­ходимы­ми для изме­рения пок­рытия вхо­да.
  2. За­пуск цели с раз­ными вход­ными дан­ными (основная часть работы).
  3. Сох­ранение дан­ных, которые поз­волили открыть новые пути исполне­ния кода.
  4. Фик­сация дан­ных, при которых прог­рамма сва­лилась с ошиб­кой.

AFL++ — форк AFL, который прив­нес мно­жес­тво полез­ных фун­кций. В их чис­ле:

  • ин­тегра­ция луч­ших мутато­ров;
  • встро­енная под­дер­жка QEMU, Frida, Unicorn и некото­рых дру­гих эму­лято­ров;
  • фаз­зинг без исходни­ков путем перес­борки прог­раммы с помощью раз­личных инс­тру­мен­тов.

Но если бинар­ный фаз­зинг такой клас­сный, то почему бы прос­то не при­менить его ко всем целям под­ряд? Нап­ример, к сетевым про­токо­лам. Но с ними это так прос­то не сра­бота­ет.

 

Сетевой фаззинг

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

  1. Слож­ность вход­ных дан­ных — в отли­чие от бинарей, где все парамет­ры чаще все­го мож­но опи­сать при запус­ке прог­раммы, сетевой про­токол тре­бует мно­гос­тупен­чатого обще­ния меж­ду кли­ентом и сер­вером.
  2. Не­обхо­димость пра­виль­ной пос­ледова­тель­нос­ти переда­чи — нуж­но не толь­ко орга­низо­вать диалог, дан­ные еще нуж­но передать в пра­виль­ном поряд­ке: ини­циали­зация → авто­риза­ция → выпол­нение команд.
  3. Мень­ше ско­рость, соеди­нение ненадеж­но — мало того что ско­рость фаз­зинга замед­ляет­ся (по под­сче­там авто­ров AFL, раз­ница может быть в сто раз!), пакеты могут терять­ся, что при­водит к лож­ным сра­баты­вани­ям.
  4. Слож­ность рас­парал­лелива­ния — если соз­дать сто про­цес­сов одной и той же прог­раммы не проб­лема, то соз­дать сеть из ста условных роуте­ров — та еще задача (даже если день­ги не огра­ниче­ны).
  5. От­сутс­твие обратной свя­зи — чаще все­го получить дос­туп к трей­сло­гу прог­раммы невоз­можно и судить о том, смог­ла ли оче­ред­ная пор­ция дан­ных сло­мать обра­бот­ку, при­ходит­ся лишь по наличию отве­та от сер­вера, что сок­раща­ет количес­тво потен­циаль­ных багов (и, кста­ти, отсы­лает нас к треть­ему пун­кту это­го спис­ка).

www

Кста­ти, если ты не знал, обра­бот­ку сетево­го вза­имо­дей­ствия чаще все­го реали­зуют в виде ко­неч­ного авто­мата (finite state machine), о них есть хорошая статья на «Хаб­рахаб­ре».

Нес­мотря на все ужа­сы, фаз­зинг про­токо­лов все же реален, и люди им занима­ются. Для это­го было соз­дано нес­коль­ко прек­расных инс­тру­мен­тов:

  • Peach — ранее проп­риетар­ный фаз­зер, впос­ледс­твии став­ший опен­сор­сным. Сло­жен в исполь­зовании и перес­тал активно раз­вивать­ся.
  • Defensics — ком­мерчес­кий фаз­зер. Не смо­гу о нем ска­зать что‑либо, так как не выпало воз­можнос­ти поп­робовать.
  • AFLnet — рас­ширение клас­сичес­кого AFL, адап­тирован­ное под сетевые про­токо­лы. «Из короб­ки» дос­тупны некото­рые популяр­ные про­токо­лы. Тес­тирова­ние все еще про­исхо­дит методом серого ящи­ка, но в целом это выг­лядит как очень хороший век­тор раз­вития сетево­го фаз­зинга.
  • Sulley — по сути, пра­роди­тель всех сетевых фаз­зеров. Сей­час заб­рошен, но заложил важ­ные кон­цепции нап­равле­ния.
  • Kitty — один из фор­ков Sulley, раз­работан­ный в Cisco SAS и ори­енти­рован­ный на свои спе­цифи­чес­кие задачи.
  • Boofuzz — еще один форк Sulley, на сегод­ня самый популяр­ный выбор. Имен­но о нем мы и будем говорить даль­ше.

info

Ты тоже заметил отсылку к «Кор­порации монс­тров», уви­дев, как называ­ются три пос­ледних инс­тру­мен­та? И не зря: тул­зы дей­стви­тель­но наз­ваны в честь пер­сонажей из муль­тфиль­ма.

 

Boofuzz

Для AFL осо­бая нас­трой­ка перед началом работы не нуж­на, а вот в слу­чае с Boofuzz все чуть слож­нее: пер­вым делом нуж­но опи­сать сам про­токол и порядок сооб­щений, которые отправ­ляют­ся тес­тиру­емо­му сер­веру.

Продолжение доступно только участникам

Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».

Присоединяйся к сообществу «Xakep.ru»!

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии