Підручник з тестування Fuzz (Fuzzing).

⚡ Розумний підсумок

Fuzz-тестування передає програмі недійсні, неочікувані або випадкові дані та відстежує збої, зависання та помилки пам'яті, виявляючи дефекти безпеки, до яких сценарні функціональні тести майже ніколи не доходять самостійно.

  • 🔘 Походження: Бартон Міллер ввів цей термін в Університеті Вісконсин-Медісон, і перші запуску фузз-процесів у 1989 році призвели до аварійного завершення приблизно третини протестованих утиліт UNIX.
  • ☑️ Шестикроковий цикл: Визначити ціль, визначити вхідні дані, згенерувати нечіткі дані, виконати, відстежити поведінку, а потім зареєструвати кожен дефект, що з'являється.
  • Три стратегії покоління: Фазери мутацій спотворюють дійсні зразки, фаззери генерації створюють вхідні дані з моделі, а фаззери протоколів працюють зі специфікацією.
  • 🧪 Зворотній зв'язок щодо висвітлення змінив поле: Сучасні рушії зберігають будь-які вхідні дані, що потрапляють до нового коду, що дозволяє знайти набагато глибші помилки, ніж суто випадкові дані.
  • 🛠️ Інструментарій змінився: Peach Fuzzer та WebScarab архівовані, тоді як AFL++, libFuzzer, OSS-Fuzz, boofuzz ​​та OWASP ZAP є підтримуваними варіантами.
  • Відомі обмеження: Фаззинг знаходить збої, а не логічні недоліки, тому він доповнює, а не замінює перевірку коду та тестування на проникнення.

Підручник з тестування Fuzz (Fuzzing).

Що таке Fuzz Testing?

Тестування на нечіткість або фаззинг — це метод тестування програмного забезпечення, який полягає у введенні недійсних або випадкових даних, що називається FUZZ, у програмну систему для виявлення помилок коду та лазівок у безпеці. Метою fuzz-тестування є введення даних за допомогою автоматизованих або напівавтоматичних методів та тестування системи на наявність різних винятків, таких як збої системи або збій вбудованого коду.

Fuzz-тестування було спочатку розроблено Бартоном Міллером з Університету Вісконсина-Медісона, який придумав цей термін після того, як лінійний шум на модемному з'єднанні призвів до збою програм, які він використовував. Його студенти запустили перші fuzzer-тести у 1989 році та виявили, що приблизно третина утиліт UNIX, на які вони орієнтувалися, виходили з ладу або зависали. Fuzz-тестування - це... тестування програмного забезпечення техніка, і це тип Тестування безпеки.

На діаграмі нижче показано базовий цикл фаззингу, де згенеровані дані надсилаються до тестованої програми та спостерігається відповідь.

Робочий процес фуз-тестування: фаззер генерує спотворені вхідні дані та передає їх тестованій програмі.

Навіщо проводити Fuzz Test?

Фаззинг займає своє місце в плані тестування, оскільки він досліджує вхідні дані, для яких ніхто не думав писати тестовий випадок. Основні причини, чому команди його використовують, перелічені нижче.

  • Фуз-тестування зазвичай виявляє найсерйозніші недоліки та дефекти безпеки, оскільки збій є прямим доказом необробленого вхідного шляху.
  • Нечітке тестування дає ефективніший результат при використанні з Black Box Тестування, Бета-тестування та інші методи налагодження.
  • Нечітке тестування використовується для перевірки вразливості програмного забезпечення, і це дуже економічно ефективний метод тестування, оскільки вхідні дані генеруються, а не пишуться від руки.
  • Фуз-тестування – це один із методів тестування «чорної скриньки». Фузинг також є одним із найпоширеніших методів, які хакери використовують для пошуку вразливостей у системі, тому його запуск спочатку усуває найпростіший шлях для зловмисника.

Види фуз-тестування

Фазери зазвичай групуються за тим, скільки вони знають про програму, яку атакують. Чим більше знає фаззер, тим глибше в код він може його впровадити.

тип Що знає фузер Типове використання
Розмиття чорної скриньки Нічого про внутрішню роботу; він бачить лише входи та виходи. Швидкий дим запускається на бінарному файлі або в робочій кінцевій точці.
Біла коробка розмивається Повний вихідний код, часто поєднаний із символьним виконанням для вирішення важкодоступних гілок. Глибокий аналіз компонента, джерело якого доступне.
Сіра коробка пухнаста Без перевірки вихідного коду, але зворотний зв'язок під час виконання, наприклад, до яких розгалужень коду дійшов вхід. Значення за замовчуванням для сучасних рушіїв, таких як AFL++ та libFuzzer.

