Корпоративные порталы
Решение задач консолидации компании, повышение эффективности работы и исполнительской дисциплины, автоматизация Бизнес-процессов с помощью Интранет-портала.
Корпоративные сайты
Решение задач узнаваемости бренда, повышения лояльности клиентов и увеличения продаж с помощью современного корпоративного сайта.
Интернет-магазины
Организация онлайн-продаж, интеграция с учётными системами, механизмы стимулирования продаж и повышения эффективности маркетинга.

Трактовка результатов сканера безопасности

27.10.2013

С момента запуска сканера безопасности в версии security 12.5.0 прошло около полу года. За это время его рекомендации увидело около 12к+ сайтов (суммарно более 50к проверок). Увы, как показывает статистика подавляющее большинство либо игнорирует его рекомендации, либо не знает, что с ними делать. Именно поэтому я решил более детально описать тесты и каким образом трактовать их результаты. Я постараюсь описать лишь наиболее часто встречающиеся угрозы или угрозы, вызывающее наибольшее количество вопросов. Осторожно, ниже обильное количество  хардкора.

Локальное сканирование
Как вы знаете из предыдущего поста Сканер безопасности - верный друг и помощник. Сканер разделен на две части - локальную и внешнюю. Локальная - ответственна за проверки, которые невозможно/нецелесообразно выполнить “снаружи”, например, настройки сайта или исполнение php/python/perl/etc скриптов в директории хранения загружаемых файлов гораздо эффективнее проверять именно изнутри. Все проверки сгруппированы по типу (настройки окружения, настройки php, настройки сайта и т.д.), поэтому предлагаю начать по порядку:)

Настройки окружения
  • Директория временных файлов php доступна для всех системных пользователей
    Вы можете лицезреть сообщение об этой угрозе, когда директория хранения временных файлов php (upload_tmp_dir, по умолчанию /tmp) доступна для всех (other), например:
    $ stat -c 'Perms: %A' /tmp
    Perms: drwxrwxrwt
    Если вы пользуетесь shared-хостингом - это хороший повод задать ему вопрос и потребовать внести правки в конфигурацию, таким образом дабы временные файлы каждого пользователя были отделены друг от друга, и на эти директории были установлены корректные файловые права. Пользователям выделенных серверов это менее критично, но все же рекомендовано, причем что у вашего администратора это займет не более 10 минут времени;)
  • Директория хранения файлов сессий доступна для всех системных пользователей
    Аналогично предыдущей проблеме, за исключением настройки, на которую стоит обратить внимание: session.save_path
    Если вы не используете хранение сессий в БД и пользуетесь shared-хостингом, то в большинстве случаев ваш “сосед” сможет получить полный доступ к вашему сайту, модифицировав сессионные данные.
  • Предположительно в директории хранения сессий находятся сессии других проектов
    Подобное сообщение можно встретить, если несколько сайтов используют одну директорию для хранения сессий. Очень часто это можно встретить при использовании выделенных серверов, когда есть N сайтов и все они хранят свои сессии где-нить в /tmp/php_sess. Начиная с версии main 12.5.0 это стало не столь критично, но тем не менее стоит это исправить указав собственную директорию хранения сессий для каждого сайта. Чем это опасно? При такой конфигурации сессии получаются “сквозные”, т.е., допустим, есть сайт A и сайт B:
    a) Мы регистрируемся на сайте B, получаем ID пользователя 7;
    b) Теперь зайдя на сайт A с ID сессии от сайта B, мы окажемся авторизованными под пользователем с ID 7, но сайта A, улавливаете?:) А что если пользователь с ID 7 на сайте A администратор?
  • PHP/Python/Perl/etc скрипты исполняются в директории хранения загружаемых файлов
    Используя API Битрикс, пользователь сайта не может загрузить .php, .py, .psp, .pl и т.д. файлы без наличия необходимых прав. Но к сожалению, как в пользовательском коде, так и в коде разработчиков Маркетплейс все еще встречается “кастомная” загрузка файлов, которая может позволить загрузить файлы с потенциально опасными расширениями. Именно поэтому лучше исключить эту возможность, корректно сконфигурировав ваш веб-сервер.
  • .htaccess файлы обрабатываются Apache в директории хранения загружаемых файлов
    Аналогично предыдущему, только вектор атаки через загрузку файлов направлен на загрузку .htaccess файлов с кастомными конфигами. Например такой:
    <Files ~ "^\.ht"> 
    Order allow,deny
    Allow from all
    </Files>
    AddHandler zend-enabler-script .htaccess
    <IfModule mod_mime.c>
       AddType application/x-httpd-php .htaccess
    </IfModule>
    #<?php assert($_GET[0]); ?>
    Необходимо найти все текущие правила:
    $ find ./upload -type f -name '.htaccess' -print -exec cat {} \;
    ./upload/support/not_image/.htaccess
    Deny from all
    ./upload/.htaccess
    <IfModule mod_mime.c>
       RemoveHandler   php .php3 .php4 .php5 .php6 .phtml .pl .asp .aspx .cgi .dll .exe .ico .shtm .shtml .fcg .fcgi .fpl .asmx .pht .py .psp
       AddType text/plain   php .php3 .php4 .php5 .php6 .phtml .pl .asp .aspx .cgi .dll .exe .ico .shtm .shtml .fcg .fcgi .fpl .asmx .pht .py .psp
    </IfModule>
    <IfModule mod_php5.c>
       php_flag engine off
    </IfModule>
    Перенести их в конфигурацию виртуального хоста вашего сайта и добавить AllowOverride None для директории загружаемых файлов, например так:
       <Directory /home/bitrix/www/upload/support/not_image>
          AllowOverride none
          Order allow,deny
          Deny from all
       </Directory>
    
       <Directory /home/bitrix/www/upload>
          AllowOverride none
          AddType text/plain   php .php3 .php4 .php5 .php6 .phtml .pl .asp .aspx .cgi .dll .exe .ico .shtm .shtml .fcg .fcgi .fpl .asmx .pht .py .psp
          php_value engine off
       </Directory>
    
  • Apache Content Negotiation разрешен в директории хранения загружаемых файлов
    Суть проблемы заключается в том, что в конфигурации Apache по умолчанию можно встретить такую строку:
    AddHandler type-map .var
    Это означает, что если в директории загружаемых файлов у вас будет лежать файл с именем test.var.gif и содержимым:
    GIF89: any 
    Content-language: ru
    Content-type: text/html;
    Body:----------ru--
    <img src=x onerror=prompt(/XSS/)>
    ----------ru--
     
    (вполне валидная картинка по мнению PHP!), то при запросе этого файла нам будет отдано тело с типом text/html, что логично, т.к. обработчики в Apache вызываются до определения типа:
    $ http -v http://bus-win.my/upload/test.var.gif
    GET /upload/test.var.gif HTTP/1.1
    Accept: */*
    Accept-Encoding: gzip, deflate, compress
    Host: bus-win.my
    User-Agent: HTTPie/0.7.2
    
    
    
    HTTP/1.1 200 OK
    Accept-Ranges: bytes
    Content-Language: ru
    Content-Length: 34
    Content-Type: text/html
    Date: Sun, 27 Oct 2013 09:57:40 GMT
    Server: Apache/2.4.3 (Unix) OpenSSL/1.0.1c PHP/5.4.7
    
    <img src=x onerror=prompt(/XSS/)>
    А не как мы ожидали image/gif, что разумеется приводит к возможности XSS нападения:
    2013_10_27_154126.png
    Эта возможность придает гибкости Apache для обработки мультиязычной статики, но безопасности вашего сайта только вредит.

Настройки PHP
Еще не устали? Тогда продолжаем! По настройкам PHP зачастую не возникает вопросов, кроме двух:
  • Разрешено чтение файлов по URL (URL wrappers)
    Это разумеется один из тез пунктов, за который на меня зол не один разработчик. Но природа PHP такова, что никогда не знаешь с какой стороны получишь поддых:) И если мы хотим повысить безопасность нашего сайта - allow_url_fopen должен быть Off, дабы оградить разработчика от "сюрпризов"
  • Cookies доступны из JavaScript
    Имеется в виду, что при установке cookie ваш сайт не передает дополнительный флаг httpOnly для HTTP-заголовка Set-Cookie, который указывает на запрет чтения/записи данных Cookie посредством JavaScript, отсюда и название. Увы XSS атаки наиболее распространены, и получить пользовательские cookies это самый простой их вектор (сейчас все чаще XSS нападение используется для CSRF атак). Поэтому необходимо использовать любую возможность для уменьшения рисков. Флаг httpOnly рекомендуется указывать как минимум для ID сессии, для этого достаточно в настройках php указать:
    session.cookie_httponly = On
    Подробнее о httpOnly на OWASP: HttpOnly
    Подробнее о директиве php: session.cookie_httponly

Настройки сайта
Так же как и в случае с настройками PHP - проблем обычно не возникает, т.к. исправление обнаруженных угроз достаточно тривиально. По моему мнению требует объяснений лишь одна:
  • Ограничен список расширений исполняемых файлов
    Т.к. администратор сайта вправе изменять этот список по своему усмотрению, он может устаревать со временем (когда мы решаем добавить какое-либо расширение в список опасных, к примеру, как было с var). Сканер безопасности сообщит вам, если в вашем кастомизированном списке содержаться не все необходимые расширения.

Пользователи
Эти проверки появились только в security 14.0.3. Основная их цель - проверить все ли привилегированные пользователи используют MFA, у всех ли установлен пароль достаточной сложности и т.д. Увы, на текущий момент по политическим соображениям включена только одна:
  • У некоторых пользователей административной группы установлен слабый пароль
    Сканер безопасности берет список пользователей из административной группы и пытается подобрать пароль к ним методом перебора по словарю. В случае успеха будет выведен список пользователей, которым необходимо установить более сложный пароль. Зачастую слабый пароль у пользователей административной группы оказывается в следствии того, что изначально они небыли администраторами, т.е. административный доступ предоставляется ранее зарегистрированному пользователю, чьи политики безопасности не требовали стойкого пароля.

Внешнее сканирование

Внешнее сканирование, кажется, заслуживает отдельного поста, но я постараюсь вкратце осветить основные моменты.
  • Доступен листинг директорий
    Увы, включенный Directory AutoIndex встречается повсеместно и сулит как минимум неконтролируемым доступом к загруженным пользовательским файлам. Для nginx необходимо убрать директиву autoindex, она выглядит примерно так:
    location / {
        autoindex  on;
        ...
    }
    Для Apache это Options +Indexes, как-то так будет выглядеть в конфиге:
    <Directory /home/bitrix/www>
        Options +Indexes
    </Directory>
  • Открыт доступ к важным сервисам
    Всегда помните - все сервисы, необходимые только сайту, не должны “торчать” наружу. Увы, случаи неконтролируемого доступа к критически важным сервисам (например, memcached) - совсем не редкость. Это важный момент, т.к. доступ к memcached, где ваш сайт хранит свой кеш - это по сути полный контроль над ним. Если вы пользуетесь shared-хостингом - это отличный повод для разговора с ним:) Если у вас не кластерная архитектура проекта, то правильнее всего использовать unix-сокет, когда у вас memcached используется для кластера - корректные настройки firewall + SASL.
  • Инъекция PHP-CGI параметров из строки запроса
    Тут все достаточно просто:) Есть уязвимость в php: CVE-2012-1823
    Она позволяет как читать файлы вашего сайта ( /some_script.php?-s ), так и в большинстве случаев исполнять произвольный php код в контексте вашего сайта. Рекомендуется незамедлительно обновить версию php, либо не использовать php-cgi вовсе
  • Неправильно сконфигурирована связка Nginx + php-fpm
    Сколько не бейся над этой темой, но в интернете все еще достаточно много ужасных HowTo’шек по настройке связки nginx + php-fpm, в которых ни слова не сказано о том, что php-fpm с конфигами по умолчанию и локейшн в nginx примерно следующего содержания:
    location ~* \.php$ {
      fastcgi_pass backend;
      ...
    }
    позволит злоумышленнику интерпретировать любой файл как php скрипт. К примеру, обратившись к аватару пользователя таким образом: /upload/main/f6f/photo.jpg/some.php, злоумышленник выполнит php код содержащийся в аватаре (например в EXIF или конце PNG). Наиболее распространенными вариантами решения является либо указание в php.ini (если это удовлетворяет требованиям вашего проекта):
    cgi.fix_pathinfo=0
    , либо корректно сконфигурировать nginx, учитывая особенности вашего проекта
  • Открыт доступ к служебным "статус" страницам
    Так называемые статус-страницы позволяют злоумышленнику получить дополнительную информацию о вашем сайте, которая им столь нужна. Не стоит их радовать, ограничив доступ к ним (а лучше отключив/закрыв авторизацией, т.к. доверять localhost так же не стоит). Наиболее распространенные:
    Apache mod_status. Например: http://apache.org/server-status
    И PHP-FPM Status Page (pm.status-path)
  • Найдены временные файлы
    При редактировании файлов на сервере по SSH или при использовании DCVS могут создаваться временные копии текущих файлов, в которых может содержаться важная информация (например, все еще актуальные данные о подключении к БД). Внешнее сканирование отобразит вам список всех таких файлов, которые необходимо удалить и понять причину их появления. Так же, возможно, стоит ограничить доступ к таким файлам на уровне веб-сервера.
  • Найдены опасные файлы
    Так же достаточно часто встречаются сайты на которых остались какие-то файлы после отладки, установки и т.д. Например: bitrixsetup.php, bx_1c_import.php, restore.php, log.txt и т.д. Внешнее сканирование сообщит вам список найденных файлов, которые в обязательном порядке (!) необходимо удалить.
  • Доступны настройки PhpMyAdmin
    Еще одна частая проблема - доступны настройки PhpMyAdmin (папочка setup в новых версиях). Увы, они как минимум позволяют прочесть текущую конфигурацию PhpMyAdmin + в них постоянно находятся новые уязвимости. Внешнее сканирование сообщит вам, куда нужно смотреть;)
  • Публичный доступ к файлам контроля версий
    Как ни странно - публичный доступ к служебным каталогам DCVS все еще достаточно актуальное явление. Зачастую это крайне опасно для вашего сайта - необходимо в срочном порядке закрыть доступ к таким каталогам (.git, .hg, .bzr и т.д.) и к файлам игнорирования (.gitignore, .hgignore и т.д.). В идеале необходимо пользоваться экспортом в вашей DCVS. Разумеется, внешнее сканирование сообщит вам куда необходимо смотреть:)
  • Проверяемый сайт отвечает на хост по умолчанию
    Это пожалуй одна из самых распространенных ошибок конфигурации для выделенных серверов. Суть проблемы заключается в том, что сайт отвечает на любой Host в заголовке запроса, в следствие чего, например, если $_SERVER["HTTP_HOST"] попадет в кеш компонента, то получаем классический content spoofing.
    Проверить очень легко, запрашиваем наш сайт с правильным хостом:
    $ http -v head some.info
    HEAD / HTTP/1.1
    Accept: */*
    Accept-Encoding: gzip, deflate, compress
    Host: some.info
    User-Agent: HTTPie/0.6.0
    
    
    
    HTTP/1.1 200 OK
    Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
    Connection: keep-alive
    Content-Encoding: gzip
    Content-Type: text/html; charset=windows-1251
    Date: Fri, 25 Oct 2013 06:57:31 GMT
    Expires: Thu, 19 Nov 1981 08:52:00 GMT
    P3P: policyref="/bitrix/p3p.xml", CP="NON DSP COR CUR ADM DEV PSA PSD OUR UNR BUS UNI COM NAV INT DEM STA"
    Pragma: no-cache
    Server: nginx/1.2.6
    Set-Cookie: PHPSESSID=vp93uc1j3avoibvfkusn5p6gc5; path=/; HttpOnly
    X-Frame-Options: SAMEORIGIN
    X-Powered-CMS: Bitrix Site Manager (a0b80388d20et47833773cf8f6b7c738)
    А теперь с произвольным:
    $ http -v head some.info 'Host: batman.inc'
    HEAD / HTTP/1.1
    Accept: */*
    Accept-Encoding: gzip, deflate, compress
    Host:  batman.inc
    User-Agent: HTTPie/0.6.0
    
    
    
    HTTP/1.1 200 OK
    Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
    Connection: keep-alive
    Content-Encoding: gzip
    Content-Type: text/html; charset=windows-1251
    Date: Fri, 25 Oct 2013 06:57:35 GMT
    Expires: Thu, 19 Nov 1981 08:52:00 GMT
    P3P: policyref="/bitrix/p3p.xml", CP="NON DSP COR CUR ADM DEV PSA PSD OUR UNR BUS UNI COM NAV INT DEM STA"
    Pragma: no-cache
    Server: nginx/1.2.6
    Set-Cookie: PHPSESSID=55up92i9r2sorg24j78lud9li2; path=/; HttpOnly
    X-Frame-Options: SAMEORIGIN
    X-Powered-CMS: Bitrix Site Manager (a0b80388d20et47833773cf8f6b7c738)
    Если мы видим одинаковый контент отданный для правильного и произвольного хоста - у нас неправильно сконфигурирован веб-сервер. Для решения этой угрозы, например, в nginx достаточно добавить ПЕРВЫМ сервер с перенаправлением на основной домен. Подробнее в документации nginx
  • Найден phpinfo()
    Честно говоря, я этого искренне не понимаю, но с завидным постоянством вижу на сайтах файлы x.php, pi.php, phpinfo.php и т.д. с выводом phpinfo(). Не надо так! Внешнее сканирование укажет список таких файлов, которые необходимо удалить и впредь использовать встроенную в Битрикс админскую страницу с выводом phpinfo()
  • Включен Automatic MIME Type Detection для Internet Explorer
    По умолчанию в Internet Explorer включен mime-сниффинг (MIME Type Detection in Windows Internet Explore, IE8 Security Part VI: Beta 2 Update), что никак не идет на пользу безопасности пользователей вашего сайта. В двух словах, если в заголовке ответа Content-Type сказано "text/plain," "application/octet-stream,", он отсутствует либо пуст - IE сам решает какой тип у контента основываясь, на его содержимом. Благо начиная с IE8 этим поведением можно управлять при помощи заголовка X-Content-Type-Options.
    Самый простой пример эксплуатации этого - загрузка файла без расширения. Допустим, у нас есть скрипт позволяющий загружать только картинки, но сохраняющий их без расширения...
    1. Загружаем через него файл test.gif с содержимым:
    GIF89
    <html>
    <script>
        prompt('XSS on ' + document.domain);
    </script>
    </html>
    2. Т.к. это вполне валидная картинка с позиции PHP, она благополучно попадет на сервер, но сохранится без расширения (по условиям примера). Допустим будет доступна по адресу: http://192.168.1.185:8080/upload/test
    3. Для начала проверяем как его обработает IE10 с включенным mime-сниффингом:
    $ http head http://192.168.1.185:8080/upload/test
    HTTP/1.1 200 OK
    Accept-Ranges: bytes
    Connection: keep-alive
    Content-Length: 80
    Content-Type: application/octet-stream
    Date: Sun, 27 Oct 2013 12:14:45 GMT
    ETag: "526d026b-50"
    Last-Modified: Sun, 27 Oct 2013 12:09:15 GMT
    Server: nginx/1.4.3
    Т.к. тип отдаваемого контента application/octet-stream (по умолчанию, регулируется директивой default_type), IE включает mime-сниффинг, и мы видим, что наша “картинка” была обработана как html-код:
    2013_10_27_152021.png
    4. А теперь с заголовком "X-Content-Type-Options: nosniff".
    В nginx это можно сделать через add_header:
    add_header X-Content-Type-Options nosniff;
    Проверяем:
    $ http head http://192.168.1.185:8080/upload/test
    HTTP/1.1 200 OK
    Accept-Ranges: bytes
    Connection: keep-alive
    Content-Length: 80
    Content-Type: application/octet-stream
    Date: Sun, 27 Oct 2013 12:18:21 GMT
    ETag: "526d026b-50"
    Last-Modified: Sun, 27 Oct 2013 12:09:15 GMT
    Server: nginx/1.4.3
    X-Content-Type-Options: nosniff
    И видим, что IE теперь предлагает нам сохранить этот файл:
    2013_10_27_152255.png

На этом пожалуй все:) Я постарался осветить основные моменты, далеко не все, но наиболее часто встречающиеся. В скором времени набор тестов во внешнем сканировании будет еще расширен.


Возврат к списку



 
ФИО:*
Телефон:
E-mail:*
Компания:
Комментарий:
ТЗ/Бриф:
Подтверждаю согласие на обработку персональных данных в соответствии с Политикой конфиденциальности.

* - обязательные поля обязательные поля

 
ФИО:*
Телефон:
E-mail:*
Компания:
Комментарий:
Файл:
Интересующий проект:*
Подтверждаю согласие на обработку персональных данных в соответствии с Политикой конфиденциальности.

* - обязательные поля обязательные поля