Делаем свободное ПО безопасней: баги и фиксы InstantCMS

    Этой статьёй мы начинаем серию материалов, посвященных поиску уязвимостей в популярных системах с открытым кодом. Ошибки в OpenSSL и glibc показали, что тысячи глаз, имеющих доступ к коду, — не гарантия безопасности open source. Конечно, и закрытый код не становится безопаснее от самого факта закрытости. Просто при наличии правильных инструментов доступность исходного кода позволяет выявить гораздо больше уязвимостей, чем при тестировании методом «чёрного ящика». Вопрос лишь в том, кто этим воспользуется раньше – разработчики или злоумышленники.

    image

    Последние два года в ходе разработки системы анализа исходных кодов PT Application Inspector мы проверяли на стендах и «в поле» сотни бесплатных и коммерческих, открытых и проприетарных приложений. В ходе этих тестов было найдено значительное число уязвимостей нулевого дня. Часть этих проблем была закрыта и известна по последним докладам о безопасности SCADA, часть ожидает своей погибели в ходе ответственного разглашения.

    Воспользуемся же открытостью open source и покажем, как выявляются и анализируются уязвимости в исходном коде. В роли первого подопытного выступает бесплатная система управления сообществами InstantCMS, работающая на PHP и MySQL. На базе данного конструктора создано немало социальных сетей, сайтов знакомств, онлайн-клубов, городских порталов и государственных ресурсов.

    В настоящее время разработчик InstantCMS устранил все обнаруженные нами уязвимости. В этой статье мы рассмотрим ошибки той версии, которая была актуальна на момент тестирования — в ней было найдено несколько десятков багов разной степени риска. Ниже описаны самые интересные.

    Краткий FAQ о проекте:
    В: Как выбираются системы для проверки?
    О: Встречаются экспертам в ходе консалтинговых работ по тестированию на проникновение и анализу защищенности.

    В: Что такое PT Application Inspector?
    О: Система анализа исходного кода: ptsecurity.ru/appsecurity/application-inspector

    В: Почему вы не пишете про систему ХХХ?
    О: Она либо ещё не проверялась, либо её уязвимости ещё устраняются разработчиками. Пишите нам в комментариях или на почту, поставим в очередь.

    В: Что вы делаете с уязвимостями?
    О: Отправляем информацию производителям ПО и помогаем устранить ошибки. Полный список обнаруженных уязвимостей: ptsecurity.ru/lab/advisory

    В любой CMS есть хотя бы одна XSS


    Исследуя код InstantCMS, наш анализатор сообщил о возможности проведения атаки XSS (межсайтовое выполнение сценариев) вот в таком формате:

    image

    Рис. 1.1. Сообщение о наличии XSS-уязвимости

    В сообщении приводится полное имя скрипта, номер строки и непосредственно сам код, содержащий уязвимость. Эта информация важна для разработчика: теперь он может найти ошибку, которая стала причиной этой уязвимости.

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

    image

    Рис 1.2. Подробная информация о найденной XSS

    Очевидно, что условие истинно только тогда, когда в запросе будет передан конкретный параметр:

    textinputs[]=''

    Проверим, как это работает на практике. Отправляем на сервер эксплойт и получаем ответ:

    image

    Рис 1.3. Запрос и ответ сервера

    Как видим, ответ сервера в HTML-странице содержит именно тот JavaScript-код, который мы отправляли в эксплойте.
    Итак, мы убедились, что уязвимость существует. Самое время покопаться в коде и найти ошибку программиста. Воспользуемся информацией из Application Inspector, а именно — полным именем скрипта, номером строки и самим кодом, содержащим уязвимость (см. рис. 1.2).

    Проанализировав исходный код, получаем такую картину:

    Файл spellchecker.php:

    17 строка: 	$textinputs = $_POST['textinputs'];
    …
    		function print_textinputs_var() {
    			global $textinputs;
    			foreach( $textinputs as $key=>$val ) {
    27 строка:			echo "textinputs[$key] = decodeURIComponent(\"" . $val . "\");\n";
    			}
    }
    …
    161 строка: 	print_textinputs_var();
    

    Функция print_textinputs_var () объявлена в верхней части этого же скрипта и как раз содержит известную нам строку номер 27, в которой происходит вызов опасной функции “echo”:

    Анализ показал, что код в строке 17 содержит недостаток — нефильтрованный параметр $_POST['textinputs'] — который и стал причиной уязвимости в строке 27. А это, в свою очередь, сделало XSS-атаку возможной.

    Чего можно добиться с помощью XSS? Как минимум инвайта на Хабре :) А если звезды сойдутся — получить в свое распоряжение cookies администратора сайта, а следовательно, и доступ в админскую панель.

    Уязвимость HTTP Response Splitting


    В ходе дальнейшего сканирования была обнаружена возможность провести атаку, основанную на расщеплении HTTP-ответа сервера (HTTP Response Splitting):

    image

    Рис 2.1. Отчет Application Inspector (справа — уязвимость в деталях)

    Сгенерирован классический тестовый эксплойт, добавляющий дополнительный заголовок путем внедрения символов «перевод строки» и «возврат каретки». Эксплуатация возможна, если приложение работает на PHP версии ниже 5.1.2 (в более поздних версиях в интерпретатор встроена защита от таких атак).

    image

    Рис. 2.2. Граф потока выполнения демонстрирует наличие уязвимости

    Результат анализа позволяет найти причину возникшей уязвимости и выработать рекомендации по ее устранению. Система PT AI указала, что вызов опасной функции произошел на 32-й строке файла set.php. Открыв исходный код, мы действительно видим, что в означенную строку попадает параметр, принимаемый без всякой фильтрации из POST-запроса в 15-й строке того же файла.

    image

    Рис 2.3. Программный код, содержащий уязвимость

    Бывают случаи, когда разбор причин возникновения уязвимости является значительно более трудоемким, однако в данном случае и причины возникновения уязвимости, и пути ее устранения очевидны. Программисту необходимо добавить дополнительные проверки при присвоении значения переменной $back.

    Уязвимость Open Redirect


    В результате сканирования была обнаружена возможность провести атаку, классифицируемую как Open Redirect — открытое перенаправление:

    image

    Рис 3.1. Отчет о наличии Open Redirect, с подробной информацией

    Воспользуемся автоматически сгенерированным запросом-эксплойтом: отправим его на сервер-стенд и проанализируем ответ.

    image

    Рис 3.2. Запрос-эксплойт для проверки уязвимости Open Redirect и ответ на него

    Как мы видим, в исследуемой CMS действительно имеет место открытое перенаправление: ответом на запрос стала страница стороннего ресурса, переданная в векторе атаки. Попробуем разобраться в причинах. Отчет говорит о том, что точкой выхода атаки является строка 32 файла set.php. Откроем программный код:

    image

    Рис 3.3. Уязвимый участок программного кода

    В 32-й строке формируется заголовок location со значением из переменной $back. В свою очередь, переменная $back принимает свое значение из массива $_POST в 15-й строке того же файла без всяких дополнительных проверок. Таким образом становится ясна причина уязвимости — передача нефильтрованного параметра в 15-й строке файла set.php. Для устранения ошибки необходимы дополнительные проверки для переменной $back.

    Чем опасна эта уязвимость? Прежде всего — возможностью практически незаметно для пользователя перенаправить его на зараженную страницу, а затем, так же незаметно, вернуть обратно.

    Сплитинг и редирект в свежей PHP и Internet Explorer


    Сплитинг с использованием последовательности символов %0D%0A работает на версиях PHP ниже 5.1.2, однако в некоторых ситуациях он возможен, даже если на сервере используется современная версия PHP.
    Подходящие условия возникают, если клиентом является браузер Internet Explorer: он понимает последовательности %0A%20 или %0D%0A%20 как разделитель, а другие браузеры считают новую строку, начинающуюся с пробела, продолжением предыдущего заголовка. Такое поведение IE и недостаточная фильтрация в функции header() в PHP делают сплитинг возможным. Баг в header() исправлен недавно (bugs.php.net/bug.php?id=68978) и скоро попадет в релизы.

    Примеры внедрения заголовка и содержимого в IE — ниже, адрес для проверки: molnar.es/php-header/test.php.

    image

    Рис. 4.1

    image

    Рис. 4.2

    Проверить внедрение заголовков и открытое перенаправление на уязвимом сценарии (InstantCMS set.php в IE) можно и с помощью AI. Возьмем информацию из двух эксплойтов, полученных AI (адрес, метод, нефильтруемый параметр) для демонстрации такого вектора атаки на примере ptsecurity.com. Сделаем форму, которая посылает нужный вектор на нужный адрес, и посмотрим, работает ли атака. Как видим, да: на рис. 4.4 видно и адрес скрипта (set.php), и редирект (302-й статус и потом загрузку ptsecurity.com) и сплитинг (заголовок custom header).

    Теперь по шагам:

    1. Создаем страницу с формой:

    <form action="http://example.com/modules/mod_template/set.php" method="POST">
    <textarea cols="100" rows="10" name="back">http://www.ptsecurity.com/
     Custom-Header: Test</textarea><br/>
    <input type="submit">
    </form>
    

    2. Заходим на страницу в IE и отправляем запрос.

    Результат выполнения запроса:

    image

    Рис. 4.3

    image

    Рис. 4.4

    На рис. 4.4 видно, что помимо перенаправления был установлен заголовок Custom-Header со значением Test.

    SQL Injection


    Рассмотрим еще один пример уязвимости, обнаруженной при помощи AI. Согласно результатам сканирования, в InstantCMS возможно внедрение SQL-кода (SQL Injection), да еще и в различных вариантах.

    image

    Рис. 5.1. Фрагмент отчета PT AI. Однотипные SQL-инъекции — и подробная информация об одной из них

    Помимо определения уязвимого фрагмента кода и родительской уязвимости в приложении, PT AI выдает необходимые условия для проведения атаки.

    На рис. 5.1 видно, что для эксплуатации SQL Injection требуются несколько условий, одно из которых — наличие в сессии вектора атаки. Это признак межмодульных уязвимостей (Second Order SQL Injection, хранимых XSS). У таких багов данные попадают в уязвимую функцию не сразу из переменных от точек входа, а из каких-то промежуточных хранилищ — базы, сессий и т. п., где они до этого каким-то образом оказались.

    Эксплуатация межмодульных уязвимостей происходит в несколько этапов. Например, для хранимой XSS данные одним запросом заносятся в СУБД, а вторым запросом — извлекаются оттуда и чем-то выводятся на страницу.

    image

    Рис. 5.2. Схема эксплуатации хранимых XSS

    Продемонстрируем эксплуатацию найденной уязвимости Second Order SQL Injection в условиях, которые позволяют злоумышленнику изменять значения переменных в сессии. Возьмем простейший пример — виртуальный хостинг с общим хранилищем сессий. У хостинга есть ошибка конфигурации — значение директивы PHP session.save_path, которое по умолчанию равно /tmp (подробности).

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

    Для этого необходимо:

    1. Создать файл сессий с вектором для SQL Injection.

    2. Сделать запрос с cookie, соответствующим файлу сессии из п. 1, к странице InstantCMS, при генерации которой вектор из сессии попадет в SQL-запрос.

    Пример PHP-скрипта, генерирующего файл:

    <?php
    session_start();
    $sessionSavePath = session_save_path();
    $_SESSION['user']['id'] = "1' and sleep(5)='";
    session_write_close();
    $sessionFilePath = $sessionSavePath . '/sess_'. session_id();
    $output =
    	'session id: ' . session_id() ."\n" .
    	'session file: '. $sessionFilePath . "\n" . 
    	'chmod result: ' . var_export(chmod($sessionFilePath, 0755), TRUE) . "\n" .
    	"file: \n\n" . file_get_contents($sessionFilePath) . "\n";
    echo '<pre>' . $output . '</pre>';
    ?>
    

    Атака проходит в два этапа:

    Сначала запускается скрипт, который создает файл с вектором и выводит значение для cookie сессии.

    image

    Рис. 5.3. Пример файла с вектором для SQL Injection в InstantCMS

    Затем отправляется следующий запрос на сайт с InstantCMS:

    GET /admin/index.php HTTP/1.1
    Host: victim
    Cookie: PHPSESSID=session
    Connection: close
    

    Ответ сервера будет получен примерно через 5 секунд для вектора с sleep(5), что подтвердит наличие SQL Injection.

    Стоит подчеркнуть еще пару моментов:

    • Описанный сценарий атаки не сработал бы в случае, если бы в коде InstantCMS разработчики устанавливали значение session.save_path, которое бы отличалось от значения для сайта атакующего, и права на директорию с сессиями не давали получать список файлов, читать, изменять их и создавать свои.
    • Иногда встречаются баги с инъекцией в сессию (1, 2) — как в самом PHP, так и в коде приложений.


    Уязвимость SQL Injection позволяет провернуть множество нехороших фокусов, от чтения содержимого таблиц БД до заливки на сервер веб-шелла, это наиболее опасный вид атаки среди рассмотренных в данной статье. Об ошибках управления сессиями можно почитать в презентации на ZeroNights, где показывали похожий случай ошибки управления сессиями применительно к CMS.

    На этом с InstantCMS — все. Исследование уязвимостей в других системах с открытым кодом мы продолжим в следующих материалах.
    Метки:
    • +12
    • 9,8k
    • 7
    Positive Technologies 462,97
    Компания
    Поделиться публикацией
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 7
    • +1
      Начинание хорошее. Сколько систем сейчас проанализированно уже (и какие)? Планируете ли проверять плагины wordpress? Если да, то какие?
      • 0
        Думаю, посыл статьи такой — «Смотрите, как крут наш продукт. Покупайте.»

        Никто не будет делать подробный анализ по каждой небольшой системе. Копнули лидеров рынка, проанализировали, развернуто показали. Тут очень напрашиваются параллели с блогом другой компании, тоже разрабатывающей средства анализа исходного кода: habrahabr.ru/company/pvs-studio/blog/
        • +1
          (1) "Смотрите, как крут наш продукт" — да, мы действительно пишем в своём блоге про свой крутой продукт, а не про ваш. Ведь про ваш продукт мы ничего не знаем. Было бы нечестно писать о том, чего не знаешь.

          (2) "Никто не будет делать подробный анализ по каждой небольшой системе" — нет, размер системы не влияет на решение об анализе. Влияет тот, кто заказывает исследование безопасности.

          (3) "Копнули лидеров рынка" — нет, мы исследовали более 150 различных CMS в течение долгого времени. Было бы наивно думать, что это сделано только ради публикации в блоге. Кроме того, внимательный читатель нашего блога может заметить, что мы рассказываем о наиболее интересных *уязвимостях*, а вовсе не о лидерах *рынка*.

        • 0
          Всего в данном проекте исследовано более 150 различных CMS. Конечно, в первую очередь постараемся рассказать о популярных системах, потому что их уязвимости задевают большое число пользователей. В частности, в следующих выпусках будут Jumla, Shopos, Yii и Jahia. Про плагины Wordress отдельный материал будет тоже.
          • 0
            Извините, опечатка. Вместо Jumla следует читать Joomla. А если совсем точно, то Joomla!
        • 0
          Эта система какие языки способна анализировать? Только PHP?
          • +1
            PHP конечно же велик и на нём 80% Интернета. Но наш анализатор поддерживает и другие языки.

            Конкретно, версия Web FrontEnd ориентированна на PHP, Java (с массой фреймворков), .NET, JavaScript, HTML 5.0, SQL. А скоро будут другие версии: ERP, Mobile и ещё.

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое