Главная > Uncategorized > Модели уязвимостей, используемые в статическом и динамическом анализе

Модели уязвимостей, используемые в статическом и динамическом анализе

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

Фундаментальное определение уязвимости в ПО было дано Деннинг аж в 1975 году и потом было развито в моделях невыводимости и невмешательства, а также их расширениях (хороший обзор есть вот тут). Больше всего нас интересует модель невмешательства. Вкратце, модель определяет уязвимость так:
Пусть программа получает данные из high-level (доверенных) и low-level (недоверенных) каналов и генерирует вывод в high-level (критические) и low-level (обычные) каналы. Вывод low-level (недоверенных) данных в high-level (критический) канал считается нарушением принципа невмешательства. 2
С этим определением уже можно работать — надо только определить, что в программе мы будем считать каналами ввода и каналами вывода.

Самый простой вариант, известный как taint analysis (или taint checking), решает задачу в лоб: недоверенные каналы ввода — это методы, возвращающие данные HTTP-запросов, а критические каналы вывода — это вызов критических функций (нам надо явно указать, каких).
Модель уязвимости выглядит так:

  • данные, полученные из HTTP-запросов, считаются ненадежными; это low-level каналы ввода;
  • данные, полученные из локального хранилища данных (файловая система, СУБД), считаются надежными; это high-level каналы ввода;
  • ненадежные данные могут стать надежными в следствие специальной обработки (фильтрации);
  • ненадежные данные не должны попадать в критические операции (запросы к СУБД, вывод HTML, системные вызовы, eval’ы и т.д.); это high-level каналы вывода.

Это значит, для применения модели для конкретного языка и конкретного веб-фреймворка надо сделать небольшое исследование. Во-первых, найдо перечислить все конструкции, возвращающие данные HTTP-запросов (например, для PHP к этим конструкциям будут относится обращения к массивам $_GET, $_POST, $_COOKIE и т.д.) и указать их анализатору. Соответственно, анализатор будет помечать переменные, получившие свое значение из таких конструкций, как «tainted». В графе зависимостей по данным вершины, соответствующие такой инициализации, будут раскрашиваться, например, в красный цвет.
Во-вторых, надо перечислить все критические операции, аргументы для которых мы бы не хотели отдавать под контроль злоумышленника. Для PHP в этот список войдут, например, mysql_query, echo, system, eval и т.д. В графе зависимостей по данным вершины, соответствующие вызовам этих функций, будут раскрашиваться, например, в синий цвет.
В-третьих, надо перечислить все фильтрующие конструкции, которые нормализуют, а потом удаляют, экранируют или кодируют специальные символы в пользовательском вводе. Для PHP в этот список войдут, например, htmlspecialchars, addslashes, escapeshellcmd.3

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

Второй вариант претворения базового определения невмешательства в жизнь основан на следующем наблюдении. Все веб-приложения в процессе своей работы взаимодействуют с окружением: СУБД, LDAP, браузером клиента, файловой системой, стандартным интерпретатором ОС и т.д. Многие из этих элементов окружения предоставляют специальный язык (в общем смысле этого понятия) для взаимодействия с ними: СУБД — язык SQL, LDAP — язык запросов LDAP, браузер — HTML/CSS/JavaScript/расширения, файловая система — язык именования объектов (пути), стандартный интерпретатор ОС — *nix shell/CMD shell/whatever. Большинство обращений веб-приложений к окружению параметризованы, а параметры этих обращений зависят от пользовательского ввода.

Заметим теперь, что все уязвимости к внедрению кода (HTML, SQL, OS, и т.д.) позволяют злоумышленнику изменять структуру соответствующего обращения к окружению. А это значит, что дерево синтаксического разбора соответствующего обращения при внедренном коде и без внедренного кода будет различным не только в листьях (потому что запрос параметризован), но и на более верхних ярусах.
Этот тезис очень хорошо проиллюстрирован на рисунке ниже4. На нем показаны два дерева разбора WHERE-клаузы в SQL-запросах с внедрением (а) и без внедрения (b):

