Node Hero — руководство по безопасности Node.js

В последнее время почти каждую неделю мы видим новости о какой-нибудь серьёзной бреши в безопасности — чего стоят только LinkedIn и MySpace. В ходе атак произошла утечка большого количества пользовательских данных и, как следствие, пострадала репутация компании. Изучение проблем безопасности также показало, что в некоторых отраслях тикеты к багам открыты в среднем по 18 месяцев.

Эту ситуацию необходимо исправить. Если вы разрабатываете программное обеспечение, забота о безопасности — часть вашей работы.

Правила безопасного кода

Правило 1: не используйте eval

Функция eval() может сделать ваше приложение уязвимым для инъекций произвольного кода. Постарайтесь не использовать её, но если это всё-таки необходимо, никогда не передавайте чистый пользовательский ввод в eval().

Правило 2: всегда используйте режим «use strict»

С use strict вы можете использовать строгий «вариант» JavaScript. Это позволяет выявлять некоторые скрытые ошибки и отображать их.

'use strict'  
delete Object.prototype 
// ошибка ввода
var obj = {  
    a: 1, 
    a: 2 
} 
// синтаксическая ошибка

Правило 3: обрабатывайте ошибки аккуратно

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

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

Правило 4: делайте статический анализ кода

Статический анализ кода вашего приложения поможет отловить большое количество ошибок. Для этого рекомендуется использовать ESLint вместе с Standard code style.

Правило 5: не запускайте процессы с правами суперпользователя

К сожалению, разработчики часто запускают свои приложения с правами суперпользователя, чтобы использовать порты 80 и 443.
Это неправильно. В случае ошибки или бага процесс может положить всю систему, поскольку ему предоставлен доступ ко всем её возможностям.

Вместо этого вы можете настроить HTTP-сервер или прокси для перенаправления запроса. Это может быть nginx или Apache. Чтобы узнать больше, можете ознакомиться со статьёй Operating Node.js in Production.

Правило 6: настройте обязательные HTTP-заголовки

Существуют несколько относящихся к безопасности HTTP-заголовков, которые стоит установить:

  • Strict-Transport-Security делает обязательным безопасные (HTTP через SSL/TLS) соединения с сервером;
  • X-Frame-Options предоставляет защиту от кликджекинга;
  • X-XSS-Protection включает фильтр межсайтового скриптинга (XSS), встроенный в большинство современных браузеров;
  • X-Content-Type-Options предотвращает MIME-сниффинг ответа без декларированного Content-Type;
  • Content-Security-Policy предотвращает широкий спектр атак, включая XSS и другие межсайтовые инъекции.

В Node.js это просто сделать, используя модуль Helmet:

var express = require('express')
var helmet = require('helmet')
 
var app = express()
 
app.use(helmet())

Правило 7: корректно управляйте сессиями

Приведённые ниже флаги должны быть установлены для всех куки:

  • secure — сообщает браузеру, что нужно отправлять куки только если запрос отправляется через HTTPS;
  • HttpOnly — используется для помощи в предотвращении атак типа XSS, так как не даёт доступ к куки через JavaScript.

Правило 8: настройка ограничений для куки

Следующие флаги также должны использоваться, если вы работаете с куки:

  • domain — используется для сравнения домена, записанного в куки, и домена в URL. Если он совпадает или является субдоменом, то следующим будет проверен атрибут path;
  • path — в дополнение к domain для куки может быть задан URL. Если domain и path совпадают, куки считаются валидными и будут отправлены в запросе;
  • expires — используется для установки срока действия куки.

В Node.js вы можете запросто создавать куки, используя пакет cookies, но это достаточно низкоуровневая фича, так что скорее всего вы просто воспользуетесь оболочкой вроде 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)

Инструменты

Правило 9: поиск уязвимостей с Retire.js

Главная цель Retire.js — помочь обнаружить уязвимые версии модулей.

Просто установите его:

npm install -g retire

После этого использование команды retire позволит обнаружить уязвимости в директории node_modules.

Правило 10: аудит модулей с Node Security Platform CLI

nsp — главный командный интерфейс для Node Security Platform. Он позволяет проводить аудит package.json или npm-shrinkwrap.json, сравнивая его со списком уязвимых модулей NSP API.

npm install nsp --global
# Из директории вашего проекта
nsp check

Чтение по теме: Как защитить веб-приложение: основные советы, инструменты, полезные ссылки

Перевод статьи «Node Hero - Node.js Security Tutorial»

Подобрали три теста для вас:
— А здесь можно применить блокчейн?
Серверы для котиков: выберите лучшее решение для проекта и проверьте себя.
Сложный тест по C# — проверьте свои знания.

Также рекомендуем: