7.16M
Category: programmingprogramming

Введение в фаззинг

1.

Введение
в фаззинг
Виктория Егорова
Заместитель директора
Департамента анализа безопасности
1

2.

SDLC
2

3.

SDLC
3

4.

SDLC
4

5.

Загадка Жака Фреско
int main(int argc, char* argv[]) {
int fd;
char* buffer;
int flags = O_WRONLY|O_APPEND|O_CREAT;
if ((fd = open(”data.log”, flags, 0666)) == 0)
exit(1);
buffer = malloc(u32size + 1);
read(0, buffer, u32size);
write(fd, buffer, u32size);
return 0;
}
На размышления дается 30 секунд
5

6.

Загадка Жака Фреско
int main(int argc, char* argv[]) {
int fd;
char* buffer;
int flags = O_WRONLY|O_APPEND|O_CREAT;
if ((fd = open(”data.log”, flags, 0666)) == 0)
exit(1);
buffer = malloc(u32size + 1);
read(0, buffer, u32size);
write(fd, buffer, u32size);
return 0;
}
На размышления дается 30 секунд
6

7.

Загадка Жака Фреско
int main(int argc, char* argv[]) {
int fd;
char* buffer;
int flags = O_WRONLY|O_APPEND|O_CREAT;
if ((fd = open(”data.log”, flags, 0666)) == 0)
exit(1);
buffer = malloc(u32size + 1);
read(0, buffer, u32size);
write(fd, buffer, u32size);
return 0;
}
На размышления дается 30 секунд
7

8.

Загадка Жака Фреско
int main(int argc, char* argv[]) {
int fd;
char* buffer;
int flags = O_WRONLY|O_APPEND|O_CREAT;
if ((fd = open(”data.log”, flags, 0666)) == 0)
exit(1);
buffer = malloc(u32size + 1);
read(0, buffer, u32size);
write(fd, buffer, u32size);
return 0;
}
На размышления дается 30 секунд
8

9.

Загадка Жака Фреско
int main(int argc, char* argv[]) {
int fd;
char* buffer;
int flags = O_WRONLY|O_APPEND|O_CREAT;
if ((fd = open(”data.log”, flags, 0666)) == 0)
exit(1);
buffer = malloc(u32size + 1);
read(0, buffer, u32size);
write(fd, buffer, u32size);
return 0;
}
На размышления дается 30 секунд
9

10.

Загадка Жака Фреско
int main(int argc, char* argv[]) {
int fd;
char* buffer;
int flags = O_WRONLY|O_APPEND|O_CREAT;
if ((fd = open(”data.log”, flags, 0666)) == 0)
exit(1);
buffer = malloc(u32size + 1);
read(0, buffer, u32size);
write(fd, buffer, u32size);
return 0;
}
На размышления дается 30 секунд
1
0

11.

11

12.

1
2

13.

Обнаружение
нестандартного/неожиданного поведения
`LS –AL /`
Ошибки сегментации
touch tmp/blns/fail.bin
§¶℔Ѓ: D0 83
Исключения
śṏUśḿ BFśṏśśśśṏś
+1E4F, UTF-8
Отличия в поведении
Утечки памяти
1
3

14.

Обнаружение
нестандартного/неожиданного поведения
`LS –AL /`
Ошибки сегментации
touch tmp/blns/fail.bin
§¶℔Ѓ: D0 83
Исключения
śṏUśḿ BFśṏśśśśṏś
+1E4F, UTF-8
Отличия в поведении
Утечки памяти
1
4

15.

Доисторический фаззер
$ head –c 1000 /dev/urandom > input.sample
$ /usr/bin/prog -f input.sample
1
5

16.

Этапы фаззинга
Инициализация
1
6

17.

Этапы фаззинга
Инициализация
1
7

18.

Эксперимент
Подробнее: https://lcamtuf.blogspot.com/2014/11/pulling-jpegs-out-of-thin-air.html
1
8

19.

Словарь умных слов
http
pdf
Больше готовых словарей: https://github.com/salmonx/dictionaries
sql
1
9

20.

Инструментация
int some_func(char* data, size_t size) {
if (size < 4)
return 0;
if (data[0] == ‘F’)
if (data[1] == ‘U’)
if (data[2] == ‘Z’)
if (data[3] == ‘Z’)
return data[5];
return 0;
}
2
0

