Эта статья была спонсирована Codiscope . Спасибо за поддержку спонсоров, которые делают возможным использование SitePoint.
Я играл в игру под названием « Ты не знаешь, Джек» . Это пустяковая игра, заданная как игровое шоу, в котором весело проиграть. При неправильном ответе игрок получает остроумный и непочтительный выговор от хозяина игры.
Это также урок того, как мелкие детали означают разницу между пониманием чего-то правильного и ужасно неправильным.
Недавно меня попросили написать о Джеках . Я никогда не слышал об этом раньше, но мне сразу стало интересно. Видите ли, существует не так много служб, которые утверждают, что помогут вам, когда вы узнаете о том, как кодировать безопасно. Джекс хочет быть такой службой. Почти как тренер. Это никогда не спит. И ничего не стоит.
В отличие от викторины, она более прощающая. Здорово, когда вы действительно не знаете, что делаете — как я узнал, когда решил изучить новую веб-среду.
Большую часть кода для этого поста можно найти на Github . Я проверил это в Node
7.0.0
на macOS Sierra10.12.1
.
Получение хапи
Я написал много небольших приложений для NodeJS и часто обнаруживал, что Express достаточно для нужд моего веб-приложения. Но я также задавался вопросом, как лучше структурировать гораздо большее приложение. Есть варианты самоуверенного, как у Адониса , но я с ним уже хорошо знаком. Что нового я мог бы узнать, в то же время пинать шины Джека?
А потом я увидел упоминание о Хапи на домашней странице Джека .
Я открыл свой терминал, сделал новую папку проекта и установил Hapi:
yarn add hapi
Вы также можете установить Hapi, используя NPM . Я просто любитель тенденций, а пряжа чертовски быстро!
Согласно документам, сделать приложение Hapi так же просто, как:
"use strict" const hapi = require("hapi") const server = new hapi.Server() server.connection({ "port": 3000, }) server.route({ "method": "get", "path": "/", handler: function (request, reply) { reply("hello world") }, }) server.start(err => { if (err) { throw err } console.log("server at " + server.info.uri) })
Это из index.js
.
Если вы использовали Express, это должно показаться вам знакомым. Я создал новый HTTP-сервер с одним маршрутом. Когда браузер запрашивает /
, этот маршрут ответит hello world
:
Подключить
Следующим шагом было подключение моей учетной записи Github к Джеку. Создать учетную запись Jacks было довольно легко и бесплатно. Сначала я создал новый проект:
… А затем я подключил свою учетную запись Github (и репозиторий проекта) к Jacks:
Все это заняло около 2 минут, от начала до конца.
Ошибаясь
Теперь пришло время посмотреть, насколько полезным может быть Джек. Я собрал список распространенных ошибок безопасности веб-приложения и решил попробовать несколько, чтобы посмотреть, что скажет Джекс (и как это может научить меня быть лучше на работе).
Политика безопасности контента
На данный момент я не ожидал, что у Джека пока что есть какие-либо рекомендации для меня. Но когда я вернулся к интерфейсу, я увидел первый совет, который он мог мне предложить:
Потребовалось немного времени для поиска хорошего объяснения, но я наконец нашел его в Справочнике и примерах политики безопасности контента CSP . CSP — это, по сути, способ ограничения места загрузки ресурсов HTTP. Это замечательно, потому что злоумышленники, которые могли бы внедрить пользовательские сценарии и / или изображения, не смогли бы использовать эти уязвимости так же легко.
Джекс также предоставил пример кода для того, как добавить Blankie в мой серверный скрипт:
"use strict" const hapi = require("hapi") const blankie = require("blankie") const scooter = require("scooter") const server = new hapi.Server() // ...create server + connection + routes server.register([scooter, { "register": blankie, "options": { // ..CSP directives here "defaultSrc": "self", } }], err => { // ...start server })
Это из index.js
.
Чтобы этот код работал, мне нужно было установить Blankie и Scooter с yarn add blankie
и yarn add scooter
yarn add blankie
. Они добавляют заголовки CSP к каждому запросу:
Конечно же, как только я передал этот код в проект, Джекс заметил это и отметил рекомендацию как решенную.
Отключение списков каталогов
Распространенной ошибкой безопасности является включение (или, скорее, неправильное отключение) списков каталогов в веб-приложениях. Существует популярный плагин Hapi, который называется Inert, который обеспечивает статическое обслуживание файлов и списки каталогов. Это не редкость, чтобы включить эти функции, вот что я пытался сделать:
"use strict" const hapi = require("hapi") const blankie = require("blankie") const scooter = require("scooter") const inert = require("inert") // ...create server + connection server.register([inert, scooter, { "register": blankie, "options": { // ..CSP directives here "defaultSrc": "self", } }], err => { // ...create other routes server.route({ "method": "GET", "path": "/{params*}", "handler": { "directory": { "path": "public", "listing": true, }, }, }) // ...start server })
Это из index.js
.
Мне нужно было установить yarn add inert
, с yarn add inert
, чтобы этот код работал. После этого я смог увидеть списки каталогов в вашем веб-приложении:
Я отправил этот код в хранилище и прыгнул к Джеку для анализа. Как и ожидалось, он предупредил против включения списков каталогов:
Более того, он предоставил мне информацию о патче, чтобы отключить списки каталогов:
Это очень хорошо для начинающих хапи, как я. Как только я последовал этому совету, Джекс перестал предупреждать меня об этой конкретной проблеме.
Небезопасные файлы cookie
Последней дырой в безопасности, которую я хотел проверить, было небезопасное управление сессиями / состоянием. Документы Hapi показывают, как создавать куки, чтобы сохранить состояние сеанса. Они упоминают различные настройки, которые вы можете использовать, и их значения по умолчанию. Чего они не упоминают, так это как вы можете испортить безопасность сеанса, используя неправильные настройки:
"use strict" const hapi = require("hapi") const blankie = require("blankie") const scooter = require("scooter") const inert = require("inert") // ...create server + connection server.register([inert, scooter, { "register": blankie, "options": { // ..CSP directives here "defaultSrc": "self", } }], err => { server.state("session", { "ttl": 24 * 60 * 60 * 1000, "isSecure": false, "isHttpOnly": false, "path": "/", "encoding": "base64json", }) server.route({ "method": "get", "path": "/", handler: function (request, reply) { let session = request.state.session if (!session) { session = { "returning": true } } session.date = Date.now() return reply("hello world") .state("session", session) }, }) // ...create other routes // ...start server })
Это из index.js
.
В этот момент я ожидал, что Джекс укажет на оскорбительные строки кода:
"isSecure": false, "isHttpOnly": false,
Они не выглядят очень безопасными для меня, и они также отличаются от значений по умолчанию Хапи. Я предполагаю, что это говорит о том, что, хотя оценка человеческого кода может выявить очевидные ошибки, гораздо сложнее заставить алгоритм их увидеть.
Другие вещи, которые Джек защищает от
Я связался с разработчиками Jacks, и они рассказали мне о многих других вещах, которые рекомендует Jacks:
- Использование адаптивных односторонних функций хеширования для хранения паролей
- Использование методов, отличных от базовой аутентификации HTTP (через HTTPS)
- Использование соответствующих факторов работы с PBKDF2 и Scrypt
- Использование CSPRNG надлежащим образом
- Включение белого списка CORS
- Как избежать уязвимости JSONP Rosetta Flash
… И это только некоторые из рекомендаций, характерных для хапи. Джек также может анализировать код MongoDB и Express. Недавно они также добавили поддержку Java, начиная с Spring и Struts .
Вывод
Я определенно стремлюсь продолжать использовать Джекса, поскольку я узнаю больше о Хапи. Это просто та помощь, которая мне нужна, когда я пишу код. И когда я застреваю, я всегда могу использовать функцию обмена мгновенными сообщениями поддержки, чтобы поговорить с одним из их разработчиков. Лучше всего, это бесплатно.