Математическая морфология.

Электронный математический и медико-биологический журнал. - Т. 7. -

Вып. 4. - 2008. - URL:

http://www.smolensk.ru/user/sgma/MMORPH/TITL.HTМ

http://www.smolensk.ru/user/sgma/MMORPH/N-20-html/TITL-20.htm

http://www.smolensk.ru/user/sgma/MMORPH/N-20-html/cont.htm

 

 

УДК 004.056

 

БЕЗОПАСНОЕ ПРОГРАММИРОВАНИЕ В API WIN32

 

Ó 2008 г. Малашенкова И. В., Панкратова Е. А., Семенова О. В.

 

(malashenkova-1.doc)

 

В статье содержится обзор функций Win 32 API,  некорректное использование которых приводит к ошибкам и делает возможным проведение сетевых атак. Небезопасные функции  сгруппированы по видам уязвимостей, к которым приводит некорректное использование функций,  и предложены методы создания защищенного программного кода.

Ключевые слова: функции Win32 API, сетевые атаки, троянские программы.

 

В библиотеках различных языков программирования и в API операционных систем имеется ряд функций, некорректное использование которых приводит к ошибкам и делает возможным проведение сетевых атак. Разработчикам программного обеспечения для написания безопасного кода необходимо хорошо представлять, к каким последствиям может привести использование той или иной «небезопасной» функции.

«Небезопасные» функции условно разбиваются на следующие группы:

1)   функции, некорректно, работающие с буферами памяти и указателями;

2)   функции, ненадежные по отношению к манипулированию именами;

3)   функции, позволяющие запускать процессы и выполнять DLL на удаленных компьютерах;

4)   функции передачи оконных сообщений;

5)   API-функции олицетворения;

6)   функции, требующие монопольного доступа к ресурсам;

7)   сетевые API-функции;

8)   функции для работы с файлами, наследующие ACL по умолчанию.

Описание функций первой группы приведено в таблице 1 [1].

 

Таблица 1  

Функции, некорректно, работающие с буферами памяти и указателями

Функции

Назначение

Уязвимости

strcpy, lstrcpy и аналогичные функции Delphi, объявленные в модуле SysUtils

Копирование строки в буфер

Функции не проверяют размер буфера-приемника и значение указателей, не отметают указателей на nil (null) или с другими некорректными значениями. Если буфер-источник не завершается нулем, результат такой функции непредсказуем.

 

strcat, lstrcat,  и т.п.

Добавление одной строки к другой

Те же  недостатки, что и в предыдущем случае. Этим функциям необходимо, чтобы буферы — источник и приемник — завершались нулем.

strlen, lstrlen, и т.п.

Данные функции возвращают длину строки в байтах (ANSI версия) или в символах (UNICODE версия)

Данные функции в состоянии корректно об­работать буфер только при условии, что он завершается нулем. Их вызов не при­водит к «эксплуатируемому» переполнению буфера, но способен вылиться в ошибку нарушения доступа, если функция попытается прочитать память, расположенную за пределами буфера.

 

strcmp,  lstrcmp  и т.п.

Выполняет сравнение двух строк

Сравниваемые строки должны заканчиваться двоичным нулем. Функция не проверяет корректность значения указателей.

 

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

Поэтому при разработке программного обеспечения следует:

·      проверять корректность указателей на строки;

·      размер строки ( данный размер не должен проверять размер буфера);

·      наличие завершающего строку двоичного нуля.

Описание функций второй группы приведено в таблице 2 [2].

 

Таблица 2

Функции, ненадежные по отношению к манипулированию именами

Функция

Описание

CreateDirectory

Создание новой папки

CreateEvent

Создание объекта «Событие». Если объект с указанным именем уже существует,  то функция выполняет открытие существующего объекта

CreateFile

Создание или открытие файла

CreateFileMapping

Создание или открытие файла, проецируемого в память

CreateJobObject

Создание или открытие объекта ядра «Задание»

CreateMailslot

Создание или открытие почтового ящика Windows

CreateMutex

Создание или открытие объекта ядра «Mutex»

CreateNamedPipe

Создание или открытие именованного канала

CreateSemaphore

Создание или открытие объекта ядра «Семафор»

CreateWaitableTimer

Создание или открытие объекта ядра «Ожидаемый таймер»

К данной группе относятся также классы, инкапсулирующие эти фун­кции.

Любой вызов API-функции, в ходе которого создается нечто, имеющее имя, подвержен атакам с манипулированием именами (name-squatting), так как  взломщик в состоянии угадать, какой файл или иной объект будет создан, и заблаговременно создать и «подсунуть» свой с таким же именем.

Например, если во время редактирования текстовый процессор создает файл в папке c:\temp с именем, которое легко предугадать, взломщик может заранее со­здать такой файл с разрешениями на чтение и затем манипулировать моим фай­лом.

Возможна и другая атака, которая состоит в том, что взломщик создает ссылку на файл, на запись которого у него нет прав, и заставляет администратора уда­лить файл или, того хуже, изменить разрешения.

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

·      Предоставить каждому пользователю его «личное» временное пространство, в Microsoft Windows 2000 и более поздних это папка Documents and Settings. Если нужно создавать временные файлы или каталоги в общедоступ­ной области, лучше всего генерировать действительно случайные имена;

·      При создании файлов установить флаг CREATE_NEW, который заставит функцию завершиться с ошиб­кой, если файл уже существует.

·      Никогда не следует предполагать, что файл или каталог не существуют, даже если проверили его отсутствие. Взломщик может воспользоваться временем между про­веркой существования и созданием файла. Несмотря на то, что временной промежуток слишком мал, множество успешных разрушающих атак были проведены на UNIX-системы в условиях конкуренции за ресурсы, и имеется несколько свидетельств об успеш­ных нападениях такого типа на Windows.

Функции третьей группы (функции, позволяющие запускать процессы и выполнять DLL на удаленных компьютерах) уязвимы для «Троянских программ», то есть при некорректном использовании данных функций становится возможным загрузка и исполнение приложением «постороннего» кода. Описание  функций  третьей  группы приведено в таблице 3 [2].

 

Таблица 3

Функции, позволяющие запускать процессы и выполнять DLL на удаленных компьютерах

Функции

Назначение

Уязвимости

CreateProcess (NULL,...)

Создание процесса

В данных функциях один из аргументов — путь к приложению, второй — командная строка. Если путь к приложению указать как nil (null), а в командной строке содержится пробел в пути к приложению, возможно выполне­ние «не того» приложения. Например, если аргумент С:\Program Files\MyApp\MуАрр.ехе, то при наличии соответствующего файла выполнится программа C:\Progrат.ехе.

CreateProcessAsUser

Создание процесса в контексте указанного пользователя

WinExec

Запуск внешней программы

Данная функции ведет себя так же, как CreateProcess(NULL,   ). Кроме того, функция WinExec  позволяет указывать путь к файлу длиной не более 80 символов

ShellExecute

Запуск внешней программы и открытие документа

Данная функции ведет себя так же, как CreateProcess(NULL,   ).

LoadLibrary

Загрузка DLL в адресное пространство процесса

Во многих версиях Windows при загрузке файлов поиск начинается с текущего каталога. Если попытаться загру­зить DLL, указав неполный путь (например file.dll вместо c:\dir\dir\ftle.dll), програм­ма сначала просмотрит текущий каталог, и если там окажется подложный файл, то загрузится именно он. В Windows XP SP1 и Windows .NET Server 2003 подобной проблемы не возни­кает, поиск в них выполняется по-другому - вначале просматриваются системные каталоги и только затем текущий

LoadLibraryEx

Загрузка DLL в адресное пространство процесса

SearchPath

Поиск файла

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

·      При использовании функций CreateProcess (NULL,...), CreateProcessAsUser, WinExec, ShellExecute  всегда указать путь к приложению в первом аргументе;

·      При  использовании функции WinExec проверять длину пути, чтобы она не превышала 80 символов;

·      При использовании функций LoadLibrary, LoadLibraryEx и SearchPath   всегда указывать пол­ный путь.

