УДК 681.326
M. А. Егоров
МЕТОДИКА ОЦЕНКИ БЕЗОПАСНОСТИ ПРОГРАММНОГО КОДА КОРПОРАТИВНЫХ ПРИЛОЖЕНИЙ
Рассмотрен класс уязвимостей корпоративных приложений, которые связаны с небезопасным взаимодействием отдельных слоев приложения. Представлен формальный критерий наличия уязвимостей в приложении. Предложена методика оценки программного кода корпоративных приложений на наличие уязвимостей.
Email: [email protected]
Ключевые слова: информационная безопасность, уязвимость, SQL, база
данных
К корпоративным приложениям (Enterprise application) относят приложения, предназначенные для автоматизации бизнес-процессов и операций, которые составляют деятельность конкретной организации (например, приложения для автоматизации бухгалтерского и кадрового учета, ведения медицинских карт пациентов, анализа кредитной истории клиентов банка, страхования и пр.).
Для описания архитектуры применяют понятия слоя (Layer) и уровня (Tier). Слои определяют логическое разделение корпоративного приложения на отдельные части, по функциональному признаку. Уровни определяют физическое разделение корпоративного приложения на отдельные части в зависимости от размещения.
Сегодня наиболее распространенными платформами, применяемыми для разработки и внедрения корпоративных приложений, являются J2EE и .NET Framework. По данным аналитического агентства Gather Group, в 2005 г. доля корпоративных приложений, разработанных с применением указанных платформ, составила более 70 % и со временем данный показатель непрерывно растет. Наиболее популярными языками программирования высокого уровня, которые поддерживаются указанными платформами и используются для написания программного кода, являются Java, C#, VB.Net, ASP, ASP.Net и JSP.
Для приложений, написанных на языках низкого уровня, таких как С/С++, основные уязвимости — это переполнение буфера и дефекты в строках форматирования. Для программного обеспечения на языках высокого уровня практически не существует указанных проблем безопасности. Такие программы являются интерпретируемыми и исполняются средой выполнения (интерпретатором), которая автоматически управляет выделением (освобождением) памяти и запрещает прямой доступ к ней.
Для корпоративных приложений, написанных на языках программирования высокого уровня, характерны уязвимости, связанные с небезопасным взаимодействием отдельных слоев приложения.
Наиболее распространенными и опасными типами уязвимостей корпоративных приложений, которые связаны с небезопасным взаимодействием отдельных слоев приложения, являются:
1) SQL-инъекция;
2) межсайтовый скриптинг (Cross-Site Scripting, XSS);
3) SOAP-инъекция;
4) LDAP-инъекция;
5) XPath-инъекция;
6) обход директории (Path traversal).
Ведущая организация в области информационной безопасности SANS Institute составила сводный отчет о наиболее критичных уяз-вимостях программного обеспечения «2010 CWE/SANS Top 25 Most Dangerous Programming Errors». Уязвимости XSS и SQL-инъекции занимают две первые строки отчета и являются в настоящий момент наиболее критичными для корпоративных приложений.
Уязвимости корпоративных приложений. Рассмотрим основные типы уязвимостей корпоративных приложений, которые связаны с небезопасным взаимодействием отдельных слоев приложения (более подробная информация об уязвимостях дана в работах [1-5].
SQL-инъекция. Наличие этой уязвимости в корпоративном приложении связано с тем, что данные, полученные из ненадежного источника, не проверяются, и на их основе формируется динамический SQL-запрос (например, с использованием конкатенации строк), который затем передается СУБД на выполнение. В результате злоумышленник получает несанкционированный доступ к конфиденциальной информации, которая содержится в БД, а также к функциональным возможностям СУБД и в некоторых случаях доступ к операционной системе сервера, на котором функционирует СУБД.
В настоящее время существует большое количество техник эксплуатации SQL-инъекций для различных СУБД и приложений на их основе.
Основными техниками эксплуатации SQL-инъекций являются: Union SQL-инъекция, Error-based SQL-инъекция, Blind SQL-инъек-ция, Time-based SQL-инъекция, Out-bound SQL-инъекция. Первые две техники применяют, когда приложением осуществляется вывод возвращаемой информации из БД либо вывод сообщения о возникшем при работе с СУБД исключении. Техники Blind SQL-инъекция и Time-based SQL-инъекция используются злоумышленниками, если вывод информации из БД (сообщения об исключении) не осуществляется приложением, но можно влиять на логику работы приложения
или на время отклика сервера СУБД в результате модифиции входных данных. Техника Out-bound SQL-инъекции применяется злоумышленниками, когда остальные техники не дают результата.
Кросс-сайтовый (межсайтовый) скриптинг. Если атаки с использованием уязвимостей SQL-инъекции направлены на серверы СУБД, то атаки с применением XSS-уязвимостей — на пользователей системы. XSS-уязвимости в приложении могут стать причиной отображения пользователю нежелательного контента, хищения конфиденциальной информации или загрузки на компьютер жертвы вредоносных программ. Для получения максимального эффекта от атаки злоумышленник помимо XSS-уязвимости в программных компонентах сервера приложений также эксплуатирует уязвимости в браузере на стороне пользователя. Существует три основных вида XSS-уязвимостей: отраженные XSS (Reflected or non-persistent XSS), сохраняемые XSS (Persistent or stored XSS) и расщепление ответа HTTP (HTTP response splitting).
SOAP-инъекция. Simple Object Access Protocol (SOAP) является протоколом на основе XML, используемом в технологии веб-сервисов. Язык XML, лежащий в основе SOAP, является интерпретируемым и поэтому протокол SOAP уязвим к атакам инъекции кода.
В связи с этим при небезопасной обработке входных данных возможна модификация оригинального SOAP-сообщения, формируемого приложением, в целях изменения логики работы и обхода механизмов безопасности.
LDAP-инъекция. Lightweight Directory Access Protocol (LDAP) является протоколом для доступа к службе каталогов X.500. Каждая запись в LDAP-каталоге состоит из одного или нескольких атрибутов и обладает уникальным именем (DN). Атрибутами являются относительные уникальные имена (RDN). Относительное уникальное имя имеет вид Имя_Атрибута=значение.
В протоколе LDAP для работы с каталогом определены операции поиска, модификации, сравнения. Как правило, LDAP-каталоги используют для хранения сведений о сотрудниках организации, в том числе персональные данные.
Таким образом, в результате эксплуатации рассматриваемой уязвимости злоумышленник может извлечь содержащуюся в каталоге конфиденциальную информацию, которая недоступна при нормальной работе приложения.
XPath-инъекция. Эта уязвимость похожа на уязвимость SQL-инъекции. Некоторые приложения хранят данные (например, пароли пользователей или конфигурационные данные) в XML-файле, при этом для доступа к этим данным из приложения используется XPath.
Если XPath-выражение формируется на основе входных данных и входные данные не тестируются на безопасность, возможен несанкционированный доступ к информации, содержащейся в XML-файле.
Обход директории (Path traversal). Многие приложения выполняют чтение или запись в файлы на сервере, путь к которому формируется на основе входных данных. Для реализации атаки, эксплуатирующей уязвимость обхода директории, злоумышленник использует специальную последовательность обхода ../ (две точки, один слеш), которая позволяет выйти из текущего каталога в родительский.
В результате эксплуатации уязвимости злоумышленник сможет получить доступ к файлам с паролями и журналам аудита, а также модифицировать конфигурационные файлы приложения.
Формальный критерий наличия уязвимости в приложении. Рассмотрим формально проблему небезопасного взаимодействия слоев приложения. Отдельный программный компонент слоя или слой целиком можно представить в виде графа потока управления (Control Flow Graph, CFG), который представляет собой ориентированный граф S = (V, E) и обладает следующими основными свойствами:
1) {start, stop} e V, In (start) = Out (stop) = 0;
2) Vv e V0, V0 с V / [start, stop} : p = start ^* v ^* stop, p e E;
3) Vv, w eVv <3p = w start,..., w), v е p (отношения предшествования);
4) Vv, w eV v sdom w v< w л v Ф w (отношение обязательного предшествования);
5) Vv, w eV v idom w v sdom w лVu eVu sdom w ^ u < v (отношение непосредственного обязательного предшествования).
Каждая вершина v eV графа S связана с вызовом метода, который можно отнести к одному их четырех типов Mt = {sourse, propagation, sink, e}.
Методы типа source (далее — source-методы) определяют, каким образом входные данные попадают в приложение.
Методы типа propagation (далее — propagation-методы) определяют, каким образом данные передаются внутри приложения.
Методы, имеющие тип sink (далее — sink-методы) определяют выполнение потенциально опасных действий в приложении, таких как обращение к СУБД с SQL-запросом. Остальные методы относятся к типу e.
Отображение F1 : V ^ Mt задает для каждой вершины v eV графа S тип вызываемого метода.
Множества Ci, С2, С3 определяют классы source-, propagation- и sink-методов. Отображение F2 : V ^ C1 U С2 U С3 U {е} задает для каждой вершины v eV графа 6 класс метода следующим образом:
1) Fz(v) = ci, v е V, ci g Ci & Fi(v) = sourse;
2) Fz(v) = C2, v g V, C2 g C2 & Fi(v) = propagation;
3) Fz(v) = сз, v g V, сз е C3 & Fi(v) = silk;
4) Fz(v) = е, v е VC3, v & Fi(v) = е.
Отображение F3 : Ci x С2 x С3 ^ В, где В = {0, i}, задает propaga-
tion-методы, которые не проверяют входные данные на безопасность при заданных source- и sink-методах. Если F3 : (ci, с2, с3) = i, то propagation-метод, имеющий класс с1 и расположенный между вызовами source- и sink-метода с классами с2, и с3, не проверяет входные параметры на безопасность.
К propagation-методам, которые не проверяют входные данные на небезопасность, относятся, например, функции работы со строками в языке программирования Java: String.toString, String.concat, String. toLowerCase, String.toUpperCase, String.substring, String-Builder.append, StringBuilder.substring, StringBuilder.toString и т. д.
Сформулируем необходимый критерий наличия уязвимостей в приложении, который будет использован при статическом анализе исходных текстов приложения.
Программные компоненты слоя приложения содержат уязвимости, связанные с небезопасным взаимодействием слоев приложения, если выполнены следующие условия:
1. Пусть 6 = (V, E) — граф потока управления приложения.
2. Путь у = vi, v2, ..., vn, у е 6.
3. Fi(v1) = sourse, Fi(vn) = silk, Vj: Fi(vj) = propagation, Fi(vj) Ф е, i < j < n.
4. Fz(vi) = ci, F2(vn) = Cn, Vj : F2&) = cj, i < j < n .
5. Vj : F3(ci, Cj, Cn) = i, i < j < n.
Предложенный критерий является необходимым, но недостаточным. Это означает, что результаты статического анализа исходных текстов приложения с использованием данного критерия, будут содержать ложные срабатывания — ошибки первого рода (False Positives). Чтобы свести к минимуму ошибки первого рода, необходимо дополнительно использовать динамический анализ приложения на наличие уязвимостей. Динамический анализ предполагает имитацию реальных атак на приложение, которые эксплуатируют уязвимости, выявленные в ходе статического анализа. Если атака на прило-
жение успешно осуществлена, это означает, что уязвимость, выявленная в ходе статического анализа, присутствует в приложении. В противном случае уязвимость, выявленная в ходе статического анализа, является ложным срабатыванием.
Статический анализ исходных текстов приложения на наличие уязвимостей. Статический анализ основан на сформулированном выше формальном критерии и использует результаты контекстно-нечувствительного анализа для построения графа потока управления приложения, а также результаты контекстно-чувствительного анализа указателей целей для определения объектов кучи, на которые ссылается интересующая переменная в исходном коде приложения. Контекстно-нечувствительный анализ и контекстно-чувствительный анализ целей указателей рассмотрены в работах [6, 8].
Для описания алгоритмов статического анализа исходных текстов на наличие уязвимостей применяют язык логического программирования Datalog, позволяющий эффективно и компактно описывать алгоритмы статического анализа.
Статический анализ исходных текстов приложения на наличие уязвимостей включает четыре этапа (рисунок):
0. Исходные тексты программы
1. Локальный анализ исходных текстов
3. Контекстно-чувствительный анализ целей указателей
4. Выявление уязвимостей
Цели указателей
► А h
Статический анализ исходных текстов на наличие уязвимостей
1. Локальный анализ. На этом этапе осуществляется заполнение EBD-отношений основными атомами на основе локального (внутри-процедурного) анализа исходных текстов программы.
2. Построение графа вызовов приложения. На данном этапе выполняется построение графа вызовов приложения на основе контекстно-нечувствительного анализа указателей целей. Алгоритм построения графа вызовов Л1 - (D1, P1, R1) рассмотрен в работах [6, 8].
3. Определение целей указателей. На этом этапе осуществляется вычисление целей указателей на основе контекстно-чувствительного анализа. Алгоритм определения целей указателей Л2 -(D2, P2, R2) рассмотрен в работах [6, 8].
4. Выявление уязвимостей. На данном этапе выявляются уязвимости в приложении при использовании предложенного формального критерия. Алгоритм Л3 - (D3, P3, R3) описан ниже.
Язык Datalog. Этот язык использует записи наподобие языка Prolog, но с более простой семантикой. Элементами Datalog являются атомы, которые имеют вид p(X\, X2, ..., Xn), где p — предикат; X1, X2, ..., Xn — переменные или константы. Предикат, аргументами которого являются константы, называется основным атомом. Литералом называется атом либо его отрицание.
Алгоритм статического анализа исходных текстов рассматривается как набор правил языка Datalog. Правила имеют вид H(x, y) : -A(x, z), B(y, w), C(z, q), где H(x, y) — заголовок правила; A(x, z), B(y, w), C(z, q), — тело правила; A(x, z), B(y, w), C(z, q) — литералы. Правило задает, каким образом должен быть вычислен заголовок правила. Заголовок правила является истинным, если все литералы, содержащиеся в правой части правила, истинны.
Упорядоченные бинарные диаграммы решений. Программа на языке Datalog представляет проблему статического анализа исходного кода приложения в терминах операций над конечными областями. С помощью бинарного кодирования указанных областей проблема анализа безопасности исходного кода может быть сведена к операциям над булевыми значениями. Одним из эффективных методов представления и обработки булевых функций является использование упорядоченных бинарных диаграмм решений (Oriented Binary Decision Diagram, OBDD).
OBDD-диаграммы представляют булевы функции в виде ориентированных ацикличных графов. OBDD имеет одну корневую и две терминальные (листовые) вершины, которые помечены 0 и 1. Нетерминальные вершины помечены переменными булевой функции. Булева функция f при фиксированном порядке переменных x1 < x2 < ... < xn имеет несколько изоморфных OBDD-представлений B1, B2, ..., Bs.
Представление с минимальным количеством вершин называется ROBDD.
Множество операций над булевыми функциями ОР = = (V,A,®,®,3, V) реализуется в виде графовых алгоритмов на OBDD. К основным графовым алгоритмам относятся алгоритмы Build, Apply, Restrict. Алгоритм Build позволяет построить ROBDD для булевой функции f; таким образом Bf = Build (f). В общем случае сложность алгоритма Build является экспоненциальной. Размер ROBDD зависит от задания порядка переменных Kf булевой функции f. Поэтому алгоритм Build использует эвристические методы для нахождения оптимального порядка переменных Kf. Для некоторых
классов булевых функций доказаны асимптотические оценки размера ROBDD. Так, для симметричных булевых функций справедлива следующая оценка: O(n) < Bf < O(n2), где п — количество переменных
булевой функции f.
Алгоритм Apply реализует операции над булевыми функциями при помощи операций с OBDD. Пусть Bf и Bf — ROBDD-пред-
ставления булевых функций fi и f2, тогда Bf — Apply(B^, Bf ), где f — fi °P f2 и op e OP, является представлением функции f Сложность алгоритма Apply равна O^B^ ■ B^ j.
Алгоритм Restrict позволяет найти ROBDD-представление для булевой функции f1 — f\xi ^ b, где b e{0, l}. Сложность алгоритма
Restrict равна O ^Bf | j.
Таким образом, для вычисления Datalog-программы необходимо представить правила вычисления предикатов в виде формул булевой алгебры BA, а затем представить характеристические булевые функции в виде ROBDD и вычислить результирующую булеву функцию по формуле BA с использованием алгоритмов Apply и Restrict.
Алгоритм анализа уязвимостей. Этот алгоритм представляет собой кортеж Л3 — (D3, P3, R3).
Первый элемент кортежа Л3 задает множество доменов D3 = — {C, M, H, V, Z, I}. Каждый домен определяет множество значений
переменных и констант, которые являются аргументами предикатов. Домен С определяет множество контекстов, М — множество методов; Н — множество объектов кучи; V — множество используемых в программе переменных; Z — множество номеров параметров; I — множество точек вызовов.
Второй элемент кортежа Л3 задает множество предикатов P3PeBD U PiBD, PeBD П PfBD — 0. Предикат p <= P3 является отношением вида p: Xх YхZх... ^ {True, False}, где {X, Y, Z, ...}с D3. Будем
различать два типа предикатов: предикаты экстенсиональной базы данных (Extensional database, EBD) и предикаты интенсиональной базы данных (Intensional database, IBD). EBD-предикаты — это предикаты, которые определены априори (их значения заданы с помощью таблицы, при подстановке строки вместо переменных предикат становится истинным). IBD-предикаты — это предикаты, которые определяются с помощью правил.
Для алгоритма анализа уязвимостей будем использовать следующие множества EBD- и IBD-предикатов:
PeBD — {vPc, Ret, SourseMethod, SinkMethod, PropagationMethod, Actual, IEc}; PfBD — {Sourse, Sink, Tainted, Vulnerability}.
Для анализа уязвимостей вводятся следующие предикаты: Ret, SourseMethod, SinkMethod, PropagationMethod, Sourse, Sink, Tainted,
Vulnerability, vPc, IEC, которые определены следующим образом:
1) oтношение Ret: M х I х V ^ {True, False} определяет, что возвращаемое функцией m G M значение в точке вызова i G I сохраняется в переменной v G V;
2) oтношение vPC: C х V х H True, False} определяет, что переменная v G V указывает на объект кучи h G H в контексте c G C;
3) oтношение IEC: C х I х M ^ {True, False} определяет цели точек вызова. Предикат является истинным, если существует точка вызова i в контексте c, которая вызывает метод m, т. e. i : v.m(...) в контексте c;
4) oтношение Actual: I х Z х V ^ {True, False} определяет, что v G V является фактическим параметром с номером z G Z вызова в точке i G I.
5) oтношение Sourse: CхIхVхH ^ {True, False} определяет, что
объект h G H в контексте c G C, сохраненный в переменной v G V,
содержит данные из ненадежного источника (например, вводимые пользователем данные) и создан в результате вызова source-метода в
точке вызова i G I;
6) отношение Sink: C x I x V x H True, False} определяет, что
объект h G H в контексте c G C, сохраненный в переменной v G V, передается в качестве параметра в sink-метод, который выполняет потенциально опасные действия (обращение к СУБД с динамическим SQL-запросом, выполнение кода, чтение данных из файла и т. д.), в
точке вызова i G I.
7) отношение Tainted: C x I x V x H ^ {True, False} определяет,
что объект h G H в контексте c G C, сохраненный в переменной v E V, является небезопасным и получен в результате вызова propagation-метода в точке вызова i G I, который не осуществляет проверку данных на безопасность;
8) отношение SourseMethod: M ^ {True, False} определяет, что
метод m G M является source-методом;
9) отношение SinkMethod: M x Z ^ {True, False} определяет, что
метод m G M является sink-методом; номер параметра метода z G Z
определяет входной параметр, в качестве которого в метод т передаются потенциально опасные данные (например, строка, содержащая SQL-запрос, который передается СУБД в результате вызова sink-метода);
10) отношение PropagationMethod: Mx Z ^ {True, False} определяет, что метод m G M является propagation-методом; номер параметра метода z G Z определяет входной параметр, в качестве которого в метод т передаются потенциально опасные данные;
Vulnerability: C x I x C x I ^ {True, False} определяет, что входные данные, поступающие в результате вызова source-метода, в точке вызова ii G I и в контексте c G C недостаточно проверяются приложением и передаются в sink-метод в точке вызова i2 G I и в контексте c2 G C,
который совершает потенциально опасные действия; в результате приложение является уязвимым к рассмотренным выше уязвимостям.
Предикаты vPc, IEC вычисляются на шаге контекстно-чувствительного анализа целей указателей. Остальные EBD-предикаты вычисляются в ходе внутрипроцедурного анализа.
Множество правил для вычисления IBD-предикатов R =
— {r^ R2 , ..., R5 } .
(R3 j Sourse(c, i, v, h): -IEC(c, i,_ , m), SourseMethod(m), Ret(m, i, v), vPc (c, v, h).
(R23 j Sink(c, i, v, h): _IEc (c, i,_ , m), SinkMethod(m, z), Actual(i, z, v1), vPc (c, v, h).
(3* j Tainted(c, i, v, h): - Sourse(c, i, v, h).
(R43 j Tainted(c, i, v, h): -IEc (c, i,_ , m), PropagationMethod(m, z), Actual(i, z, v1), vPc (_, v1, h1), Ret(i, v), vPc (c, v, h), Tainted(_, _, v1, h1).
(r^ j Vulnerability: (c1, i1, c2, i2 ): -Sourse(c1, v1, h1), Sink(c2, i2, v2, h2 ), Tainted(c2, i2, v2, h2 ).
Заключение. Рассмотрена методика оценки уязвимостей корпоративных приложений, которые связанны с небезопасным взаимодействие слоев приложения. Методика применима для анализа уяз-вимостей корпоративных приложений, функционирующих на платформах J2EE и .Net Framework и разработанных с использованием языков программирования высокого уровня, таких как Java, C#, VB.Net, ASP, ASP.Net и JSP. Благодаря статическому анализу, основанному на контекстно-чувствительном анализе с использованием упорядоченных бинарных диаграмм решений, данная методика позволяет проводить анализ уязвимостей сложных корпоративных приложений, которые состоят из десятка тысяч строк кода.
СПИСОК ЛИТЕРАТУРЫ
1. Justin Clarke. SQL Injection Ettacks and defense. Syngress Date: May 2009. -474 p.
2. Sttutard D., Pinto M. The Web Application Hacker's Handbook: Discovering and Explointing Security Flaws.
3. Поляков А. М. Безопасность Oracle глазами аудитора: нападение и защита. -М.: ДМК Пресс, 2010. - 336 с.
4. Litchfield D., Anley C., Heasman J., Grindlay B. The Database Hacker's Handbook: Defending Database Servers. Publisher: Wiley Date: July 2005. -500 p.
5.Ховард М., Лебланк Д. Защищенный код: Пер. с англ. - 2-е изд., испр. -М.: Изд.-торг. дом «Русская редакция», 2004.
6. Ахо А., Лам М., Сети Р., Ульман Д. Компиляторы: принципы, технология и инструментарий. - 2-е изд.: Пер. с англ. - М.: ООО «И.Д. Вильямс», 2008. -1184 с.
7. Wegener I. Branching programs and binary decision diagrams: theory and applications. p.cm. - (SIAM monograph on discrete mathematics and applications). -ISBN 0-8987i-458-3.
8. Whale y J., Lam M. Cloning-based context-sensitive pointer alias analysis using binary decision diagram // In Proc. of the ACM SIG-Plan 2004 Conference of Programming Language Design and Implementation. - P. i3i-i44.
9. Markov A. S., Kernozitsky V. A. Economically effective data bases diagnostics method // Advances in Modeling & Analysis. AMSE B. i995. - Vol. 33. No. 3. - P. 5-ii.
i0. Пакеты программ офисного назначения / С.М. Кильчик, А.С. Марков,
С.В. Назаров и др. - М.: Финансы и статистика, i997. - 320 с. i i. Медведев Н. В., Быков А. Ю., Гришин Г. А. Противодействие неавторизованному доступу к серверу Web-приложений с использованием механизма подложных SQL-запросов // Вестн. Моск. гос. техн. ун. им. Н.Э. Баумана. Сер. Приборостроение. 2006. - № 3. - С. 74-82. i2. Кларк Э. М., Грамберг О., Пелед Д. Верификация моделей программ: Model Checking. М.: МЦНО, 2002. 4i6 с.
Статья поступила в редакцию i9.i0.20ii