Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Polnaya_metodichka

.pdf
Скачиваний:
27
Добавлен:
11.05.2015
Размер:
2.79 Mб
Скачать

Рисунок 2. Иллюстрация техники JMP ESP.

Если целевая операционная система (или атакуемое приложение) известна с точностью до версии, найти двухбайтовую последовательность не проблема. Не обязательно искать именно JMP ESP. FFh E4h вполне может быть и частью совсем другой команды - например, инструкции CALL DbgPrint с опкодом E8h FFh E4h FEh FFh 56h (см. рис. 2). На машинах с неисполняемым стеком/кучей последовательность FFh E4h необходимо искать только в кодовых секциях динамических библиотек или исполняемом файле атакуемого приложения. Если же защиты нет (или отключена), подойдет и область данных.

На системах с поддержкой ASLR данная техника не работает, поскольку невозможно заранее определить адрес искомой последовательности, однако если атакуемый исполняемый файл не содержит перемещаемых элементов (а чаще всего так и бывает) или же одна из его динамических библиотек имеет сброшенный бит рандомизации (состояние по умолчанию), шансы на успешную атаку многократно возрастают.

18. Защита от атак типа переполнение буфера.

Известны следующие методы защиты от атак по переполнению буфера:

-Корректировка исходных кодов программы для устранения уязвимостей. Переполнение буфера происходит прежде всего из-за неправильного алгоритма работы программы, который не предусматривает проверок выхода за границы буферов. Также особую роль здесь играет язык программирования Си и его стандартные библиотеки. Так как Си не содержит средств контроля соответствия типов, то в переменную одного типа можно занести значение другого типа. В результате чего, для программистов выработано ряд методик и указаний по написанию программ не содержащих уязвимости.

-Использование n-функций

Функции стандартной библиотеки C определяют конец строки по нулевому байту. Например функция strcpy()копирует содержимое исходной строки в строку назначения пока не встретит нулевой байт. В некоторых случаях такое поведение становится опасным;

#define LG_IDENT 128

int fonction (const char * name)

{

char identity [LG_IDENT]; strcpy (identity, name);

...

}