Функции четвертой группы (функции передачи оконных сообщений)  SendMessage и  PostMessage  являются одними из наиболее часто используемых функций ОС Windows [2]. Для передачи сообщения необходимо знать только дескриптор окна получателя. Но некоторые  стили окна и типы элементов управления представляются опасность с точки зрения безопасности: 

·      Сообщения ТВ_GETBUTTONTEXT, LVM_GETISEARCHSTRING и TVM_GETISEARCHSTRING копируют данные из элемента управления в буфер, следовательно, необходимо про­верять, что IParam установлен в nil, чтобы сначала получить размер буфера.

·      TTM_GETTEXT не существует способа ограничить размер буфера; предполага­ется, что размер источника не превышает 80 символов.

·      СЕ_GETLBTEXT, CB_GETLBTEXTLEN, SB_GETTEXT, SB_GETTEXTLENGTH, SB_GETTIPTEXT, LB_GETTEXT и LB_GETTEXTLEN в общем случае следует прежде все­го отправлять сообщение GETTEXTLENGTH, чтобы узнать размер входной строки. Однако это не всегда избавляет от ошибок: размер данных может изме­ниться в промежутке между определением размера и приемом текста, в результа­те чего возникнет переполнение. Кроме того, пока не существует способа запросить длину текста всплывающей подсказки (ToolTip) строки состояния при посредстве сообщения SB_GETTIPTEXT.

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

Функции пятой группы (API-функции олицетворения) описаны в таблице 4 [3].

Олицетворение (impersonation) – мощное средство, часто используемое в модели защиты Windows 2000.  Олицетворение также применяется в модели программирования клиент-сервер. Например, серверное приложение может экспортировать ресурсы (файлы,  принтеры или базы данных). Клиенты, которые хотят обратиться к этим ресурсам посылают серверу запрос. Получив запрос, сервер должен убедиться, что у клиента есть разрешение на выполнение над ресурсом запрошенных операций.  Windows 2000 в таких случаях предоставляет серверу сервисы олицетворения.  Олицетворение позволяет серверу временно заимствовать  профиль защиты клиента, запрашивающего ресурс. После этого сервер может обращаться к ресурсам от имени клиента. Обычно серверу доступен долее широкий круг ресурсов, чем клиенту и при олицетворении сервер может терять часть исходных прав доступа [3].

 

Таблица 4

API-функции олицетворения

Функция

Описание

RpcImpersonateClient

Вызов серверным потоком клиентской удаленной процедуры. Если сервер взаимодействует с клиентом через RPC, с помощью данной процедуры сервер выдает запрос на олицетворение.

ImpersonateLoggedOnUser

Вызов потока, имеющего другие атрибуты секретности, чем у вызывающего потока

ImpersonateNamedPipeClient

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

ImpersonateDdeClient

Если сервер взаимодействует с клиентом через DDE, с помощью данной процедуры сервер выдает запрос на олицетворение.

ImpersonateSecurityContext

С помощью данной функции пакет SSPI (Security Support Provider Interface) может олицетворять своих клиентов

ImpersonateSelf 

Поток создает маркер олицетворения просто как копию маркера своего процесса

SetThreadToken

Выполнение олицетворения для потока

SetSecurityDescriptorDacl(...,...,NULL,...)

Создание дескриптора защиты

При выполнении функций,  перечисленных в таблице 4 возможно появление следующих уязвимостей:

·      Если вызов функции олицетворения по каким-либо причинам терпит сбой, оли­цетворения не происходит и запрос выполняется в контексте безопасности вы­зывающего процесса. Таким образом, становится возможным превышение полно­мочий, если процесс работает в контексте высоко привилегированной учетной записи, например SYSTEM или члена группы администраторов. Поэтому очень важно всегда проверять возвращенное значение. Если вызов завершился неудач­но, немедленно следует прервать выполнение клиентского запроса.

·      SetSecurityDescriptorDacl(...,...,NULL,...)  не рекомендуется создавать дескрипторы защиты, имеющие нулевые (NULL) DACL, то есть, при создании ко­торых третий параметр (pDacl) равен NULL. Такая DACL никак не защищает объект. Более того, ничто не мешает взломщику определить АСЕ запись Full Control: Deny для группы Everyone, что запретит доступ к объекту всем, в том числе и админи­страторам.

Выполнение функций шестой группы (функции, требующие монопольного доступа к ресурсам)  может привести к возникновению условий для отказа в обслу­живании (DoS атака), особенно при недостатке памяти [2].

К таким функциям относятся:

·      InitializeCriticalSection (инициализация критической секции) и EnterCriticalSection (вход в критическую секцию), которые в условиях недостатка памяти инициируют исключения, и если исключение не перехватывается, приложение завершается аварийно. Взамен рекомендуется использовать функцию InitializeCriticalSectionAndSpinCount. Причем, EnterCriticalSection не инициирует исключения в Windows XP, Windows .NET Server и последующих ОС. Также необходимо следить, чтобы не выполнять блокирующих сетевых вызовов из критической секции или других блокируемых уча­стков программы. Код внутри критической секции следует проверять с особой тщательностью. Любые исключения должны перехватываться в самой критической секции, в противном случае программа «вывалится» в обработчик исключения до вызова LeaveCriticalSection. В критической секции надо выполнять лишь необходимый минимум операций.

·      TerminateThread (завершение потока) и TerminateProcess (завершение процесса) обе эти функции следует вызывать только в крайнем случае. Особенно TerminateThread. Память, дескрипторы и системные ресурсы, которыми владел поток, не очищаются и не освобождаются.

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

К таким функциям относятся следующие:

·      bind  (определение номера порта и IP-адреса по которому       сервер будет принимать данные)   создавая привязку к INADDR_ANY (все интерфейсы) — есть опасность, что сервер станет прослушивать все   имеющиеся сетевые интерфейсы;

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

·      send  -   отправляет данные в сокет, с которым установлено соединение. Не следу­ет считать, что все данные успешно переданы, если send не возвраща­ет ошибки. Соединения иногда разрываются между вызовами connect и send. Кро­ме того, если злоумышленник намеренно задал размер окна TCP очень малень­ким, существует лишь один путь заметить это — если при вызове send возникнет тайм-аут. Если  сокет является блокирующим или не проверяется значение, воз­вращаемое функцией, есть вероятность  проведения атаки  отказ в обслуживании.

К функции восьмой группы  относятся CopyFile и MoveFile. Возможные проблемы с этими функциям связаны с тем, как они работают с ACL. Файлы, копируемые вызовом CopyFile, наследуют ACL по умолчанию каталога, в который копируются, а файлы, переносимые посредством MoveFile, сохраняют свои ACL. При работе с данными функциями необходимо проверять, что объект используется только локально только локально и  н и в коем случае не  устанавливать флаг CLSCTX_REMOTE_SERVER.

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

 

Литература

 

1.    Ховард М., Лебланк Д.  Защищенный код. Пер. с англ. – 2-е  изд., испр. М.:  Издательско-торговый дом «русская редакция», 2004. – 704 стр.: ил.

2.    Рихтер Дж. Windows для профессионалов:  создание эффективных Win32-приложений с учетом специфики 64-разрядной версии Windows. ./ Пер. с англ. – 4-е изд. – СПб.: Питер; М.: Издательско-торговый дом «Русская редакция», 2004 – 749 с.:ил.

3.    Соломон Д., Руссинович М.  Внутреннее устройство Microsoft Windows 2000. Мастер-класс./ Пер. с англ.  – СПб.: Питер; М.: Издательско-торговый дом «Русская редакция», 2001 – 752 с.:ил.

 

 

SAFE PROGRAMMING USING API WIN32

 

Malashenkova I. V., Pankratova H. A., Semenova O. V.

 

The article contains a review of Win 32 API-functions, which’s incorrect usage leads to mistakes and makes successful network attacks possible. Unsafe functions has been grouped together by types of  brittleness, can be caused by incorrect usage of the functions, and techniques of  secured programming code’s creation are offered.

Key words: Win 32 API-functions, network attacks, Troyan Horses.

 

Филиал ГОУ ВПО «МЭИ (ТУ)» в г. Смоленске

Поступила в редакцию 8.12.2008.