Другий, давніший розкол розділяє тупе махінації від розумний фазингТупий фаззер перевертає біти, не маючи уявлення про формат вхідних даних, тому більшість його даних відхиляється першим-ліпшим парсером, який він зустрічає. Розумний фаззер розуміє контрольні суми, поля довжини та структуру повідомлень, тому його вхідні дані витримують перевірку та досягають логіки, що лежить в основі. Фузинг, керований покриттям це вдосконалення сірої коробки, яке зробило фаззинг мейнстрімом: рушій інструментує бінарний файл, зберігає будь-які вхідні дані, які досягають нової гілки, та мутує ті, що залишилися, тому корпус послідовно розвивається до недослідженого коду, а не перезапускається з випадкового шуму.

Як виконати Fuzz Test

Кроки для фуз-тестування включають основні кроки тестування:

Крок 1) Визначте цільову систему — виберіть кінцеву точку бінарного файлу, бібліотеки, служби або протоколу, яка буде атакована, та підтвердьте, що вам дозволено її тестувати.

Крок 2) Визначте вхідні дані — перерахувати всі точки входу, з яких ціль зчитує дані: файли, аргументи командного рядка, змінні середовища, мережеві пакети, поля форм та корисні навантаження API.

Крок 3) Створіть Fuzzed дані — створювати спотворені вхідні дані шляхом змінення дійсних зразків, генерування їх з моделі формату або комбінуванням обох.

Крок 4) Виконайте тест, використовуючи нечіткі дані — запустити ціль на основі згенерованих вхідних даних, в ідеалі в циклі, який автоматично перезапускає процес після кожної невдачі.

Крок 5) Відстежуйте поведінку системи — слідкуйте за збоями, зависаннями, помилками тверджень, надмірним використанням пам'яті та звітами про санітарну очистку, а не лише перевіряйте виведені дані.

Крок 6) Дефекти журналу — зберегти точний вхідний дані, які спричинили кожну помилку, стиснути їх до найменшого відтворюваного випадку та помістити їх у стек tracдодається.

Приклади Fuzzers

Фазери також класифікуються за тим, як вони формують свої вхідні дані, і три підходи, наведені нижче, – це ті, з якими ви зустрінетеся найчастіше.

  • Фуззери на основі мутацій змінювати існуючі зразки даних для створення нових тестових даних. Це дуже простий і зрозумілий підхід: він починається з дійсних зразків протоколу та постійно спотворює кожен байт або файл.
  • Фазери на основі генерації визначають нові дані на основі вхідних даних моделі. Вони починають генерувати вхідні дані з нуля на основі специфікації.
  • Фаззери на основі протоколів залежать від детального знання формату протоколу, що тестується, і це розуміння походить зі специфікації. Це включає запис масиву специфікації в інструмент, а потім використання методу генерації тестів на основі моделі для проходження специфікації та додавання нерегулярності до вмісту даних, послідовності тощо. Це також відомо як синтаксичне тестування, тестування граматики або тестування на робустність. Фаззер може генерувати тестові випадки з існуючого або використовувати дійсні чи недійсні вхідні дані.

Існує два обмеження фаззингу на основі протоколу:

  1. Тестування не може тривати, доки специфікація не стане зрілою.
  2. Багато корисних протоколів є розширенням опублікованих протоколів. Якщо фаз-тестування базується на опублікованих специфікаціях, Випробування покриття для нових протоколів буде обмежено.

Найпростішою формою методу фаззингу є надсилання випадкових вхідних даних програмному забезпеченню або у вигляді пакетів протоколу, або як подія. Цей метод передачі випадкових вхідних даних є дуже потужним для пошуку помилок у багатьох програмах та сервісах. Також доступні інші методи, і їх дуже легко реалізувати. Щоб реалізувати ці методи, нам просто потрібно змінити існуючі вхідні дані, і ми можемо змінити вхідні дані, просто помінявши їх біти.

Типи помилок, виявлених Fuzz Testing

Оскільки фаззинг оцінює прогін за поведінкою програми, а не за очікуваним значенням, виявлені ним дефекти об'єднуються в три родини.

  • Збої тверджень та витоки пам'яті: Ця методологія широко використовується для великих програм, де помилки впливають на безпеку пам'яті, що є серйозною вразливістю. Buffer Тут відображаються переповнення, використання після звільнення та зчитування за межі меж.
  • Недійсний ввід: У фуз-тестуванні фаззери використовуються для генерації недійсних вхідних даних, які використовуються для тестування процедур обробки помилок, і це важливо для програмного забезпечення, яке не контролює свої вхідні дані. Простий фазинг можна розглядати як спосіб автоматизації негативне тестування.
  • Помилки коректності: Фазинг також може бути використаний для виявлення деяких типів помилок «коректності», таких як пошкоджена база даних або погані результати пошуку. Диференціальний фазинг, який подає однакові вхідні дані до двох реалізацій та порівнює відповіді, є звичайним способом їх виявлення.