21.

Граф потока управления (CFG)
size < 4
int some_func(char* data,
size_t size) {
data[0] == ‘F’
if (size < 4)
return 0;
if (data[0] == ‘F’)
data[1] == ‘U’
if (data[1] == ‘U’)
if (data[2] == ‘Z’)
return 0;
if (data[3] == ‘Z’)
data[2] == ‘Z’
return data[5];
return 0;
}
data[3] == ‘Z’
return data[5]
2
1

22.

Маркировка блоков
int some_func(char* data, size_t size) {
if (size < 4)
return 0;
if (data[0] == ‘F’)
mark_block;
if (data[1] == ‘U’)
mark_block;
if (data[2] == ‘Z’)
mark_block;
if (data[3] == ‘Z’)
mark_block;
return data[5];
return 0;
}
2
2

23.

Этапы компиляции
Код на C/C++
Код на C/C++
после
макроподстанов
ок
clang –E fuzzy.c
Ассемблер
clang –S fuzzy.c
Объектные
файлы
clang –c fuzzy.c
Препроцессор
Бинарный
файл
clang –o fuzzu fuzzy.o
Линковщик
Компилятор
2
3

24.

Этапы компиляции
Код на C/C++
Код на C/C++
после
макроподстанов
ок
clang –E fuzzy.c
Код размечен на базовые блоки
Добавляем свои инструкции перед
каждой меткой
Ассемблер
clang –S fuzzy.c
Объектные
файлы
clang –c fuzzy.c
Препроцессор
Бинарный
файл
clang –o fuzzu fuzzy.o
Линковщик
Компилятор
2
4

25.

Этапы фаззинга
Инициализация
2
5

26.

Стратегии создания входных
данных
• Генерация
• Мутация
2
6

27.

Как работают мутации?
int some_func(char* data, size_t size) {
if (size < 4)
return 0;
if (data[0] == ‘F’)
if (data[1] == ‘U’)
if (data[2] == ‘Z’)
if (data[3] == ‘Z’)
return data[5];
return 0;
}
2
7

28.

AAA
mark_block
size < 4
mark_block
data[0] == ‘F’
mark_block
data[1] == ‘U’
mark_block
return 0;
mark_block
data[2] == ‘Z’
mark_block
return data[5]
mark_block
data[3] == ‘Z’

29.

AAAA
mark_block
size < 4
mark_block
data[0] == ‘F’
mark_block
data[1] == ‘U’
mark_block
return 0;
mark_block
data[2] == ‘Z’
mark_block
return data[5]
mark_block
data[3] == ‘Z’

30.

FAAA
mark_block
size < 4
mark_block
data[0] == ‘F’
mark_block
data[1] == ‘U’
mark_block
return 0;
mark_block
data[2] == ‘Z’
mark_block
return data[5]
mark_block
data[3] == ‘Z’

31.

FUAA
mark_block
size < 4
mark_block
data[0] == ‘F’
mark_block
data[1] == ‘U’
mark_block
return 0;
mark_block
data[2] == ‘Z’
mark_block
return data[5]
mark_block
data[3] == ‘Z’

32.

FUZA
mark_block
size < 4
mark_block
data[0] == ‘F’
mark_block
data[1] == ‘U’
mark_block
return 0;
mark_block
data[2] == ‘Z’
mark_block
return data[5]
mark_block
data[3] == ‘Z’

33.

FUZZ
mark_block
size < 4
mark_block
data[0] == ‘F’
mark_block
data[1] == ‘U’
mark_block
return 0;
mark_block
data[2] == ‘Z’
mark_block
return data[5]
mark_block
data[3] == ‘Z’

34.

FUZZ
mark_block
size < 4
mark_block
data[0] == ‘F’
mark_block
data[1] == ‘U’
mark_block
return 0;
mark_block
data[2] == ‘Z’
mark_block
return data[5]
mark_block
data[3] == ‘Z’

35.

Стандартные мутации
• bit flip AAAA → FAAA
• known integer 0x15037F0002010A -> 0x15037F00020164 [Int100=0x64]
• arithmetic operations 0x12037F0002200A -> 0x15037F0002200A [Arith+3]
• test case splicing t1: AAA t2: BBBB → AABBBB
• erase bytes AAAA → AA
• dictionary mutations
• И другие…
3
5

36.

int some_func(char* data, size_t size) {
if (size < 4)
return 0;
mark_block
mark_block
if (data[0] == ‘F’)
if (data[1] == ‘U’)
data[0] == ‘B’
data[0] == ‘F’
if (data[2] == ‘Z’)
if (data[3] == ‘Z’)
return data[5];
return 0;
}
int some_other_func(char* data, size_t size) {
if (size < 4)
data[1] == ‘U’
return 0;
if (data[0] == ‘B’)
if (data[1] == ‘U’)
if (data[2] == ‘Z’)
if (data[3] == ‘Z’)
return 1;
return 0;
}
mark_block

37.

Этапы фаззинга
Инициализация
3
7

38.

AFL
3
8

39.

Этапы фаззинга
Инициализация
3
9

40.

shared_mem[c1 ^ prev_location]++;
prev_location = c1;
00
00
00
00
00
00
2a
00
00
00
00
00
05
39
00
17
1e
00
00
00
00
00
00
00
00
00
00
00
1c
57
MEM_SIZE = (1 << 16)
A→B→C→D→E===AB BC CD DE
A→B→D→C→E===AB BD DC CE

41.

shared_mem[c1 ^ prev_location]++;
prev_location = c1;
01
00
00
00
00
00
2a
00
00
00
00
00
05
39
00
17
1e
00
00
00
00
00
00
00
00
00
00
00
1c
57
MEM_SIZE = (1 << 16)
A→B→C→D→E===AB BC CD DE
A→B→D→C→E===AB BD DC CE

42.

shared_mem[c1 ^ prev_location]++;
prev_location = c1;
x < 10
x++

43.

shared_mem[c1 ^ prev_location]++;
prev_location = c1;
x < 10
x++

44.

shared_mem[c1 ^ prev_location]++;
prev_location = c1 >> 1;
00
00
00
00
00
00
2a
00
00
00
00
00
05
39
00
17
1e
00
00
00
00
00
00
00
00
00
00
00
1c
57
MEM_SIZE = (1 << 16)
A→B→C→D→E===AB BC CD DE
A→B→D→C→E===AB BD DC CE

45.

shared_mem[c1 ^ prev_location]++;
prev_location = c1 >> 1;
01
00
00
00
00
00
2a
00
00
00
00
00
05
39
00
17
1e
00
00
00
00
00
00
00
00
00
00
00
1c
57
MEM_SIZE = (1 << 16)
A→B→C→D→E===AB BC CD DE
A→B→D→C→E===AB BD DC CE

46.

Этапы фаззинга
Инициализация
4
6

47.

FUZZ
int some_func(char* data, size_t size) {
if (size < 4)
return 0;
if (data[0] == ‘F’)
if (data[1] == ‘U’)
if (data[2] == ‘Z’)
if (data[3] == ‘Z’)
return data[5];
return 0;
}
4
7

48.

FUZZ
int some_func(char* data, size_t size) {
if (size < 4)
return 0;
if (strncmp(data, “FUZZ”, 4) == 0)
return data[5];
return 0;
}
4
8

49.

FUZZ
int some_func(char* data, size_t size) {
if (size < 4)
return 0;
if (strncmp(data, “FUZZ”, 4) == 0)
return data[5];
return 0;
}
char *strncmp(const char* str1, const char* str2, size_t n) {
add_to_dict(str2);
return origin_strncmp(str1, str2, n);
}
4
9

50.

Санитайзеры
int main(int argc, char* argv[]) {
int fd;
char* buffer;
int flags = O_WRONLY|O_APPEND|O_CREAT;
if ((fd = open(”data.log”, flags, 0666)) == 0)
exit(1);
buffer = malloc(u32size + 1);
read(0, buffer, u32size);
write(fd, buffer, u32size);
return 0;
}
5
0

51.

