
- •Активный сниффинг
- •Методы шифрования
- •Описание атаки Man In The Middle
- •Атаки на пароли
- •Дополнительные материалы
- •Сегментация памяти программы
- •Переполнение буфера
- •Переполнение в стеке
- •Практическая работа.
- •Доп. Задания и отчётность
- •Дополнительные материалы
- •1.3 Признаки заражения
- •1.4. Антивирусные программы (служебные программы)
- •Краткие теоретические сведения. Система разграничения доступа в Windows. Теоретические сведения
- •Учетные записи пользователей
- •Группы пользователей
- •Управление учетными записями, группами и их правами
- •Порядок выполнения работы.
- •8. Рекомендуемая литература
- •8.1. Основная
- •8.2. Дополнительная
- •9. Технические и программные средства
- •Компьютеры.
- •Презентации.
- •Компьютерный вариант умк. Приложение 1.
- •Брянский институт управления и бизнеса
- •Приложение 2.
- •Раздел 1. Концепция информационной безопасности.
- •Раздел 2. Угрозы информации.
- •Раздел 3. Виды возможных нарушений информационной системы.
- •Кодификатор Генерального Секретариата .
- •Раздел 4. Информационная безопасность информационных систем.
- •4. Перестановки;
- •Раздел 5. Методы и средства защиты компьютерной информации.
Переполнение буфера
Язык Си даёт программисту большие возможности для контроля над программой, но то же обстоятельство может привести к появлению программ, подверженных переполнению буфера или утечкам памяти, если программист будет недостаточно внимателен. Имеется в виду, что если переменной выделена память, то никакие встроенные механизмы защиты не будут обеспечивать соответствие размеров помещаемых в переменную данных и отведённого для неё пространства памяти. Если возложить ответственность за целостность данных на компилятор, то в результате будут получаться исполняемые файлы, которые станут работать значительно медленнее из-за проверок целостности, осуществляемых для каждой переменной. Если программист захочет записать десять байт данных в буфер, которому выделено только восемь байт памяти, ничто не запретит ему это сделать, даже если в результате почти наверняка последует крах программы. Такое действие называют переполнением буфера, поскольку два лишних байта переполнят буфер и разместятся за концом отведённой памяти, разрушив то, что находилось дальше. Если будет изменён важный участок данных, это вызовет крах программы. Соответствующий пример даёт следующий код.
void overflow_func(char *str)
{
char buf[20];
strcpy(buf, str); // Функция, копирующая str в buf
}
int main()
{
char big_string[128];
int i;
for(i=0; i < 128; i++) // Повторить цикл 128 раз
{
big_string[i] = 'A'; // Заполнить big_string символами 'A'
}
overflow_func(big_string);
return 0;
}
Функция overflow_func попытается втиснуть 128 байт данных в буфер, которому выделено всего 20 байт. Оставшиеся 108 байт данных просто покроют всё, что находится в памяти за буфером.
$ gcc -o overflow overflow.c
$ ./overflow
Segmentation fault
$
Программа аварийно завершилась в результате переполнения. программист часто встречается с такими ошибками, которые легко исправить, если только известно, какой длины будут входные данные. Часто программист рассчитывает, что вводимые пользователем данные всегда будут иметь определённую длину, и основывает на этом свои действия. Но поиск уязвимостей в том и заклдючается, чтобы представить себе ситуацию, на которую не рассчитывали, и тогда программа, прекрасно работавшая годами, может внезапно рухнуть, если кто-нибудь решит ввести тысячу символов в поле, которое обычно принимает несколько десятков символов, например имя пользователя. Итак, можно вызвать крах программы, введя неожиданные значения, которые вызовут переполнение буфера, но можно ещё и получить контроль над программой. Для этого нужно разобраться, какие именно данные оказываются затёртыми.
Переполнение в стеке
В рассмотренном примере при вызове функции overflow_func() в стек помещается кадр стека. При первом вызове функции кадр стека может выглядеть примерно так:
buf |
указатель кадра стека (sfp) |
адрес возврата (ret) |
*str (аргумент функции) |
остальной стек |
Однако когда функция пытается записать 128 байт данных в buf длиной 20 байт, лишние 108 байт запишутся за пределы буфера, затирая указатель кадра стека, адрес возврата и аргумент функции указатель str. Затем, когда функция завершает свою работу, порграмма пытается перейти по адресу возврата, который теперь заполнен буквами "А" (0х41 в шестнадцатеричном виде). Программа пытается выполнить возврат по этому адресу, заставляя EIP перейти на 0x41414141 некоторый случайный адрес, который либо относится к недопустимому пространству памяти, либо содержит недопустимые команды, что приводит к аварийному завершению программы. Это называется переполнением в стеке, потому что оно происходит в стековом сегменте памяти.
Переполнения могут происходить и в других сегментах памяти (об этом позже), но переполнения в стеке более разнообразны и интересны, поскольку могут изменять адрес возврата. Аварийное завершение программы при переполнении в стеке не столь интересно, как причина, по которой оно происходит. Если адрес возврата можно было бы контролировать и записать в него какой-нибудь адрес, где находится реально исполняемый код, то тогда программа "вернулась" бы и выполнила этот код, а не завершилась аварийно. А если данные, переписывающие адрес возврата, зависят от данных, введённых пользователем, например от текста в поле для ввода имени пользователя, то он сможет управлять адресом возврата и последующим выполнением программы.
Если можно модифицировать адрес возврата и изменить порядок выполнения путём переполнения буфера, то всё, что требуется, это какой-нибудь полезный код, который хотелось бы выполнить. Здесь мы сталкиваемся с инжекцией байт-кода. Байт-код это искусно написанный на ассемблере код, являющийся законченной программой, которую можно вредить в буфер. На байт-код накладываются некоторые ограничения: он должен быть законченной программой и в нём не должно быть некоторых специальных символов, потому что он должен иметь вид обычных данных, помещаемых в буфер.
Самый распространённый пример байт-кода это шеллкод. Это код, который запускает оболочку. Если suid-программу (Set UID — программа, у которой установлен этот бит, выполняется с правами хозяина файла программы. Имеет смысл только при установке на исполняемые файлы) с правами root удастся заставить выполнить шеллкод, то атакующий получит пользовательскую оболочку с правами root, при этом система будет считать, что suid-программа продолжает делать то, что ей положено.