SELECT cardnum FROM accounts WHERE uname='John' AND cardtype=2
SELECT cardnum FROM accounts WHERE uname='John' AND cardtype=2 OR 1=1

Деревья разбора WHERE-клаузы для SQL-запроса без внедрения (a) и с внедрением (b)

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

В следующем посте я расскажу об ограничениях этих моделей уязвимостей, а потом о реализациях этих моделей в рамках статического и динамического анализа.

Note 1. На самом деле, здесь есть небольшое лукавство. Статические анализаторы реально ищут не уязвимости, а ошибки, которые могут стать (а могут и не стать) уязвимостями. Пример ошибок в программе, которые не являются уязвимостями:
1. Допустим, у нас есть веб-приложение, со следующими характеристиками:

  • не имеет авторизации, все интерфейсы доступны в public;
  • приложение предоставляет функции по поиску и фильтрации результатов футбольных матчей;
  • приложение обращается в СУБД только к одной таблице, с теми самыми результатами матчей;
  • для этого в СУБД заведен специальный пользователь, которому даны права только на выполнение SELECT только в этой таблице;
  • возможные ошибки СУБД корректно обрабатываются — пользователь получает обычную HTML-страницу с некими общими словами «все плохо, попробуйте еще раз».

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

2. Еще один пример — это возможность переполнения буфера в программе ls. Ошибка программистов? Безусловно. Уязвимость? Ниразу…

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

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

Note 4. Рисунок взят из статьи «The Essence of Command Injection Attacks in Web Applications».

Note 5. Получается, что low-level канал вывода — это нетерминалы языка, из которых выводятся только строковые и числовые константы, а high-level канал вывода — это нетерминалы языка, из которых выводятся терминалы (например, ключевые слова). В low-level канал пользователи веб-приложений могут писать сколько угодно, а вот в high-level — никак. В него может записывать только программист, задающий структуру запросов.

Реклама
  1. 29.04.2010 в 15:36

    >> данные, полученные из локального хранилища данных (файловая система, СУБД), считаются надежными; это high-level каналы ввода;

    не согласен. пример: хостинг, загружаю файл в каталог /www1/file.jpg через сайт www1, а обращаюсь к нему через сайт www2, eq http://www2/?a=/www1/file.jpg файл file.jpg расположен в пределах одной файловой системы и при этом является не надежным.

    другой пример, LFI over logs/mail/proc — все это файловая система, но данные в них могут использоваться для реализации атаки.

    • 29.04.2010 в 18:35

      Дык я тоже не согласен :)
      Можно привести даже более красивый пример:
      1. Модуль А получил пользовательские данные, благоразумно их заэскейпил и поместил в СУБД.
      2. Модуль Б считывает данные из СУБД и использует их для построения нового SQL запроса. Модуль Б получает данные из СУБД, как нетрудно догадаться, в первоначальном виде, незаэскейпленные.
      Что же мы имеем в итоге? Данные вроде бы и проверялись, и модуль А не имеет SQLI. А веб-приложение будет уязвимо к Second Order SQLI, если модуль Б будет считать полученные из СУБД данные надежными.

      Дело в том, что когда мы рассматриваем модели уязвимости, речь не может идти в терминах согласен/не согласен. Потому что задача модели описать на некотором уровне абстракции, что есть плохо. Вот в модели taint propagation уязвимость определяется именно так. А это предположение про надежность локальных данных дает простой, но грубый ответ на вопрос: надо ли присваивать метку taint данным, полученным из локального хранилища?
      Другое дело, что такая модель имеет свои ограничения. И ты четко увидел одно из них: модель делает неадекватные предположения о надежности данных из локального хранилища. Примерно так :)
      Кстати, по поводу ограничений моделей я скоро напишу отдельный пост, stay tuned, если интересно. Ну или можно почитать об этом на английском:
      http://andrewpetukhov.blogspot.com/2010/04/limitations-of-taint-propagation.html

  1. 07.08.2013 в 00:25

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: