CodeFest 2019. Максим Бакиров (2ГИС) — Тестирование мусорными данными с libFuzzer

16b6c87229eaf58768d25ed7b2bbbf52?s=47 CodeFest
April 06, 2019

CodeFest 2019. Максим Бакиров (2ГИС) — Тестирование мусорными данными с libFuzzer

Поисковый запрос в 2ГИС содержит 25+ параметров, начиная c введённого текста и заканчивая персональными предпочтениями пользователя. Чтобы обеспечить стабильную работу приложения, мы решили не ограничиваться тестовыми запросами, сгенерированными человеческой логикой. Так в нашей жизни появился фаззинг — тестирование приложения на неправильных, неожиданных или случайных данных. На примере библиотеки libFuzzer расскажу про фаззинг. Узнаем, какую магию он использует под капотом, чтобы находить баги в коде, и как с помощью API его приручить. Не обойдём вниманием приёмы по интеграции в пайплайн разработки.

16b6c87229eaf58768d25ed7b2bbbf52?s=128

CodeFest

April 06, 2019
Tweet

Transcript

  1. Фаззинг или тестирование мусорными данными Максим Бакиров C++ разработчик 2ГИС

  2. None
  3. None
  4. О чём поговорим? — Что такое фаззинг — Фаззинг с

    libFuzzer — Наш опыт и результаты
  5. Что такое фаззинг Фаззинг — тестирование случайными входными данными.

  6. S A TEST?

  7. Это вообще работает? Баг случается с вероятностью 0,000001 = вероятность

    стабильной работы 0,999999 Вызовов 1 млн. 0,999999 ^ 1000000 ~ 0,37 вероятность, что функция отработает стабильно
  8. None
  9. 17%

  10. libFuzzer ✓ Удобное и расширяемое C-API для интеграции

  11. libFuzzer ✓ Удобное и расширяемое C-API для интеграции ✓ Входит

    в поставку с компилятором Clang >= 6
  12. libFuzzer ✓ Удобное и расширяемое C-API для интеграции ✓ Входит

    в поставку с компилятором Clang >= 6 ✓ Хорошая документация
  13. 1.bool FuzzMe(Char data[ ], Int8 size /*[0,128)*/) { 2. return

    size >= 3 && 3. data[0] == 'F' && 4. data[1] == 'U' && 5. data[2] == 'Z' && 6. data[3] == 'Z'; 7.}
  14. 1.bool FuzzMe(Char data[ ], Int8 size /*[0,128)*/) { 2. return

    size >= 3 && // data[ ] = “FUZ”, size = 3 3. data[0] == 'F' && // OK 4. data[1] == 'U' && // OK 5. data[2] == 'Z' && // OK 6. data[3] == 'Z'; // ← Out of bounds access 7.}
  15. None
  16. Как это устроено? тестовый корпус → вызов функции → оценка

    сценариев → следующее поколение → мутации данных → ∞ → артефакты
  17. SanitizerCoverage - программа = набор инструкций

  18. Мутаторы - EraseBytes - InsertByte - InsertRepeatedBytes - ChangeByte -

    ChangeBit - ShuffleBytes
  19. — Парсеров — Компрессии — Криптографии — Регулярных выражений Подходит

    для тестирования:
  20. None
  21. Sanitizers - AddressSanitizer - LeakSanitizer - MemorySanitizer - UndefinedBehaviourSanitizer -

    ThreadSanitizer - libFuzzer itself (!)
  22. Подытожим тестовый корпус → вызов функции → оценка сценариев →

    следующее поколение → мутации данных → ∞ → артефакты
  23. Что получилось — Нашли 10 потенциальных крашей — Внедрили в

    пайплайн разработки — Оцениваем регрессию
  24. Планы на будущее — Интегрировать с AFL — Отслеживать медленные

    запросы — Совершенствовать мутаторы
  25. None
  26. Полезные ссылки Библиотеки libFuzzer — https://llvm.org/docs/LibFuzzer.html American fuzzy lop —

    http://lcamtuf.coredump.cx/afl/ PyJFuzz — https://github.com/mseclab/PyJFuzz HeartBleed — http://heartbleed.com Баг, найденный PyJFuzz — https://github.com/cesanta/frozen/issues/15 Доклад про Monkey Testing — https://2017.codefest.ru/lecture/1141 Доклад про Fuzzing компилятора — https://www.youtube.com/watch?v=S2vBz_ZPAbc
  27. @moximko Максим Бакиров C++ разработчик 2ГИС Вопросы? gmoximko@icloud.ru

  28. СПАСИБО! Максим Бакиров Telegram @moximko

  29. Не подходит если: — Функция выполняется за 10 мс

  30. Не подходит если: — Функция выполняется за 10 мс —

    Входные данные сильно ограничены и структурированы
  31. Не подходит если: — Функция выполняется за 10 мс —

    Входные данные сильно ограничены и структурированы — Функция меняет своё поведение от вызова к вызову
  32. Как внедряли собрали проект-приложение → из коробки мало → свои

    мутаторы → реальные данные → оценка результатов → CI
  33. Как внедряли собрали проект-приложение → из коробки мало → свои

    мутаторы → реальные данные → оценка результатов → CI
  34. Как внедряли собрали проект-приложение → из коробки мало → свои

    мутаторы → реальные данные → оценка результатов → CI
  35. Как внедряли собрали проект-приложение → из коробки мало → свои

    мутаторы → реальные данные → оценка результатов → CI
  36. Как внедряли собрали проект-приложение → из коробки мало → свои

    мутаторы → реальные данные → оценка результатов → CI
  37. Как внедряли собрали проект-приложение → из коробки мало → свои

    мутаторы → реальные данные → оценка результатов → CI
  38. $ echo "aaa" | radamsa aaaa $ echo "aaa" |

    radamsa :aaa $ echo "Fuzztron 2000" | radamsa Fuzztron 4294967296 Radamsa
  39. $ echo "100 * (1 + (2 / 3))" |

    radamsa | bc […] (standard_in) 1418: illegal character: ^_ (standard_in) 1422: syntax error (standard_in) 1424: syntax error (standard_in) 1424: memory exhausted [hang] Radamsa
  40. PyJFuzz {"qTR8SayNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN NNNNNNNNNNNNNNNNNNNNNNNM": {"0BuX8TiFu": 9.04030355791, "GTD4sJG": null}, "BfD2D7a0": {}, "UuWvWx":

    {"le3es2": "xx"t5Uh78", "4PR3qRB": 74.9013428365, "xsu9NjDkx": 57.7924494423}}
  41. None