Функции, ограничивающие длину копирования, обходят эту проблему. Эти функции имеют букву `n' в середине их названий , например, strncpy() как замена для strcpy()

, strncat() для strcat() или даже strnlen() для strlen().Однако, вы должны быть осторожными с использованием ограничения функции strncpy(), так как оно порождает краевой эффект: когда исходная строка меньше строки назначения, копия будет дополнена нулевыми символами до n-ой позиции, что делает приложение медленнее. С другой стороны, если исходная строка длиннее, она будет урезана и копия поэтому не будет заканчиваться нулевым символом, поэтому вы должны добавить его вручную.

#define LG_IDENT 128

int fonction (const char * name)

{

char identity [LG_IDENT+1]; strncpy (identity, name, LG_IDENT); identity [LG_IDENT] = '\0';

...

}

-Использование безопасных строковых функций . Безопасные строковые функйии должны обладать :

-размер бефера-примника должен передоваться в фнкцию,чтобы она не выводила за его пределы;

-буферы гарантированы должны содержать запрещающий null,даже при усечении результата;

-все функции должны возвращать значение типа HRESULT с одним концом успешного завершения;

-каждая функция должна быть доступной в двух версиях: с поддержкой числа символов(cch) и байт(cb);

-у большинства функций должна быть расширенная (Ex-) версия, обладающая расширенной функциональномтью.

-Использование неисполнимых буферов. Суть метода заключается в запрещении исполнения кода в сегментах данных и стека, т.е. параметры сегментов данных и стека содержат только атрибуты записи и чтения, но не исполнения.

-Применение проверок выхода за границы. В основе данного метода лежит выполнение проверок выхода за границы переменной при каждом обращении к ней. Это предотвращает все возможные атаки по переполнению буфера, так как полностью исключает само переполнение. Однако, у этого решения есть существенный недостаток - значительное (до 30 раз) снижение производительности.

-Применение проверок целостности. Решение, основанное на данном методе, получено

благодаря проекту Synthetix. В рамках проекта реализован

набор

утилит,

таких

как StackGuard и PointGuard. StackGuard предназначен для

защиты

от

всех атак

по

переполнению буфера с изменением адреса возврата из

функции и реализован

в

виде

“заплаты” к gcc. Данная заплата изменяет пролог и эпилог всех функций с целью проверки целостности адреса возврата из функции при помощи так называемого "canary word".

Измененный пролог каждой функции выполняет занесение в стек “canary word”, а эпилог проверку содержимого стека, занесенного ранее и, в случае, нарушения останавливает программу с предупреждающим сообщением. При атаке с искажением адреса возврата неизбежно произойдет искажение “canary word”, что и будет признаком нарушения целостности. Таким образом, целостность адреса возврата определяется целостностью

“canary word” .Таким образом “canary word”.:

1.имеет 0, CR, LF, EOF, что не позволит произвести атаку типа переполнение буфера , так как данные значения являются признаками конца строки;

2.имеет псевдослучайные значения генерируемые при каждом запуске системы;

Определение переполнения буфера на основе стека (/GS)

Определение переполнения буфера на основе стека — это самый старый и хорошо известный способ защиты кода в Visual C++. Параметр компилятора /GS выполняет простую задачу: снижение вероятности корректного выполнения вредоносного кода. Параметр /GS по

умолчанию используется в Visual C++ начиная с версии 2003. Во время выполнения он позволяет обнаружить определенные сбои в работе стека. Для этого в стек функции перед адресом возврата добавляется определенное случайное значение(32-байтный canary word), а когда функция завершает работу, соответствующий код проверяет это значение, чтобы убедиться, что оно не изменилось. Если значение cookie, а оно называется именно так, было изменено, выполнение программы прерывается.

Код, выполняемый перед запуском функции и устанавливающий значение cookie выглядит следующим образом:

sub

esp, 8

mov

eax, DWORD PTR ___security_cookie

xor

eax, esp

mov

DWORD PTR __$ArrayPad$[esp+8], eax

mov

eax, DWORD PTR _input$[esp+4]

А ниже показан код, завершающий работу функции и проверяющий значение cookie:

mov ecx, DWORD PTR __$ArrayPad$[esp+12] add esp, 4

xor ecx, esp

call @__security_check_cookie@4 add esp, 8

Кроме того, Visual C++ 2005 перемещает данные внутри стека, чтобы их было сложнее повредить. Например, буферы могут переноситься в более высокие области памяти, чем не буферы. В частности, это позволяет защитить указатели на фукнции, находящиеся внутри стека. Кроме того, перемещение аргументов в виде указателей и буферов в нижнюю память может предотвратить различные атаки, связанные с переполнением буфера. Сравнение обычного стека со стеком /GS показано на рисунке.

Параметр компилятора /GS не применяется в следующих ситсуациях:

функции не содержат буфеов;

оптимизация отключена;

функции имеют переменный набор аргументов;

функции определены с использованием ключевого слова naked (C++);

первая инструкция функций содержит встроенный код ассемблера;

буфер имеет не восьмибайтовый тип, а его размер менее 4 байт.

-NX/XD-бит процессора, технология DEP от Microsoft.

NX - аббревиатура от Non-Executable. Бит неисполняемости процессора. Как известно, шеллкод внутри приложения имеет вполне определенное положение - это стек, куча или статическая память внутри секции данных приложения. Если запрещать выполнение кода внутри этих областей памяти (метим их NX-битом), то при попытке выполнить шелл-код в помеченных областях памяти получим исключение защиты.

Именно на основе NX/XD-бита и построена технология DEP от Microsoft, встроенная в операционные системы Windows XP SP2 и Windows 2003 SP1. Также технология DEP включает в себя контроль целостности стека и кучи на основе проверочных данных и контроль цепочки SEH.

1.Внутри исполняемых процессов все области данных метятся NX-битом, что запрещает исполнение кода в них. В случае попытки выполнить код в этих областях памяти вылетает исключение и приложение заканчивает свою работу. Если же процессор не поддерживает NX/XD-бит, то код можно выполнять в любой доступной области памяти процесса.

2.Контроль целостности стека представляет собой применение старой доброй технологии StackGuard, реализованной для Linux. При входе в функцию в стек запихивается некоторое проверочное число. При выходе из функции то число, которое лежит в стеке, сравнивается с эталонным. Если эти числа не совпадают, значит, было переполнение. В этом случае генерируется исключение защиты и приложение заканчивает свою работу. Эта возможность заложена в компиляторы Microsoft начиная с VC 2003 (директива компилятора /GS, включена для всех проектов по умолчанию).

С кучей происходит примерно та же вещь: в начало каждого блока кучи операционная система помещает проверочные данные. Если при выделении нового блока или при освобождении старого где-то внутри цепочки блоков проверочные данные не сошлись, генерируется исключение защиты. Это не свойство компилятора, как в предыдущем случае, а свойство операционной системы!

3. Контроль целостности цепочки SEH. SEH - это последовательность обработчиков исключений приложения. У каждого потока внутри приложения своя цепочка SEH! Если в потоке происходит исключение, то система последовательно вызывает все обработчики, ожидая, что хоть один из них справится с ним. Если же ни один из обработчиков исключений не смог обработать его, то вызывается обработчик исключений, общий для всех потоков (UnhandledExceptionFilter). Если же и он бессилен, то системе ничего другого не остается, как показать сообщение об ошибки и закрыть его. Так вот, возвращаясь к контролю. При наличии исключения в потоке система проверяет, не лежат ли адреса обработчиков исключений внутри кучи или стека. Если лежат, система генерирует исключение защиты.

19. Проверка входных данных приложения.

Большинство взломов защиты происходит от того, что приложение неправильно проверяте или вообще не проверяет входные данные. Если данные не проверять, то приложение становится уязвимым. Следует придерживаться 2м принципам:

1)Все входные данные зловредны пока не доказано противное

2)Проверку корректности данных следует выполнять при каждом пересечении ими границы между ненадежной и доверенными средами.

Не доверенными данными считаются данные, вводимые пользователем. Слишком многие разработчкик пренебрегают проверкой данных, вводимых пользователями, надеясь на функции, вызываемые в приложении. И не желают вводить доп проверки, дабы не увеличивать время работы программы.

Существует три основных способа обработки входных мусорных данных, перечисленных далее.

Проверяйте все данные из внешних источников

Получив данные из файла, от пользователя, из сети или любого другого внешнего интерфейса, удостоверьтесь, что все значения попадают в допустимый интервал. Проверьте, что числовые данные имеют разрешенные значения, а строки достаточно коротки чтобы их можно было обработать. Если строка должна содержать определенный набор значений (скажем, идентификатор финансовой транзакции или что-то подобное), проконтролируйте, что это значение допустимо в данном случае, если же нет – отклоните его. Если вы работаете над приложением, требующим соблюдения безопасности, будьте особенно осмотрительны с данными, которые могут атаковать вашу систему: попыткам переполнения буфера, внедренным SQL-командам, внедренному HTMLили XML-коду, переполнения целых чисел, данным передаваемым системным вызовам и т.п.

Проверяйте значение всех входных параметров метода

Проверка значений входных параметров метода практически тоже самое, что и проверка данных из внешнего источника, за исключением того, что все данные поступают из другого метода, а не из внешнего интерфейса.

Решите, как обрабатывать неправильные входные данные

Что делать, если вы обнаружили неверный параметр? В зависимости от ситуации вы можете выбрать один из дюжины подходов.

Существуют атаки, основанные на изменении входных данных. Для защиты от таких атак существует ряд методов:

1)создание границы вокруг приложения и преобразование его в доверенную зону

2)создание checkpoint-ов для входных данных

Есть точки в приложении, через которые проходят данные и проходят проверку. Ипосле прохождения этих точек данные считаются проверенными и попадают в доверенную зону. Сл-но далее их проверка излишня. С другой стороны, может произойти ошибка и данные могут быть некорректны. Тогда есть смысл проверять их на всех уровнях. Определять этот баланс приходится разработчику. В зависимости от создаваемой системы.

Также требуется проверка на границе доверенной зоны. Необходимо определить эту точку в проекте. Она должна быть единственной и никакие данные не могут пройти в эту зону без проверки на КПП. Организуя проверку входных данных следует руководствоваться только одним правилом: отбирать только корректные данные – остальные отбрасывать.

20.Атаки типа "Внедрение SQL-кода" (SQL-injection). Защита от атак типа "Внедрение SQL-кода" (SQL-injection).

SQL инъекция - способ нападения на базу данных в обход межсетевой защиты, в котором параметры, передаваемые к базе данных через Web-приложения, изменяются таким образом, чтобы изменить выполняемый SQL запрос.

Цели SQL инъекции:

1.Получить доступ к данным, которые обычно недоступны или получить данные конфигурации системы, которые могут использоваться для дальнейших нападений Пример: возвращение измененным запросом хешированных паролей пользователей, которые впоследствии могут быть расшифрованы.

2.Получить доступ к компьютерам организации, через компьютер, на котором хостится база данных. Это можно реализовать, используя процедуры базы данных и расширения языка SQL, которые позволяют доступ к операционной системе.

Для реализации атаки должен использоваться динамический SQL, так как в противном случае SQL инъекция невозможна.

Web приложения представляют наибольшую угрозу, поскольку любой пользователь с браузером и доступом к Интернет может потенциально обратиться к чувствительным данным. Однако любое приложение, позволяющее пользователю вводить данные, которые могут быть частью динамического SQL запроса, может быть потенциально уязвимо к нападениям SQL инъекции.

Примеры атаки внедрения SQL

1.Расщепление SQL-запроса. Добавляя символ ';' к параметру, можно выполнить дополнительный запрос совместно с первым.

2.Если в приложении есть код:

string sql = "select * from client where name = ' " + name + " ' ";

Пользователь может подставить в переменную паmе другое SQL-выражение. select * from client where name = 'Blake' or 1=1 --

Поскольку 1=1 истинно для всех строк в таблице, так что будут возвращены все

строки.

3.Использование UNION. Язык SQL позволяет объединять результаты нескольких запросов при помощи оператора UNION. Это предоставляет злоумышленнику возможность получить несанкционированный доступ ко всем таблицам БД в системе, доступ к которым иначе был бы невозможен.

В предложении UNION SELECT должно присутствовать такое же число столбцов, и все типы столбцов должны быть такого же типа, как и в исходном запросе, в противном

случае возникнет ошибка. Для подсчета количества столбцов злоумышленники пользуются оператором ORDER BY. Добавление условия ORDER BY в конец предложения.

С известным корректным синтаксисом, производителем СУБД и количеством столбцов в запросе, атакующий может определить типы всей полей.

Используется простая методика, основанная на использовании ключевого слова NULL, используемого в языке SQL. В отличии от внедрения статических полей, которые относятся к определенному типу (такому как строка или число), NULL может быть совместимым с любым типом. Это делает возможным внедрить предложение UNION SELECT с полями, имеющими значение NULL, и при этом не возникнет ошибки несоответствия типов. После того как основанное на NULL значениях предложение UNION работает, определение типа каждого столбца становится тривиальной задачей. В каждой итерации отдельное поле проверяется на соответствие его типу. Все три типа (число, строка, дата) проверяются на соответствие типу поля — одно из них должно подойти. Этот способ требует количества проверок не больше утроенного количества столбцов, вместо трех в степени количества столбцов проверок.

Пример UNION предложений для определения типа всех полей

UNION SELECT NULL,NULL,NULL,NULL WHERE 1=2 --Ошибка не возникает – выражение синтаксически правильное

UNION SELECT 1,NULL,NULL,NULL WHERE 1=2 -- Ошибка не возникает — первый столбец является числом.

UNION SELECT 1,2,NULL,NULL WHERE 1=2 -- Ошибка! — второй столбец не является числом.

UNION SELECT 1,'2',NULL,NULL WHERE 1=2 -- Ошибка не возникает — второй столбец является строкой.

UNION SELECT 1,'2',3,NULL WHERE 1=2 -- Ошибка! — третий столбец не является числом.

UNION SELECT 1,'2','3',NULL WHERE 1=2 -- Ошибка не возникает — третий столбец является строкой.

UNION SELECT 1,'2','3',4 WHERE 1=2 -- Ошибка не возникает — четвертый столбец является числом.

Теперь атакующий установил действительное, корректное UNION выражение. Используя увеличивающиеся номера полей атакующий, конечно, определит тип каждого поля. Теперь, когда все это завершено, можно использовать полученный эксплоит в целях атаки. Для осуществления этого, внедрение должно использоваться для получения данных из системных таблиц (например из тех, которые содержат список таблиц и их столбцов), затем для получения фактических данных приложения.

Если приложение вывод описание своих ошибок, это сильно облегчает задачу злоумышленника. По сообщения об ошибке он может восстановить структуру БД, тип и количество полей в каждой таблице. Например, имеется уязвимый скрипт, пропускающий внедрение кода.

http://server/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES –

Системная таблица INFORMATION_SCHEMA.TABLES содержит информацию о всех таблицах на сервере. Выполнение такого запроса приводит к ошибке:

Microsoft OLE DB Provider for ODBC Drivers error '80040e07'

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvar-char value 'table1' to a column of data type int. /index.asp, line 5

Соответственно, имя первой таблицы в БД – "table1".

Для получения следующего имени таблицы, может использоваться следующий запрос:

http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMAION_SCHEMA.TABLES WHERE TABLE_NAME NOT IN ('table1')—

После получения имен всех столбцом в таблице, злоумышленник может обновить (UPDATE) или даже вставить (INSERT) новую запись в таблицу. Например, можно изменить пароль для "admin":

http://duck/index.asp?id=10; UPDATE 'admin_login' SET 'password' = 'newpass' WHERE login_name='admin-

4.Использование LIKE. Данные об именах таблиц можно получить, используя ключ LIKE:

http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE '%25login%25'—

5.Инъекция через хранимые процедуры. Они могут использоваться для выполнения команд на сервере. Например, для MS SQL могут использоваться встроенные процедуры, типа master.xp_cmdshell, для удаленного выполнения произвольных команд:

'; exec master..xp_cmdshell 'ping 10.10.1.2' –

Точка с запятой закончит текущий SQL запрос и позволят запускать новые SQL команды. Примером еще одной уязвимой хранимой процедуры является sp_makewebtask, чтобы записать результат запроса в HTML:

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]