Посмотрим на конкретном примере, как работает взлом программы через так называемое "переполнение буфера".
Возьмём простейшую программу на Си, которая запрашивает у пользователя пароль и выполняет те или иные действия в зависимости от того, правильный ли пароль был введён:
Компилируем и проверяем, что программа работает корректно:
Итак, наш crackme выдаёт сообщение "Access allowed" только в случае, если был указан суперсекретный пароль Qwerty123. Но что будет, если введённая строка окажется слишком длинной?
Вот те раз! Программа вылетела с ошибкой "stack smashing detected". А что самое интересное, сравнение происходило не со строкой Qwerty123, а с чередой единиц.
Дело в том, что scanf() записывает в память введённую строку целиком. Если буфер под неё окажется короче самой строки, будут переписаны соседние ячейки памяти. Этот эффект и называется "переполнением буфера".
Опытным путём установим минимальное количество символов, которое нужно ввести для получения непредсказуемого поведения. Им окажется степень двойки, 32 символа. Падения при этом уже не происходит:
Теперь заменим первый символ нашей строки на символ с кодом x00:
Что же мы видим? Не зная пароля, мы добились от crackme сообщения о разрешении доступа. Поздравляю, мы взломали программу!
Подобрать нужную для взлома длину строки — это быстрее, чем подобрать сам пароль или найти его дизассемблированием. К тому же эта атака продолжит работать, даже если пароль будет изменён.
Меры противодействия
Как же бороться с мамкиным хакером, чтобы он не смог так просто взломать нашу программу? К счастью, достаточно заменить "%s" на "%20s" в параметрах scanf. Это наложит ограничение (20 символов в нашем случае) на длину вводимого буфера. Компилируем исправленную программу и проверяем эксплойт:
Теперь доступ запрещён, как и должно быть. Кроме того, исправленная программа не будет падать с ошибкой при получении слишком длинных строк.
Это простой пример взлома, и защита от него тоже выглядит элементарно. Однако настоящие программы на несколько порядков сложнее, равно как и способы их взломать. Поэтому так важно проводить аудит кода на безопасность и как можно быстрее выпускать патчи для найденных уязвимостей.
Темы: #программирование #взлом #безопасность
Есть вопросы или дополнения к статье? Напишите их в комментариях!