image
Совсем недавно в разгар рабочего дня от клиента к нам поступила тревожная информация о том, что их сайт подвергается XSS/SQL атакам, часть из которых была успешной. Необходимо было срочно принять меры и настроить базовую защиту в течение нескольких часов, т.к. возможности быстро найти и устранить несовершенства кода у разработчиков не было.

После недолгих раздумий выбор пал на firewall веб-приложений для nginx под названием naxsi, который технически является модулем nginx.Naxsi работает по принципу: всё, что не разрешено — запрещено. Каждый HTTP-запрос (GET|PUT|POST) проверяется на соответствие шаблонам запрещающих правил, заданным по-умолчанию в файле naxsi_core.rules. Данные простые правила охватывают 99% всех возможных вариантов зловредных запросов. Например по-умолчанию запрещены все запросы в URI которых содержится символ "<". Если для приложения использование такого символа необходимо для нормальной работы, то нужно вручную прописать соответствующие исключения в белый список.

Такой подход обеспечивает высокий уровень защиты, т.к. для naxsi нет такого понятия как «неизвестный тип атаки», как это может быть с другими системами защиты, которые используют при фильтрации сигнатуры известных уязвимостей. Но есть и обратная сторона медали: если разрешающие правила будут проработаны плохо, то naxsi будет блокировать еще и часть легальных запросов. Ответственность за конечный результат разработчики модуля целиком и полностью возлагают на администратора системы. С этими мыслями мы и приступили к установке модуля.

Сайт клиента работает под управлением CentOS 6. К сожалению готового пакета nginx с включенным модулем naxsi для CentOS 6 не нашлось, поэтому нужно было компилировать самостоятельно.

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

Установка из пакета:
rpm -Uvh http://rpms.southbridge.ru/southbridge-rhel6-stable.rpm
yum install -y nginx-naxsi

Добавляем nginx в автозапуск:
chkconfig nginx on

Создаем файл со стандартными запрещающимиправилами naxsi:
wget -O /etc/nginx/naxsi_core.rules https://raw.githubusercontent.com/nbs-system/naxsi/master/naxsi_config/naxsi_core.rules

Включаем стандартные запрещающие правила в конфиг nginx в контекст http:
/etc/nginx/nginx.conf
http {
     ...
     include /etc/nginx/naxsi_core.rules;
     ...
}

Создаем файл с конфигурацией naxsi:
touch /etc/nginx/my_naxsi.rules
cat << EOF >/etc/nginx/naxsi.rules
LearningMode; # режим обучения. В
SecRulesEnabled;
#SecRulesDisabled;
DeniedUrl "/RequestDenied";
include "/etc/nginx/my_naxsi.rules";
## check rules
CheckRule "$SQL >= 8" BLOCK;
CheckRule "$RFI >= 8" BLOCK;
CheckRule "$TRAVERSAL >= 4" BLOCK;
CheckRule "$EVADE >= 4" BLOCK;
CheckRule "$XSS >= 8" BLOCK;
EOF

Включаем naxsi для желаемого виртуального хоста:
server {
     ...
     set $naxsi_extensive_log 1; # отключите это когда закончите настройку
     ...
     location / {
        ...
        include /etc/nginx/naxsi.rules;
        ...
     }
     ...
     location /RequestDenied {
        return 500;   # все "плохие" запросы идут на 500
     }
     ...
}

Перезапускаем nginx:
service nginx restart

С этого момента naxsi работает в режиме обучения. Никакие запросы не блокируются, но активно записываются в errorlog для указанного виртуального хоста nginx.Чтобы не нарушить в будущем работу сайта, в режиме обучения необходимо обеспечить нагрузку сайта легитимным трафиком так, чтобы было сделано как можно больше различных запросов, которые будут возникать в обычной его работе.

После обучения, переходим к генерации исключений (whitelists) для базовых запрещающих правил. Это можно делать как вручную, так и в автоматическом режиме с помощью утилиты nx_util.py.
wget -O /tmp/naxsi.zip https://github.com/nbs-system/naxsi/archive/0.53-2.zip
unzip /tmp/naxsi.zip
rm -f /tmp/naxsi.zip
sed -i 's/\/usr\/local\/etc/\/tmp\/naxsi-0.53-2\/nx_util/' /tmp/naxsi-0.53-2/nx_util/nx_util.py
python /tmp/naxsi-0.53-2/nx_util/nx_util.py -l </путь/до/errorlog-файла> -o

Утилита парсит errorlog файл на предмет записей от NAXSI и выводит в stdout сгенерированный список исключений, отсортированный по частоте срабатываний. При этом правила из нижней части списка могут быть по-умолчанию закомментированы.
Данные сгенерированные исключения, их полнота и корректность являются основным фактором — насколько эффективно будет применяться фильтрация Naxsi. Автоматически сгенерированные правила необходимо обязательно проанализировать и при необходимости отредактировать. Разобраться в синтаксисе правил можно, изучив официальную документацию
Копируем полученные whitelist-правила в файл /etc/nginx/my_naxsi.rules.
Включаем боевой режим naxsi:
sed -i 's/LearningMode/#LearningMode/' /etc/nginx/naxsi.rules

Перезапускаем nginx:
nginx -t
service nginx reload