UBSAN – Undefined Behavior
Sanitizer
int main(int argc, char* argv[]) {
int fd;
char* buffer;
int flags = O_WRONLY|O_APPEND|O_CREAT;
if ((fd = open(”data.log”, flags, 0666)) == 0)
exit(1);
check_int_overflow(u32size, 1); // UBSAN
buffer = malloc(u32size + 1);
read(0, buffer, u32size);
write(fd, buffer, u32size);
return 0;
}
5
1

52.

ASAN – Address Sanitizer
int main(int argc, char* argv[]) {
int fd;
char* buffer;
int flags = O_WRONLY|O_APPEND|O_CREAT;
if ((fd = open(”data.log”, flags, 0666)) == 0)
exit(1);
buffer = malloc(u32size + 1);
read(0, buffer, u32size);
write(fd, buffer, u32size);
return 0;
}
5
2

53.

ASAN – Address Sanitizer
53

54.

ASAN – Address Sanitizer
54

55.

А что еще есть?
• Фаззинг структурированных данных и фаззинг на основе
грамматик
• Фаззинг сетевых приложений
• Фаззинг ядра
• Как параллелить фаззинг?
• Дедупликация обнаруженных падений
• Сбор покрытия в программе с тредами
• И многое другое…
5
5

56.

Фаззить – легко, когда знаешь
код
5
6

57.

sqlite
5
7

58.

sqlite
5
8

59.

OpenSSL Heartbleed
5
9

60.

OpenSSL Heartbleed
6
0

61.

OpenSSL Heartbleed
6
1

62.

А как фаззить?
• Обертка – точка входа в тестируемую программу
6
2

63.

А как фаззить?
Подробнее: https://github.com/mykter/afl-training
6
3

64.

SDLC
6
4

65.

Цена фикса
6
5

66.

Метод динозавров
• После выхода новой версии или на этапе последних RC
• Доработка оберток, работа с обновлениями и
исправлениями
• Регрессионное тестирование
• Запуск фаззинга в ручном режиме
• Сбор покрытия и анализ результатов
6
6

67.

Недостатки
• Информация об ошибке поступает поздно
• Ошибка может оказаться сложной и повлиять много на что
• Подготовка новых оберток, адаптация старых – долгий
процесс
• Ручной запуск
6
7

68.

AutoFuzz
6
8

69.

AutoFuzz
6
9

70.

Jobs
70

71.

Jobs
71

72.

Jobs
72

73.

Интерфейс. Активные задачи
73

74.

Интерфейс. Активные задачи
74

75.

Интерфейс. Активные задачи
75

76.

Интерфейс. Статистика
76

77.

Интерфейс. Уникальные крэши
77

78.

Интерфейс. Отчет об обнаруженной
ошибке (Casr-report)
78

79.

Интерфейс. Создание задач
79

80.

Как попасть в AutoFuzz?
• Шаг 0 – научиться собирать проект с инструментацией AFL
и санитайзерами (хотя бы ASAN)
• Шаг 0.5 – подготовить обертки для своего проекта (хотя бы
одну!) и убедиться, что они работают и собираются в
составе проекта с инструментацией AFL и санитайзерами
(хотя бы ASAN)
• Шаг 1 – связаться с нами, мы проверим, что все работает
корректно и добавим неблокирующую джобу в ваш проект, а
также занесем это на платформу, все покажем и расскажем
8
0

81.

Полезные ссылки
• Хорошая инструкция по использованию AFL с реальными
примерами: https://github.com/mykter/afl-training
• Верхнеуровневое описание платформы:
https://life.astralinux.ru/pages/viewpage.action?pageId=226236
635
• Еще инструкция:
8
1

82.

Планы
• Пилотирование внедрения фаззинга в проекты команд
разработки
• Добавление других фаззеров (в том числе для других ЯП)
• Добавление дополнительных санитайзеров
• Мониторинг самой системы (Prometheus + Grafana)
• Подготовка инструкций по внедрению, обновлениеи публикация
документации
• Автоматизированное развертывание тестовой среды для
тестирования новых оберток и более детального анализа предыдущих
запусков
8
2

83.

Контакты
Команда AutoFuzz
Егор @esuraev
Алексей @apanov
8
3

84.

Контакты
Команда AutoFuzz
Егор @esuraev
Алексей @apanov
Спасибо за внимание!
8
4
English     Русский Rules