Інструменти тестування Fuzz

Інструменти, що використовуються у веб-безпеці, можуть широко застосовуватися у фуз-тестуванні, такі як Burp Suite і Peach Fuzzer. Кілька класичних імен, наведених нижче, зараз архівовані, тому їхній поточний статус зазначено поруч із кожним записом.

  • Персиковий ФузерPeach Fuzzer забезпечує надійніше покриття безпеки, ніж сканер. Інші інструменти тестування можуть шукати лише відомі загрози, тоді як Peach Fuzzer дозволяє користувачам знаходити відомі та невідомі загрози. Peach Tech була придбана GitLab, а Community Edition v3 більше не підтримується; наступником, який підтримується, є... GitLab Protocol Fuzzer Community Edition.
  • Спайк проксі: професійний інструмент, який шукає вразливості на рівні додатків у веб-додатках. SPIKE Proxy охоплює основні функції, такі як SQL Ін'єкція та міжсайтовий скриптинг на повністю відкритому Python інфраструктура, і вона була доступна для Linux та WindowsЙого не обслуговували протягом багатьох років, і він включений сюди для історичного контексту.
  • WebScarabWebScarab написано мовою Java і тому є портативним на багато платформ. Фреймворк WebScarab взаємодіє за допомогою протоколів HTTP та HTTPS і працює як перехоплювальний проксі: він дозволяє оператору переглядати та змінювати запити, створені браузером, перш ніж сервер їх отримає, а також переглядати та оновлювати відповіді, згенеровані сервером, перш ніж браузер їх отримає. Будь-яка лазівка, знайдена WebScarab, додається до списку повідомлених проблем. Репозиторій було архівовано у квітні 2024 року і тепер доступний лише для читання.
  • OWASP WSFuzzerWSFuzzer — це програма, ліцензована GPL, написана на Python що орієнтувався на веб-сервіси, а в останній версії на основі HTTP Сервіси SOAP були головною ціллю. Він постачався як частина WebScarab і був знятий з експлуатації разом з ним; OWASP ZAP та його доповнення Fuzzer є рекомендованою заміною.
  • Збережені альтернативи: АФЛ++ та libFuzzer є стандартними механізмами, орієнтованими на покриття, для нативного коду, OSS-Fuzz запускає їх безперервно та безкоштовно для проектів з відкритим кодом, а також дурень охоплює фаззинг мережевого протоколу в PythonШирший список зібрано в посібнику з інструменти тестування безпеки.

Найкращі практики нечіткого тестування

Фаззер, спрямований на ціль і залишений у спокої, рідко знаходить щось особливе. Наведені нижче методи відрізняють кампанію, яка створює зареєстровані дефекти, від тієї, яка лише спалює процесорний час.

  • Почніть з хорошого насіннєвого корпусу. Збирайте реальні, дійсні вхідні дані, які програма вже приймає. Зміна справжнього файлу досягає коду розбору набагато швидше, ніж зміна випадкових байтів.
  • Напишіть невеликий, швидкий джгут. Точка входу повинна виконувати одну дію за один запуск, уникати мережевих викликів та записів на диск, а також швидко повертатися, оскільки пропускна здатність вимірюється кількістю виконань за секунду.
  • Увімкніть санітайзери. Тихе пошкодження пам'яті часто не призводить до аварійного завершення роботи. AddressSanitizer та UndefinedBehaviorSanitizer перетворюють його на негайний, діагностований збій.
  • Бігайте довго і бігайте безперервно. Одногодинний або двогодинний пробіг виявляє поверхневі помилки; глибокі шляхи зазвичай потребують багато годин, тому фаззинг має бути частиною щоночі в завданнях неперервної інтеграції, а не ручного сеансу.
  • Мінімізуйте та усувайте дублікати кожного збою. Стиснути вхідні дані, що не вдаються, до найменшої форми та згрупувати збої за стеком tracе., інакше один баг надходить у вигляді сотень квитків.
  • Зберігайте корпус регресійного аналізу. Додайте кожен відтворюваний вхід до постійного набору, який запускається під час кожної збірки, щоб виправлений дефект не міг непомітно повернутися.
  • Визначте ціль з юридичної точки зору. Змінення роботи стороннього сервісу без письмового дозволу не відрізняється від атаки.

Переваги Fuzz Testing

Використовуваний з реалістичними очікуваннями, фаззинг додає цінності, з якою інші методи навряд чи зможуть зрівнятися.

  • Нечітке тестування покращує тестування безпеки програмного забезпечення.
  • Помилки, виявлені під час фаззингу, іноді є серйозними та часто є тими ж самими, що використовуються зловмисниками, включаючи збої, витоки пам'яті та необроблені винятки.
  • Якщо тестувальники не помічають будь-яких помилок через обмеження часу та ресурсів, ці помилки також виявляються під час нечіткого тестування.
  • Вхідні дані генеруються машиною, тому покриття продовжує зростати протягом ночі без додаткових ручних зусиль.

Недоліки Fuzz-тестування

Ті ж властивості, які роблять фазинг дешевим, також обмежують те, що він може довести.

  • Одне лише нечітке тестування не може дати повної картини загальної загрози безпеці або набору помилок.
  • Нечітке тестування менш ефективне для боротьби із загрозами безпеці, які не викликають збоїв програми, такими як деякі віруси, черв'яки та трояни.
  • Фуз-тестування може виявляти лише відносно прості помилки або загрози, і воно не буде міркувати про бізнес-логіку.
  • Для ефективної роботи потрібен значний машинний час.
  • Встановлення граничної умови з випадковими вхідними даними є дуже проблематичним, хоча тестувальники зараз вирішують значну частину цієї проблеми за допомогою детермінованих алгоритмів, керованих вхідними даними користувача.

Fuzz-тестування проти тестування на проникнення

Обидва види діяльності шукають дефекти безпеки, проте вони відповідають на різні питання та рідко взаємозамінні.

Критерії Тестування нечіткістю Тестування проникнення
Загнаний Автоматизований механізм генерує невірні вхідні дані Досвідчений тестувальник розмірковує про систему
Шукає Збої, зависання та помилки безпеки пам'яті Вразливості, що можуть бути використані, включаючи логічні недоліки та недоліки конфігурації
Глибина Дуже широке охоплення вхідних даних, поверхневе мислення Вузьке охоплення, глибоке мислення
Вихід Відтворення вхідних даних та стеку traces Звіт про результати зі шляхами експлойтів та рейтингами ризиків
Найкращий момент Безперервно, в процесі збірки Періодично, проти кандидата на реліз

На практиці ці два процеси взаємопов'язують одне одного: фаззинг усуває дешеві, автоматизовані збої, так що обмежений час тестувальника витрачається на недоліки, які може помітити лише людина.

Поширені запитання

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

Фуз-харнінг — це невелика функція, яка передає один буфер фаззованих байтів коду, що тестується. Він повинен уникати глобального стану, запису файлів та мережевих викликів, щоб рушій міг запускати його тисячі разів на секунду.

Година-дві виявляють поверхневі помилки. Серйозні кампанії тривають багато годин або днів, оскільки нове висвітлення надходить спалахами. Плато на кривій висвітлення, а не показники годинника, є чесним сигналом того, що кампанії перестали окуповуватися.

AddressSanitizer виявляє переповнення буфера та використання після звільнення, UndefinedBehaviorSanitizer виявляє неправильне використання цілих чисел та вказівників, а MemorySanitizer виявляє зчитування неініціалізованої пам'яті. Без них багато пошкоджень проходять непомітно, і фаззер взагалі не повідомляє про жодні збої.

Відтворіть його, мінімізуйте вхідні дані до найменшого випадку невдачі, згрупуйте його зі збоями, що мають спільний стек. tracе., потім подайте один квиток через звичайну процес управління дефектами та додати вхідні дані до регресійного корпусу.

Вони поділяють випадковість, але не намір. Тестування на мавпах викидає довільні дії користувача на запущений інтерфейс, тоді як фаззинг орієнтується на певний вхідний парсер та вимірює покриття коду, щоб він міг спрямувати себе на код, до якого попередні вхідні дані ніколи не доходили.

Мовні моделі використовуються для розробки схем нечітких API, синтезу початкових даних для екзотичних форматів, а також кластеризації та узагальнення звітів про збої. Механізм все ще надає зворотний зв'язок щодо покриття; модель переважно усуває необхідність ручного налаштування.

Копілот GitHub може створити точку входу libFuzzer, файл збірки та генератор початкового значення з існуючої сигнатури API. RevУважно перегляньте результат, оскільки система, яка непомітно ігнорує помилки, не повідомлятиме про збої.

Підсумуйте цей пост за допомогою: