Перейти к содержанию

Лучшие практические методы для рабочей среды: Защита

Обзор

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

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

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

Не используйте устаревшие или уязвимые версии Express

Версии Express 2.x и 3.x больше не поддерживаются. Проблемы, связанные с защитой и производительностью в этих версиях, не будут подлежать решению. Не используйте эти версии!

Использование TLS

Если ваше приложение предназначено для работы с чувствительными данными или для их передачи, для защиты соединения и данных необходимо использовать криптографический протокол Transport Layer Security (TLS). Данная технология позволяет шифровать данные до передачи с клиента на сервер, тем самым обеспечивая защиту от многих распространенных (и простых) способов несанкционированного доступа. Хотя запросы Ajax и POST могут казаться неочевидными и "скрытыми" в браузерах, инициируемая ими передача данных в сети является уязвимой для незаконного сбора и анализа пакетов и атак посредника (атак "человек посередине").

Возможно, вам знаком криптографический протокол Secure Socket Layer (SSL). SSL является предшественником TLS. Другими словами, если раньше вы пользовались SSL, пора переходить к TLS. В целом, для работы с TLS мы рекомендуем использовать сервер Nginx. Подробные инструкции по настройке TLS на Nginx (и на других серверах) можно найти в разделе Рекомендуемые конфигурации серверов (Mozilla Wiki).

Кроме того, удобным инструментом для получения бесплатного сертификата TLS является Let's Encrypt - бесплатная, автоматическая и открытая сертификатная компания (CA), предоставленная корпорацией Internet Security Research Group (ISRG).

Использование Helmet

Helmet помогает защитить приложение от некоторых широко известных веб-уязвимостей путем соответствующей настройки заголовков HTTP.

Helmet, по сути, представляет собой набор из девяти более мелких функций промежуточной обработки, обеспечивающих настройку заголовков HTTP, связанную с защитой:

  • csp задает заголовок Content-Security-Policy для предотвращения атак межсайтового скриптинга и прочих межсайтовых вмешательств.
  • hidePoweredBy удаляет заголовок X-Powered-By.
  • hpkp добавляет заголовки Public Key Pinning для предотвращения атак посредника (атак "человек посередине") с поддельными сертификатами.
  • hsts задает заголовок Strict-Transport-Security, принудительно активирующий защиту соединений с сервером (по протоколу HTTP с использованием SSL/TLS).
  • ieNoOpen задает заголовок X-Download-Options для IE8+.
  • noCache задает заголовок Cache-Control и заголовки Pragma для отключения кеширования на стороне клиента.
  • noSniff задает заголовок X-Content-Type-Options для защиты браузеров от прослушивания (сниффинга) MIME ответов с отличным от объявленного типом содержимого (content-type).
  • frameguard задает заголовок X-Frame-Options для защиты от кликджекинга.
  • xssFilter задает заголовок X-XSS-Protection для активации фильтра XSS (фильтра межсайтового скриптинга) в большинстве современных веб-браузеров.

Установите Helmet, как обычный модуль:

1
$ npm install --save helmet

Затем используйте его в своем коде:

1
2
var helmet = require('helmet');
app.use(helmet());

Как минимум, отключите заголовок X-Powered-By

Если использовать Helmet не нужно, как минимум, отключите заголовок X-Powered-By. Злоумышленники могут использовать этот заголовок (включенный по умолчанию) для выявления приложений на базе Express и активации целенаправленных атак.

Поэтому рекомендуется отключить данный заголовок с помощью метода app.disable().

1
app.disable('x-powered-by');

Если вы используете helmet.js, это будет сделано автоматически.

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

Существует два основных сеансовых модуля cookie для промежуточной обработки:

  • Модуль express-session, заменяющий собой промежуточный обработчик express.session, встроенный в Express 3.x.
  • Модуль cookie-session, заменяющий собой промежуточный обработчик express.cookieSession, встроенный в Express 3.x.

Основное различие между этими двумя модулями состоит в способе сохранения сеансовых данных cookie. Промежуточный обработчик express-session сохраняет данные о сеансе на сервере; в самом файле cookie сохраняется только ИД сеанса, но не данные сеанса. По умолчанию, используется хранилище в оперативной памяти, но данный способ не предназначен для рабочей среды. В рабочей среде необходимо настроить масштабируемое хранилище сеансов; см. список совместимых хранилищ сеансов.

Промежуточный обработчик cookie-session, в отличие от описанного выше, реализует хранение на основе файлов cookie: выполняется полная сериализация сеанса в файл cookie, вместо того, чтобы сохранять только ключ сеанса. Этот способ следует использовать только при условии, что данные сеанса имеют относительно небольшой объем и легко могут быть преобразованы в элементарные значения (а не объекты). Хотя браузеры должны поддерживать не менее 4096 байт на каждый файл cookie, позаботьтесь о том, чтобы не допустить превышения данного ограничения. Размер не должен превышать 4093 байт на каждый домен. Кроме того, помните о том, что данные cookie являются видимыми для клиента, поэтому, если по какой-либо причине их следует защитить или скрыть, остановите свой выбор на модуле express-session как на более подходящем.

