Similar presentations:
Введение в фаззинг
1.
Введениев фаззинг
Виктория Егорова
Заместитель директора
Департамента анализа безопасности
1
2.
SDLC2
3.
SDLC3
4.
SDLC4
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.
1112.
12
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
Больше готовых словарей: 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.
AAAmark_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.
AAAAmark_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.
FAAAmark_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.
FUAAmark_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.
FUZAmark_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.
FUZZmark_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.
FUZZmark_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.
AFL3
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.
FUZZint 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.
FUZZint 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.
FUZZint 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 BehaviorSanitizer
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 Sanitizerint 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 Sanitizer53
54.
ASAN – Address Sanitizer54
55.
А что еще есть?• Фаззинг структурированных данных и фаззинг на основе
грамматик
• Фаззинг сетевых приложений
• Фаззинг ядра
• Как параллелить фаззинг?
• Дедупликация обнаруженных падений
• Сбор покрытия в программе с тредами
• И многое другое…
5
5
56.
Фаззить – легко, когда знаешькод
5
6
57.
sqlite5
7
58.
sqlite5
8
59.
OpenSSL Heartbleed5
9
60.
OpenSSL Heartbleed6
0
61.
OpenSSL Heartbleed6
1
62.
А как фаззить?• Обертка – точка входа в тестируемую программу
6
2
63.
А как фаззить?Подробнее: https://github.com/mykter/afl-training
6
3
64.
SDLC6
4
65.
Цена фикса6
5
66.
Метод динозавров• После выхода новой версии или на этапе последних RC
• Доработка оберток, работа с обновлениями и
исправлениями
• Регрессионное тестирование
• Запуск фаззинга в ручном режиме
• Сбор покрытия и анализ результатов
6
6
67.
Недостатки• Информация об ошибке поступает поздно
• Ошибка может оказаться сложной и повлиять много на что
• Подготовка новых оберток, адаптация старых – долгий
процесс
• Ручной запуск
6
7
68.
AutoFuzz6
8
69.
AutoFuzz6
9
70.
Jobs70
71.
Jobs71
72.
Jobs72
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