Наденьте шляпу на свой сайт — защитите свое экспресс-приложение шлемом

Node.js Программа перевода самородков Express

Expressна основеNode.js, Это хорошая среда для создания веб-сервисов. Он очень прост в использовании, а благодаря концепции промежуточного программного обеспечения его легко настраивать и расширять. Хотя тамРазличные фреймворки для создания веб-приложений, но мой первый выбор всегда Express. Однако прямое использование Express не полностью соответствует рекомендациям по безопасности. Итак, нам нужно использовать что-то вродеhelmetмодули для повышения безопасности приложений.

развертывать

Прежде чем начать, убедитесь, что у вас установлены Node.js и npm (или yarn). Ты сможешьЗагрузите и просмотрите руководство по установке на официальном сайте Node.js..

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

Запустите следующую команду в командной строке, чтобы создать новый проект:

mkdir secure-express-demo
cd secure-express-demo
npm init -y

Выполните следующую команду, чтобы установить модуль Express:

npm install express --save

существуетsecure-express-demoСоздайте каталог с именемindex.jsфайл, добавьте следующий код:

const express = require('express');
const PORT = process.env.PORT || 3000;
const app = express();

app.get('/', (req, res) => {
  res.send(`<h1>Hello World</h1>`);
});

app.listen(PORT, () => {
  console.log(`Listening on http://localhost:${PORT}`);
});

Сохраните файл и попробуйте его, чтобы убедиться, что он работает. Выполните следующую команду, чтобы запустить службу:

node index.js

доступhttp://localhost:3000, вы должны увидетьHello World.

hello-world.png

Проверить заголовки

giphy.gif

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

curl http://localhost:3000 --include

--includeОтметьте, чтобы он выводил заголовки HTTP ответа. если он у вас не установленcurl, Вы можете использовать вашу сетевую панель вместо наиболее часто используемых инструментов разработчика браузера.

Вы можете увидеть следующие заголовки HTTP, включенные в полученный ответ:

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 20
ETag: W/"14-SsoazAISF4H46953FT6rSL7/tvU"
Date: Wed, 01 Nov 2017 13:36:10 GMT
Connection: keep-alive

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

надеть шлем

giphy.gif

Посмотрим, будем ли мы использоватьhelmetЧто случится.运行以下命令安装helmet:

npm install helmet --save

БудуhelmetДобавьте промежуточное ПО в свое приложение. правильноindex.jsВнесите следующие изменения:

const express = require('express');
const helmet = require('helmet');
const PORT = process.env.PORT || 3000;
const app = express();

app.use(helmet());

app.get('/', (req, res) => {
  res.send(`<h1>Hello World</h1>`);
});

app.listen(PORT, () => {
  console.log(`Listening on http://localhost:${PORT}`);
});

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

curl http://localhost:3000 --inspect

Новые заголовки будут похожи на следующие:

HTTP/1.1 200 OK
X-DNS-Prefetch-Control: off
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=15552000; includeSubDomains
X-Download-Options: noopen
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Content-Type: text/html; charset=utf-8
Content-Length: 20
ETag: W/"14-SsoazAISF4H46953FT6rSL7/tvU"
Date: Wed, 01 Nov 2017 13:50:42 GMT
Connection: keep-alive

Первое, что нужно отпраздноватьX-Powered-Byзаголовок отсутствует. Но сейчас появилось много новых заголовков, что они делают?

X-DNS-Prefetch-Control

Этот заголовок мало что делает для повышения безопасности. Его значениеoff, предварительная загрузка браузером DNS URL-адресов на странице отключена. Предварительная выборка DNS может повысить производительность вашего веб-сайта, согласно MDN, она можетУвеличьте скорость загрузки изображений на 5% и более. Однако включение этой функции также может вызвать проблемы с кэшем, когда пользователи посещают одну и ту же страницу несколько раз.

Аннотация: Проблема с кешем не обнаружена, если вы это понимаете, пожалуйста, оставьте сообщение

Его значение по умолчаниюoff, если вы хотите повысить производительность с его помощью, вы можете вызватьhelmet()входящий{ dnsPrefetchControl: { allow: true }}Включите предварительную загрузку DNS.

X-Frame-Options

X-Frame-OptionsПозволяет контролировать, может ли страница<frame/>,<iframe/>или<object/>например, загрузка фрейма страницы. Если вам действительно не нужно открывать страницу таким образом, полностью отключите ее со следующей конфигурацией:

app.use(helmet({
  frameguard: {
    action: 'deny'
  }
}));

Все современные браузеры поддерживаютX-Frame-Options. Вы также можете управлять им с помощью Content Security Policy, о которой речь пойдет позже.

Strict-Transport-Security

Также известный как HSTS (строго безопасный HTTP-транспорт), он используется для обеспечения того, чтобы при посещении веб-сайтов HTTPS не происходило понижение версии протокола (возврат к HTTP). Если пользователь посещает HTTPS-сайт с этим заголовком один раз, браузер гарантирует, что будущим посещениям вторичного сайта не будет разрешено использовать HTTP. Эта функция помогает защититься от атак типа «человек посередине».

Иногда вы можете увидеть это в действии, когда пытаетесь получить доступ к порталу, такому как https://google.com, находясь в общедоступном WiFi. WiFi пытается перенаправить вас на их портал, но вы зашли через HTTPSgoogle.com, и у него естьStrict-Transport-Securityзаголовок, поэтому браузер заблокирует перенаправление.

вы можете посетитьMDNилиOWASP wikiПодробнее об этом см.

X-Download-Options

Этот заголовок используется только для защиты вашего приложения от старых ошибок IE. Как правило, если вы развертываете ненадежные HTTP-файлы для загрузки, пользователи могут открывать эти файлы напрямую (без предварительного сохранения их на диск) и выполнять их непосредственно в контексте вашего приложения. Этот заголовок гарантирует, что пользователи должны загружать такие файлы локально, прежде чем получить к ним доступ, тем самым предотвращая выполнение этих файлов в контексте вашего приложения.

вы можете посетитьдокументация по шлемуа такжеСообщение в блоге MSDNПодробнее об этом см.

X-Content-Type-Options

Некоторые браузеры не используют отправку с сервера.Content-Typeчтобы определить тип файла, и используйте «обнюхивание MIME», чтобы определить тип содержимого на основе содержимого файла и выполнить файл на основе этого.

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

Установив заголовок вnosniffЭтот анализ MIME можно отключить.

X-XSS-Protection

Этот заголовок включает базовую защиту XSS в браузере пользователя. Он не может предотвратить все атаки XSS, но может защитить от основных атак XSS. Например, если браузер обнаружит, что строка запроса содержит что-то вроде<script>теги и т. д. предотвратят выполнение кода предполагаемой атаки XSS. Для этого заголовка можно установить три разных значения:0,1а также1; mode=block. Если вы хотите узнать больше о том, как выбрать режим, ознакомьтесь сX-XSS-Protectionи его потенциальные опасностиодна статья.

Обновите свой шлем

Вышеупомянутое толькоhelmetПриведены настройки по умолчанию. Кроме того, он позволяет установитьExpect-CT,Public-Key-Pins,Cache-Controlа такжеReferrer-Policyтакие как заголовки. ты сможешьhelmetДокументацияНайдите больше связанных конфигураций в .

Защитите содержимое своей веб-страницы от непреднамеренного нарушения

giphy.gif

Межсайтовый скриптинг представляет собой неумолимую угрозу для веб-приложений. Если злоумышленник сможет внедрить и запустить код в вашем приложении, последствия могут стать кошмаром для вас и ваших пользователей. Существует решение, которое может попытаться предотвратить запуск непреднамеренного кода на вашей странице:CSP(Политика безопасности контента).

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

вы можете изменитьContent-Security-PolicyЗаголовок HTTP, чтобы указать правила, или вы также можете использовать метатег, чтобы установить, когда вы не можете изменить заголовок.

Этот заголовок выглядит так:

Content-Security-Policy: default-src 'none';
    script-src 'nonce-XQY ZwBUm/WV9iQ3PwARLw==';
    style-src 'nonce-XQY ZwBUm/WV9iQ3PwARLw==';
    img-src 'self';
    font-src 'nonce-XQY ZwBUm/WV9iQ3PwARLw==' fonts.gstatic.com;
    object-src 'none';
    block-all-mixed-content;
    frame-ancestors 'none';

