Контрольный список безопасности Nodejs

Node.js Безопасность

Примечание редактора: эта статья была переведена Аримой на платформе перевода Zhongcheng.

Безопасность нельзя игнорировать,Каждый разработчик знает, что это важно, но мало кто относится к этому серьезно. Мы в RisingStack хотим, чтобы вы отнеслись к этому серьезно — вот почему мы составили этот список, чтобы помочь вам: ваше приложение должно пройти проверку безопасности, прежде чем его смогут использовать тысячи пользователей.

Большая часть этого списка является общей и применима не только к Node.js, но и к другим языкам и фреймворкам, только некоторые из методов, используемых в Node.js, указаны явно. Мы также рекомендуем вам прочитать нашу вводную статью о безопасности Node.js, а если вы только начинаете работать с Node.js, я рекомендую прочитать первую главу Node Hero.

Управление конфигурацией

Заголовок безопасности HTTP

Есть несколько заголовков HTTP о безопасности, которые должны быть на вашем сайте:

  • Strict-Transport-SecurityПринудительная замена HTTP-запросов HTTPS-запросами

  • X-Frame-OptionsПредотвратить кликджекинг

  • X-XSS-ProtectionВключить фильтрацию межсайтовых сценариев (XSS), большинство современных браузеров поддерживают этот параметр.

  • X-Content-Type-OptionsОтключите анализ браузером MIME-типа содержимого ответа, строго используйте значение Content-Type ответа.

  • Content-Security-PolicyМожет эффективно предотвращать различные атаки, включая межсайтовые сценарии и межсайтовые инъекции.

Разработчики Node.js могут использовать модуль Helmet для установки этих заголовков, код выглядит следующим образом:

var express = require('express');

var helmet = require('helmet');

var app = express();

app.use(helmet());

Фреймворки Koa и ThinkJS могут использовать koa-helmet для установки этих заголовков.Конечно, заголовков безопасности больше, чем эти.Дополнительные сведения см. в разделе HTTP-заголовки Helmet и MDN.

В большинстве архитектур эти заголовки можно задать в конфигурации веб-сервера (Apache, Nginx) без каких-либо изменений в коде приложения. Конфигурация в Nginx:

# nginx.conf

add_header X-Frame-Options SAMEORIGIN;

add_header X-Content-Type-Options nosniff;

add_header X-XSS-Protection "1; mode=block";

add_header Content-Security-Policy "default-src 'self'";

Здесь есть полный файл конфигурации Nginx, а также красивый портал.

Если вы хотите быстро проверить, есть ли на вашем сайте все необходимые заголовки, воспользуйтесь этой онлайн-проверкой.

Конфиденциальные данные клиента

При публикации клиентских приложений убедитесь, что вы никогда не включаете пароли и сертификаты API в свой код, потому что их может увидеть кто угодно.

Нет автоматического способа проверить, записаны ли в коде конфиденциальные данные, но есть два способа снизить риск раскрытия конфиденциальных данных клиентам:

  • Отправьте код с помощью запросов на включение

  • Регулярный обзор кода

Сертификация

Защита от грубой силы

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

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

var email = req.body.email;

var limit = new Limiter({ id: email, db: db });

limit.get(function(err, limit) {

});

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

var ratelimit = require('koa-ratelimit');

var redis = require('redis');

var koa = require('koa');

var app = koa();

var emailBasedRatelimit = ratelimit({

  db: redis.createClient(),

  duration: 60000,

  max: 10,

  id: function (context) {

    return context.body.email;

  }

});

var ipBasedRatelimit = ratelimit({

  db: redis.createClient(),

  duration: 60000,

  max: 10,

  id: function (context) {

    return context.ip;

  }

});

app.post('/login', ipBasedRatelimit, emailBasedRatelimit, handleLogin);

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

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

Управление сеансом

Нельзя забывать о важности безопасного использования файлов cookie: особенно в динамических веб-приложениях, которым необходимо сохранять состояние с помощью файлов cookie в протоколе HTTP без сохранения состояния.

Флаг cookie

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

  • secure- Этот атрибут указывает браузеру отправлять файлы cookie только при использовании связи HTTPS.

  • HttpOnly- Этот атрибут используется для предотвращения таких атак, как межсайтовый скриптинг. Файл cookie, который его устанавливает, не разрешает доступ через JavaScript.

Объем файлов cookie

  • domain- Это свойство используется для сравнения с доменным именем сервера, на который указывает запрошенный URL-адрес. Если доменное имя или поддомен совпадают, проверьте свойство пути.

  • path- В дополнение к имени домена также можно указать действительный URL-адрес для файла cookie. Если имя домена и путь совпадают, этот файл cookie будет отправлен вместе с запросом.

  • expires- Этот атрибут используется для установки постоянного файла cookie, до которого срок действия файла cookie не истекает.

В Node.js вы можете использовать модуль cookie для установки файлов cookie, этот модуль является более простым, вы можете использовать инкапсулированный модуль, например cookie-session.

var cookieSession = require('cookie-session');

var express = require('express');

var app = express();

app.use(cookieSession({

  name: 'session',

  keys: [

    process.env.COOKIE_KEY1,

    process.env.COOKIE_KEY2

  ]

}));

app.use(function (req, res, next) {

  var n = req.session.views || 0;

  req.session.views = n++;

  res.end(n + ' views');

});

app.listen(3000);

Примеры взяты из документации модуля cookie-session.

CSRF

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

В Node.js вы можете использовать модуль csrf для смягчения такого рода атак.Этот модуль является относительно простым, и есть несколько модулей, которые упакованы для разных фреймворков.Один из них - csurf, промежуточное программное обеспечение, используемое в экспресс-фреймворке для предотвращения CSRF-атаки.

В слое маршрутизации можно закодировать так:

var cookieParser = require('cookie-parser');

var csrf = require('csurf');

var bodyParser = require('body-parser');

var express = require('express');

// setup route middlewares

var csrfProtection = csrf({ cookie: true });

var parseForm = bodyParser.urlencoded({ extended: false });

// create express app

var app = express();

// we need this because "cookie" is true in csrfProtection

app.use(cookieParser());

app.get('/form', csrfProtection, function(req, res) {

  // pass the csrfToken to the view

  res.render('send', { csrfToken: req.csrfToken() });

});

app.post('/process', parseForm, csrfProtection, function(req, res) {

  res.send('data is being processed');

});

Токен CSRF можно использовать на уровне представления следующим образом:

<form action="/process" method="POST">

  <input type="hidden" name="_csrf" value="{{csrfToken}}">

  Favorite color: <input type="text" name="favoriteColor">

  <button type="submit">Submit</button>

</form>

Примеры взяты из документации модуля csurf.

проверка данных

XSS

Есть два похожих, но разных типа атак, от которых нужно защищаться: один — отраженный XSS, а другой — сохраненный XSS.

Светоотражающий XSSПроисходит, когда злоумышленник внедряет исполняемый код JavaScript в ответ HTML со специально созданной ссылкой.

Сохраненный XSSПроисходит, когда сохраняется несанитизированный пользовательский ввод, он запускается в браузере пользователя с разрешениями веб-приложения.

Чтобы защититься от этих атак, вам необходимо строго фильтровать пользовательский ввод.

SQL-инъекция

SQL-инъекция вводит частичные или полные SQL-запросы через пользовательский ввод, который может считывать конфиденциальную информацию или быть разрушительным.

Вот некоторые примеры:

``select title, author from books where id=$id``

Если $id поступает из пользовательского ввода, что, если пользователь введет 2 или 1=1? Оператор запроса станет таким:

``select title, author from books where id=2 or 1=1``

Самый простой способ защититься от такого типа атак — использовать параметризованные запросы или заранее написать операторы SQL.

Если вы используете PostgerSQL в Node.js, вы можете использовать модуль node-postgres. Чтобы создать параметризованный запрос, просто напишите такой код:

var q = 'SELECT name FROM books WHERE id = $1';

client.query(q, ['3'], function(err, result) {});

sqlmap — это инструмент для тестирования на проникновение с открытым исходным кодом, который автоматизируетОбнаружение эксплойтов SQL-инъекций и захват баз данныхпроцесс.

инъекция из командной строки

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

На практике, если у вас есть такая ссылка:

``https://example.com/downloads?file=user1.txt``

Он может стать:

``https://example.com/downloads?file=%3Bcat%20/etc/passwd``

В примере %3B — это транскодирование знаков препинания, таким образом можно запустить несколько команд операционной системы.

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

Все еще используя Node.js в качестве примера:

child_process.exec('ls', function (err, data) {

    console.log(data);

});

Под капотом child_process.exec вызывает /bin/sh, так что это интерпретатор bash, а не запуск программы.

Когда пользовательский ввод будет передан в это место, будут проблемы, любая обратная кавычка или $(), новая команда будет введена злоумышленником. Функция обратных кавычек состоит в том, чтобы сначала выполнить команду Linux внутри обратных кавычек, а затем присвоить результат выполнения переменной.

Эту проблему можно решить, просто используя файл child_process.execFile.

безопасная передача

SSL Version, Algorithms, Key length

HTTP — это протокол с открытым текстом, и он должен быть защищен через туннель SSL/TLS, который мы знаем как HTTPS. В настоящее время широко используются высокоуровневые шифры, и если сервер неправильно настроен, вместо него будет использоваться слабый шифр или вообще не будет шифрования.

Вам нужно протестировать:

  • Шифры, ключи и согласование протоколов настроены правильно

  • Срок действия сертификата

Использование инструментов nmap и sslyze упрощает эту задачу.

Проверить информацию о сертификате

``nmap --script ssl-cert,ssl-enum-ciphers -p 443,465,993,995 www.example.com``

Тестирование уязвимостей SSL/TLS с помощью sslyze

``./sslyze.py --regular example.com:443``

HSTS

Мы кратко коснулись этого в разделе управления конфигурацией.Strict-Transport-SecurityЗаголовок заставляет браузер и сервер использовать безопасное соединение (HTTP через SSL/TLS).Следующая конфигурация взята из Twitter:

``strict-transport-security:max-age=631138519``

Максимальный возраст здесь указывает допустимое время, в течение которого браузер должен автоматически преобразовывать HTTP-запросы в HTTPS.

Это можно легко проверить с помощью следующей команды:

``curl -s -D- https://twitter.com/ | grep -i Strict``

отказ в обслуживании

блокировка учетной записи

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

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

регулярное выражение

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

  • Использовать повторяющуюся группировку

  • Появляется в повторяющейся группе:

    • повторение

    • попеременно перекрываются

([a-zA-Z]+)*, (a+)+ или (a|a?)+ — уязвимые регулярные выражения, и простой ввод типа aaaaaaaaaaaaaaaaaaaaaaaaaa! может привести к большому количеству вычислений. Дополнительные сведения см. в разделе Регулярные выражения DOS.

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

$ node safe.js '(beep|boop)*'

true

$ node safe.js '(a+){10}'

false

Обработка исключений

Код исключения, стек трассировки ошибок

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

Стек ошибок сам по себе не является ошибкой, но часто приводит к утечке информации, представляющей интерес для злоумышленника. Плохая практика — предоставлять отладочную информацию в результате операции, вызвавшей ошибку, и вам следует распечатать эту информацию, а не выводить ее пользователю.

NPM

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

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

К счастью, в Node Security Project есть отличный инструмент, который вы можете использовать для проверки известных уязвимостей в используемых вами модулях.

npm i nsp -g

# either audit the shrinkwrap

nsp audit-shrinkwrap

# or the package.json

nsp audit-package

Вы также можете использовать requireSafe, чтобы сделать это за вас.

Snyk

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

Попробуйте snyk.io.

Final

Этот контрольный список основан на Шпаргалке по тестированию безопасности веб-приложений (поддерживается OWASP) и находится под ее сильным влиянием.

Open Web Application Security Project (OWASP) — это глобальная некоммерческая благотворительная организация, занимающаяся повышением безопасности программного обеспечения.

Еженедельник странных танцев

——————————————————

Получите представление о передовых технологиях и читайте Qiwu Weekly

Нажмите и удерживайте QR-код, чтобы подписаться на Qiwu Weekly