Базовая настройка завершена!
Если при работе модуля в боевом режиме какие-то легальные запросы все-таки оказываются неучтенными и блокируются, то нужно их добавлять в белый список в файл /etc/nginx/my_naxsi.rules. Для этого можно повторно запускать nx_util.py или научиться анализировать записи NAXSI в errorlog и писать исключения самостоятельно.
Проверить, попадают ли какие-нибудь запросы под блокировку или нет можно так:
cat </путь/до/errorlog-файла> | grep NAXSI

Вот так всего за несколько часов была организована базовая защита сайта от XSS/SQL атак. А разработчики уже без спешки продолжили устранять несовершенства в коде.

На этом всё. Спасибо за внимание!

Автор Last_Lame

Будем рады ответить на любые вопросы в личной переписке или по почте ask@centos-admin.ru

Комментарии (23)


  1. Bo0oM
    09.04.2015 13:46
    +1

    Пары часов для SQL INJ, увы, слишком много.


  1. maximw
    09.04.2015 14:21

    Как долго происходит процесс обучения? Ведь за это время злоумышленники успевают сделать довольно мнгого?
    Как потом восстанавливаете (и восстанавливаете ли) работоспособность сайта в случае повреждения БД злоумышленниками?


    1. akhaustov Автор
      09.04.2015 16:29
      +1

      Часа достаточно. Да, риск большой. Лучше, чем ничего))
      Обязательно всегда ежедневно делается бэкап, что позволяет восстановить БД.


  1. istui
    09.04.2015 14:56

    А можно поподробнее про создание собственного репозитория? В идеале хотелось бы увидеть статью на эту тему.
    При выходе обновления nginx вы пересобираете пакет вручную, или все автоматизировано?


    1. akhaustov Автор
      09.04.2015 16:27
      +1

      Сделаем отдельную статью на эту тему.
      Обновления стараемся автоматизировать.
      Кастомные пакеты приходится обновлять вручную.


      1. istui
        09.04.2015 17:59

        Было бы здорово!

        Потому что для RHEL/CentOS, увы, репозиториев, содержащий актуальный nginx с интересными модулями, практически нет…


        1. thunderspb
          13.04.2015 15:54

          Можно еще сбилдить пакет -> rpm -> puppet, например, у нас так jdk/jre живут определенных версий, да и некоторые другие сервисы.


        1. mobilesfinks
          15.04.2015 11:43

          Вот тут как бы репозиторий для актуального nginx есть. Да, может быть интересных модулей нет, но сам nginx актуален сейчас Stable версия 1.6.3 в этих репах.


          1. istui
            16.04.2015 18:36

            Мне нужен mainline с GeoIP как минимум, и рядом других модулей…

            В atomic версия stable, в ней нет ряда новых функций, которые нужны и которые есть в mainline.
            C CentALT непонятно что происходит…


            1. mobilesfinks
              16.04.2015 20:36

              По ссылке что я дал, если ниже крутануть есть раздел с репозиторием для mainline «Готовые пакеты mainline-версии»


              1. istui
                16.04.2015 21:14

                Спасибо!) Я про них в курсе, и использую уже давно там, где достаточно стандартного набора модулей.
                А вот GeoIP, к сожалению, ни в mainline-, ни в stable-пакеты на оффсайте nginx не входит…


  1. lexore
    09.04.2015 16:35
    +1

    Кстати, этот плагин может быть очень полезен, если его настроить до атаки.
    Включил плагин в режиме learning на недельку, сформировал свои правила и применил.
    Правда, потом нужно иногда просматривать логи и актуализировать список.
    А так же переводить в режим learning при выгрузке нового функционала.


    1. akhaustov Автор
      09.04.2015 17:09

      Да, все верно. Вы правы.
      Надо только посмотреть какую он может дать нагрузку.
      Это вопрос отдельного сложного теста: нужно на высоконагруженном проекте запустить и посмотреть.


  1. Chikey
    09.04.2015 19:35

    XSS атака — а что, такие бывают? Я думал никто в здравом уме не будет охотиться за пользователями когда рядом SQLi.

    Надеюсь вы клиенту объяснили что naxsi это подорожник, а они сами должны фиксить приложение?


    1. akhaustov Автор
      10.04.2015 11:46

      Всякие бывают.
      Да, клиент в курсе. Приложение пофиксил.


  1. openkazan
    10.04.2015 09:55

    а под Apache есть подобное ПО?


    1. akhaustov Автор
      10.04.2015 11:46

      Сложно сказать. Не встречал.


    1. Twost
      15.04.2015 18:17
      +1

      Для апача есть WAF, называется mod_security. Такая-же недозащита как и naxsi)


  1. xsen
    10.04.2015 11:35

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


    1. akhaustov Автор
      10.04.2015 11:46

      Примерно этим разработчики и занимались.


  1. gto
    11.04.2015 01:34
    +1

    Вы меня, конечно, извините, статья сама по себе ничего, но повод мне кажется выдуманным. Слабо представляю себе человека который, зная, что у него на сайте дыра, которая активно используется, не закроет его (сайт) сразу же на техобслуживание и не придаст ускорение девам, а будет ждать пару часов, а потом должен будет доверять непонятной надсройке на nginx-е. Не встречал еще таких.


    1. YourChief
      11.04.2015 13:24

      Подобное притягивает подобное


    1. thunderspb
      13.04.2015 16:00
      +1

      В теории — да, но, кмк, данный метод позволяет «закостылить дыры», не уводя сайт в maintenance до hotfix. IMHO идея годна. Фиг его знает сколько займет создание hotfix и накладывание его. Понятно, что случаи разные бывают.