В этом примере вы можете видеть, что мы разрешаем получать шрифты только из нашего собственного доменного имени или fonts.gstatic.com из Google Fonts; разрешена загрузка только изображений под этим доменным именем; разрешена загрузка только неуказанных источников , но должен содержать указанныйnonceФайлы сценариев и стилей для значений. Значение nonce должно быть указано следующим образом:

<script src="myscript.js" nonce="XQY ZwBUm/WV9iQ3PwARLw=="></script>
<link rel="stylesheet" href="mystyles.css" nonce="XQY ZwBUm/WV9iQ3PwARLw==" />

Когда браузер получает HTML, он на всякий случай очищает все значения nonce, а другие скрипты не могут получить это значение и не могут добавить его на веб-страницу.

Вы также можете заблокировать весь смешанный HTTP-контент, содержащийся на HTTPS-страницах, и все<object />элементы, а путем установкиdefault-srcдляnoneчтобы отключить все, кроме изображений, таблиц стилей и скриптов. Кроме того, вы также можетеframe-ancestorsчтобы отключить фреймы.

Вы можете вручную написать эти заголовки самостоятельно, но, к счастью, в Express есть много готовых решений CSP.helmetПоддержка CSP,ноnonceВам нужно сгенерировать его самостоятельно. Я лично использую файл под названиемexpress-csp-headerмодуль.

Установите и запуститеexpress-csp-header:

npm install express-csp-header --save

для тебяindex.jsДобавьте и измените следующее, чтобы включить CSP:

const express = require('express');
const helmet = require('helmet');
const csp = require('express-csp-header');

const PORT = process.env.PORT || 3000;
const app = express();

const cspMiddleware = csp({
  policies: {
    'default-src': [csp.NONE],
    'script-src': [csp.NONCE],
    'style-src': [csp.NONCE],
    'img-src': [csp.SELF],
    'font-src': [csp.NONCE, 'fonts.gstatic.com'],
    'object-src': [csp.NONE],
    'block-all-mixed-content': true,
    'frame-ancestors': [csp.NONE]
  }
});

app.use(helmet());
app.use(cspMiddleware);

app.get('/', (req, res) => {
  res.send(`
    <h1>Hello World</h1>
    <style nonce=${req.nonce}>
      .blue { background: cornflowerblue; color: white; }
    </style>
    <p class="blue">This should have a blue background because of the loaded styles</p>
    <style>
      .red { background: maroon; color: white; }
    </style>
    <p class="red">This should not have a red background, the styles are not loaded because of the missing nonce.</p>
  `);
});

app.listen(PORT, () => {
  console.log(`Listening on http://localhost:${PORT}`);
});

Перезапустите службу, посетитеhttp://localhost:3000, вы можете увидеть абзац с синим фоном, потому что соответствующие стили были успешно загружены. А у другого абзаца нет стиля, потому что в его стиле отсутствует значение nonce.

csp-output.png

Заголовок CSP также может установить URL-адрес для сообщения о нарушениях, и вы также можете включить только режим отчетов для сбора соответствующих данных, прежде чем строго включать CSP.

ты сможешьВведение в MDN CSPПросмотрите дополнительную информацию и просмотритеВеб-сайт «Могу ли я использовать» для совместимости с CSP. Большинство основных браузеров поддерживают эту функцию.

Суммировать

giphy.gif

К сожалению, универсального решения с точки зрения безопасности не существует, и новые уязвимости появляются одна за другой. Однако вы можете легко установить эти заголовки HTTP в своем веб-приложении и значительно повысить безопасность своего приложения, почему бы и нет? Если вы хотите узнать больше о передовых методах повышения безопасности заголовков HTTP, посетите страницуsecurityheaders.io.

Если вы хотите узнать больше о передовых методах веб-безопасности, посетитеОткрытый проект безопасности веб-приложений (OWASP), который охватывает широкий спектр тем и полезных ресурсов.

Если у вас есть какие-либо вопросы или у вас есть другие инструменты для улучшения веб-приложений Node.js, свяжитесь со мной:


Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из ИнтернетаНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,внешний интерфейс,задняя часть,блокчейн,товар,дизайн,искусственный интеллектЕсли вы хотите видеть более качественные переводы, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.