Использование имен сеансовых cookie, предлагаемых по умолчанию, может сделать ваше приложение уязвимым для разного рода атак. В данном случае возникает та же проблема с безопасностью, что и при использовании заголовка X-Powered-By: потенциальный злоумышленник может воспользоваться им для идентификации на сервере и организации целенаправленных атак.

Для того чтобы избежать такой проблемы, используйте обобщенные имена cookie; например, при использовании промежуточного обработчика express-session:

1
2
3
4
5
6
7
8
var session = require('express-session');
app.set('trust proxy', 1); // trust first proxy
app.use(
    session({
        secret: 's3Cur3',
        name: 'sessionId',
    })
);

Для обеспечения защиты необходимо настроить следующие опции защиты файлов cookie:

  • secure - обеспечивает отправку файлов cookie браузером только с использованием протокола HTTPS.
  • httpOnly - обеспечивает отправку cookie только с использованием протокола HTTP(S), а не клиентского JavaScript, что способствует защите от атак межсайтового скриптинга.
  • domain - указывает домен cookie; используется для сравнения с доменом сервера, на котором запрашивается данный URL. В случае совпадения выполняется проверка следующего атрибута - пути.
  • path - указывает путь cookie; используется для сравнения с путем запроса. Если путь и домен совпадают, выполняется отправка cookie в запросе.
  • expires - используется для настройки даты окончания срока хранения для постоянных cookie.

Ниже приведен пример с использованием промежуточного обработчика cookie-session:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
var session = require('cookie-session');
var express = require('express');
var app = express();

var expiryDate = new Date(Date.now() + 60 * 60 * 1000); // 1 hour
app.use(
    session({
        name: 'session',
        keys: ['key1', 'key2'],
        cookie: {
            secure: true,
            httpOnly: true,
            domain: 'example.com',
            path: 'foo/bar',
            expires: expiryDate,
        },
    })
);

Обеспечение защиты зависимостей

Для управления зависимостями приложения удобно использовать многофункциональный инструмент npm. Но пакеты, с которыми вы работаете, могут обладать критическими уязвимостями защиты, которые также могут повлиять на ваше приложение. Надежность защиты вашего приложения определяется именно надежностью "самого слабого звена" среди зависимостей.

Для того чтобы обеспечить защиту используемых вами сторонних пакетов, используйте один или оба инструмента: nsp и requireSafe. Эти два инструмента выполняют, в основном, одни и те же функции.

nsp - это инструмент командной строки, выполняющий проверку согласно базе данных уязвимостей Node Security Project и определяющий, используются ли вашим приложением пакеты с известными уязвимостями. Установите данный инструмент следующим образом:

1
$ npm i nsp -g

Воспользуйтесь этой командой, чтобы передать файл npm-shrinkwrap.json на проверку в nodesecurity.io:

1
$ nsp audit-shrinkwrap

Воспользуйтесь этой командой, чтобы передать файл package.json на проверку в nodesecurity.io:

1
$ nsp audit-package

Ниже показано, как используется requireSafe для проверки модулей Node:

1
2
3
$ npm install -g requiresafe
$ cd your-app
$ requiresafe check

Дополнительные замечания

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

  • Введите ограничение скорости передачи данных во избежание атак методом грубого подбора сочетаний символов для идентификации. Для реализации стратегии ограничения скорости передачи данных можно воспользоваться Шлюзом API StrongLoop. В качестве альтернативы, можно использовать промежуточный обработчик, например, express-limiter, но для этого придется внести некоторые изменения в код.
  • Используйте промежуточный обработчик csurf для защиты от подделки межсайтовых запросов (CSRF).
  • Всегда применяйте фильтрацию и очистку пользовательского ввода в целях защиты от атак межсайтового скриптинга (XSS) и ввода ложных команд.
  • Обеспечьте защиту от атак внедрения SQL-кода с помощью параметризованных запросов или подготовленных операторов.
  • Используйте инструмент sqlmap с открытым исходным кодом для выявления уязвимостей к внедрению SQL-кода в приложение.
  • Используйте инструменты nmap и sslyze для проверки конфигурации шифров, ключей и повторных согласований SSL, а также действительности сертификата.
  • Используйте safe-regex, чтобы убедиться в невосприимчивости регулярных выражений к атакам отказа в обслуживании регулярных выражений.

Избегайте прочих известных уязвимостей

Следите за рекомендациями Node Security Project, касающимися Express или других модулей, используемых вашим приложением. В целом, Node Security Project - это непревзойденный ресурс, предоставляющий ценные знания и инструменты, связанные с безопасностью Node.

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