Главная > Uncategorized > Taint Analysis: ограничения модели. Часть 1.

Taint Analysis: ограничения модели. Часть 1.

Недавно мы рассмотрели две модели уязвимостей, которые используются при статическом и динамическом анализе веб-приложений. В предыдущем посте было показано, что обнаружение уязвимостей не будет эффективно на 100%, если у используемой модели есть ограничения. Именно об ограничениях taint-анализа и пойдет сегодня речь. Мы рассмотрим, какие типы уязвимостей заведомо не могут быть найдены при использовании этой модели.
Давайте еще раз вспомним, в чем заключается базовая модель, используемая в taint-анализе:

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

Известно, что существует немало типов уязвимостей, например: уязвимости, связанные с некорректной обработкой пользовательских данных, использование нестойкой криптографии, некорректное освобождение ресурсов и т.д. Так вот, taint-анализ адресует только уязвимости, связанные с некорректной обработкой пользовательских данных. Это следует из определения модели, не так ли? Соответственно, если нам маркетологи станут рассказывать про 100% полноту анализатора TuroboFinder (Enterprise Edition), который осуществляет только taint-анализ, мы их тут же ловим на лжи вопросом: «а как же ваш анализатор проверяет, например, отсутствие утечки ресурсов веб-приложения?»

Однако и в рамках Input Validation уязвимостей, которые явно адресованы моделью, не всё гладко. Пусть мы реализуем taint-анализ для PHP. Будем считать, что пользовательские данные возвращаются через обращения к массивам $_GET и $_POST; критические операции — mysql_query, echo, system; фильтрующие функции — addslashes, htmlspecialchars и escapeshellcmd 1. Давайте теперь рассмотрим примеры, на которых модель не будет показывать 100% результат.

Ограничение №1: отсутствие типов у метки taint. Рассмотрим фрагмент кода веб-приложения, который реализует навигацию по архиву новостей в новостной ленте.

1: $skip = $_GET['skip'];
2: $skip = htmlspecialchars($skip);
3: mysql_connect();
4: mysql_select_db("myDB");
5: $query = "SELECT text FROM news LIMIT 10 OFFSET ".$skip;
6: $result = mysql_query($query);
7: pretty_print_query_result($result); //вывод новостей в тело HTTP-ответа

Давайте применим модель к приведённому фрагменту кода.

  1. В первой строке переменная $skip инициализируется данными из HTTP-запроса. По первому правилу модели её значение помечается меткой taint.
  2. Во второй строке переменная $skip проходит через функцию htmlspecialchars, которая у нас объявлена фильтрующей. В соответствие с третьим правилом модели с переменной снимается метка taint.
  3. В пятой строке значение переменной $skip используется для построения SQL-запроса. Так как значение переменной $skip не помечено меткой taint, то и значение переменной $query не будет помечаться меткой taint.
  4. В шестой строке переменная $query используется при вызове функции mysql_query, которая у нас объявлена критической. Проверяем, помечено ли значение аргумента меткой taint? Нет, не помечено — значит в соответствие с четвёртым правилом модели уязвимость SQLI отсутствует. Конечно, это не так!

Итак, уязвимость в коде есть, а модель её не обнаруживает. Это минус полноте. Данное ограничение легко снять, если ввести типы метки taint в соответствие с типами уязвимостей. Так, вместо одной метки taint у нас будут метки sql-taint, xss-taint, os-injection-taint и т.д. Как это должно работать?
Данные, полученные из HTTP-запроса, помечаются сразу всеми метками. При прохождении данных через фильтрующие функции снимается только соответствующая метка (остальные сохраняются): addslashes снимает sql-taint, htmlspecialchars — xss-taint, а escapeshellcmd — os-injection-taint. При вызове критических функций, опять же, мы будем проверять наличие соответствующей метки (остальные метки нас не интересуют). Так, при вызове mysql_query будем проверять наличие sql-taint, при вызове echo — наличие xss-taint, а при вызове system — наличие os-injection-taint. Итак, первое ограничение легко преодолеть. Давайте дальше считать, что у нас taint-анализ имеет типизированные метки, и перейдем уже к следующему ограничению.

Ограничение №2: данные, получаемые из локального хранилища данных, не всегда являются надежными. Рассмотрим фрагмент веб-приложения, которое реализует простейшую гостевую книгу.

модуль addpost.php
1: $text = $_GET['text'];
2: $text = addslashes($text);
3: mysql_connect();
4: mysql_select_db("myDB");
5: $query = "INSERT INTO posts (text) VALUES ('".$text."')";
6: mysql_query($query);
7: // do redirect

модуль viewpost.php
1: $skip = $_GET['skip'] + 0;
2: mysql_connect();
3: mysql_select_db("myDB");
4: $query = "SELECT text FROM posts LIMIT 10 OFFSET ".$skip;
5: $result = mysql_query($query);
6: while ($row = mysql_fetch_assoc($result)) {
7:    echo $row['text'];
8: }

Давайте применим модель к приведённому фрагменту кода. Сначала рассмотрим модуль addpost.php:

  1. В первой строке переменная $text инициализируется данными из HTTP-запроса. Следовательно, её значение помечается сразу всеми метками {sql-taint, xss-taint, os-injection-taint}.
  2. Во второй строке переменная $text проходит через фильтрацию относительно спецсимволов языка SQL, а значит мы должны снять метку sql-taint. При этом значение переменной $skip сохранит метки xss-taint, os-injection-taint.
  3. В пятой строке переменная $text используется при инициализации переменной $query. А раз так, переменная $query унаследует от $text её метки: xss-taint, os-injection-taint.
  4. В шестой строке переменная $query используется при вызове критической функции mysql_query. Согласно требованиям модели (уже типизированной), аргументы этой функции не должны содержать метку sql-taint. Наш пример удовлетворяет требованиям модели, и, следовательно, модуль addpost.php не содержит уязвимость SQLI.

Теперь давайте рассмотрим модуль viewpost.php:

  1. В первой строке переменная $skip инициализируется данными из HTTP-запроса, которые предварительно приводятся к целому числу (то есть, в переменной $skip в итоге оказывается не строка, а число). Для простоты мы будем считать, что метка taint связывается только со строками, а значит переменная $skip у нас будет без меток.
  2. В четвертой строке переменная $skip используется при инициализации переменной $query. Соответственно, переменная $query должна унаследовать от $skip все её метки. Так как меток у $skip нет, то и у $query их не будет.
  3. В пятой строке переменная $query используется при вызове критической функции mysql_query. Так как с переменной $query не связано никаких меток, уязвимостей SQLI в модуле viewpost.php нет.
  4. В шестой строке переменной $row в цикле присваивается очередной кортеж выборки из базы данных. Согласно второму предположению модели, все данные, полученные из локального хранилища, являются надежными. Значит, все строки в ассоциативном массиве $row окажутся без taint-меток.
  5. В седьмой строке данные из массива $row используются в критическом вызове echo. Так как строки в массиве $row не имеют никаких меток, то основное требование модели выполнено — уязвимостей XSS в модуле viewpost.php нет.

Получается, что согласно модели наше веб-приложение не обладает уязвимостями. Очевидно, это не так — перед нами классический пример Persistent XSS. В итоге, из-за второго ограничения модели мы не можем находить межмодульные уязвимости. Это опять минус полноте.
Методом пристального взгляда можно заметить, что межмодульные уязвимости мы не находим, потому что taint-метки пропадают при сохранении данных в локальное хранилище. Справедливый вопрос: а почему метки нельзя где-то сохранить?

Для того, чтобы грамотно ответить на этот вопрос, необходимо сделать небольшое лирическое отступление. Вспомним, что и динамический и статический анализ проводится на определенных представлениях программы. Но ведь ни одно представление программы не использует понятие метки, а тем более метки taint! Обман? Отнюдь. Дело в том, что использование меток — всего лишь один из способов (кстати, самый наглядный) вычисления зависимостей по данным. Действительно, отслеживая распространение метки, мы получаем граф зависимостей, например, от параметров HTTP-запроса. Стоит добавить, что концепт распространения метки больше сродни динамическому анализу, чем статическому.
Теперь наш вопрос про сохранение меток мы можем переформулировать более грамотно: а можно ли вычислять зависимости по данным через СУБД, файловую систему и пр.? Мы подошли к очень интересному моменту: исходная модель явно предполагает, что работа будет вестись только с представлениями отдельных модулей веб-приложения. Соответственно, если у нас появится способ построения представления веб-приложения, в котором отражены межмодульные зависимости (а это уже задача не информационной безопасности, а анализа программ), мы сможем смело снять гадкое второе правило модели. Хорошо, что и в статическом и в динамическом анализе задача построения такого представления уже решена.2

В заключение я бы хотел сказать пару слов о реализациях этой модели в анализаторах. Ведущие коммерческие статические анализаторы умеют строить представления веб-приложений, в которых отражены межмодульные зависимости. Соответственно, применение taint-анализа к такому представлению даст хороший результат — средство будет обнаруживать межмодульные уязвимости. В динамических анализаторах с межмодульными зависимостями, насколько мне известно, все плохо (PoC из статьи не в счет).

Краткое резюме. Taint-анализ предназначен только для обнаружения уязвимостей, возникающих из-за некорректной обработки пользовательских данных. При этом базовая модель этого типа уязвимостей имеет целый ряд ограничений, из-за которых анализаторы, реализующие её, заведомо не могут иметь 100% эффективность. Некоторые из этих ограничений преодолимы, некоторые — нет.
В первой части были рассмотрены самые простые ограничения модели: отсутствие типизации taint-меток по видам ненадежных данных и полное доверие к данным, получаемым из локального хранилища веб-приложения. Оба эти ограничения снижают полноту обнаружения. Однако оба этих ограничения преодолимы.
Во второй части мы обсудим более тонкие недостатки рассматриваемой модели уязвимостей.

p.s. Любой feedback и/или предложения всегда приветствуются.

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

Note 2. Пример вычисления межмодульных зависимостей при статическом анализе можно найти в статье «Multi-Module Vulnerability Analysis of Web-based Applications», а при динамическом анализе — в статье «Detecting Security Vulnerabilities in Web Applications Using Dynamic Analysis with Penetration Testing».

Реклама
  1. 15.12.2010 в 22:27

    Большое спасибо за статью.

    Могу добавить чисто по реализации:
    метки можно складывать, составлять из простых сущностей.
    Как то: фильтрация кавычек идет в sqli и attr inj based xss.
    И так далее. Плюсы такого подхода очевидны.

    Метки могут иметь динамические зависимости.
    Пример: фильтрация нижнего подчеркивания в при попадании в parse_str без второго аргумента или когда второй аргумент может быть null.

    Хотя на деле для контроля точности сверху метода меток пришлось накручивать еще алгоритмы.
    Пример:

  1. No trackbacks yet.

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

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

Логотип WordPress.com

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

Фотография Twitter

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

Фотография Facebook

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

Google+ photo

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

Connecting to %s

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