Ми під атакою! 23+ кращі практики безпеки Node.js

Ми під атакою! 23+ кращі практики безпеки Node.js

Зібрали, куратори та автори: Йоні Голдберг, Кайл Мартін та Бруно Шефлер

Технічний рецензент: Ліран Тал (Робоча група з питань безпеки Node.js)

Ласкаво просимо до нашого вичерпного списку найкращих практик безпеки Node.js, який узагальнює та удосконалює статті та блоги, що займають найкращі позиції

Кілька слів, перш ніж ми почнемо

Ці веб-атаки вибухають сьогодні, коли безпека виходить на фронт сцени. Ми зібрали понад 23 найкращих практик безпеки Node.js (+40 інших загальних практик безпеки) з усіх рейтингових статей по всьому світу. Робота тут є частиною нашого кращого практичного сховища GitHub у Node.js, що містить понад 80 практик Node.js. Примітка. У багатьох пунктах є докладніше посилання на опрацювання теми з прикладом коду та іншою корисною інформацією.

Отримуйте найкращі практики щотижня через наш канал у Twitter

1. Отримати правила безпеки лінійки

TL; DR: Використовуйте додаткові вкладиші, пов’язані з безпекою, такі як eslint-plugin-security, щоб якомога раніше виявляти вразливості та проблеми безпеки - під час їх кодування. Це може допомогти вирішити слабкі місця безпеки, як-от використання eval, виклик дочірнього процесу або імпорт модуля з не рядковим літералом (наприклад, введення користувача). Натисніть "Детальніше" нижче, щоб побачити приклади коду, які потраплять у літер безпеки

Інакше: те, що могло бути прямою слабкістю безпеки під час розвитку, стає головним питанням у виробництві. Крім того, проект може не дотримуватися послідовної практики захисту коду, що призводить до вразливості або вразливих секретів, відданих у віддалені сховища

Детальніше: Правила лінійки

Обв'язка не повинна бути лише інструментом для виконання педантичних правил щодо пробілів, крапків з комою або твердженнями eval. ESLint забезпечує потужну основу для усунення найрізноманітніших потенційно небезпечних зразків у вашому коді (регулярні вирази, перевірка вводу тощо). Я думаю, що це новий потужний новий інструмент, який заслуговує на розгляд розробниками JavaScript, що не мають безпеки. (Адам Болдуін)
Більше цитат та прикладів коду тут

2. Обмежте паралельні запити за допомогою проміжного програмного забезпечення

TL; DR: DOS-атаки дуже популярні та відносно прості в проведенні. Впроваджуйте обмеження швидкості за допомогою зовнішньої служби, такої як балансори хмарного навантаження, хмарні брандмауери, nginx, гнучкий пакет обмеження швидкості або (для менших та менш важливих додатків), що обмежує швидкість середнього програмного забезпечення (наприклад, експрес-обмеження швидкості)

В іншому випадку: Додаток може зазнати атаки, що призведе до відмови в обслуговуванні, коли реальні користувачі отримують деградовану або недоступну послугу.

Детальніше: Обмеження швидкості впровадження

3. Витягуйте секрети з конфігураційних файлів або використовуйте пакети для їх шифрування

TL; DR: ніколи не зберігайте текстові секрети у файлах конфігурації чи вихідному коді. Натомість скористайтеся системами управління секретами, такими як Vault products, Kubernetes / Docker Secrets або використовуючи змінні середовища. В останньому результаті секрети, що зберігаються в керуванні джерелами, повинні бути зашифровані та керовані (клавіші прокатки, термін дії, аудит тощо). Скористайтеся гачками попереднього вчинення / натискання, щоб запобігти випадковому введенню секретів

В іншому випадку: Контроль над джерелами, навіть для приватних сховищ, може бути помилково оприлюднений, і тоді всі секрети будуть викриті. Доступ до керування джерелами для зовнішньої сторони ненавмисно забезпечить доступ до пов’язаних систем (баз даних, apis, служб тощо).

Детальніше: Таємне управління

4. Запобігання вразливості введення запитів за допомогою бібліотек ORM / ODM

TL; DR: Щоб запобігти ін'єкції SQL / NoSQL та інших шкідливих атак, завжди використовуйте ORM / ODM або бібліотеку баз даних, яка уникає даних або підтримує іменовані або індексовані параметризовані запити та дбає про перевірку введення користувачем для очікуваних типів. Ніколи не використовуйте рядки шаблону JavaScript або об'єднання рядків для введення значень у запити, оскільки це відкриває вашій програмі широкий спектр уразливостей. Усі надійні бібліотеки доступу до даних Node.js (наприклад, Sequelize, Knex, мангуста) мають вбудований захист проти атак ін'єкції

В іншому випадку: неваліфікований або несаніфікований введення користувача може призвести до введення оператора під час роботи з MongoDB для NoSQL, а не використання належної системи санітарії або ORM легко дозволить атаки ін'єкції SQL, створивши велику вразливість.

Детальніше: Запит запобігання ін'єкцій за допомогою бібліотек ORM / ODM

Цінуйте зусилля? Будь ласка, позначте наш проект на GitHub

5. Уникайте DOS-атак, чітко встановлюючи, коли процес повинен вийти з ладу

TL; DR: Процес вузла завершиться, коли помилки не обробляються. Багато кращих практик навіть рекомендують вийти, хоча помилка була виявлена ​​та її вирішено. Наприклад, Express вийде з ладу за будь-якою асинхронною помилкою - якщо ви не обмотаєте маршрути із застереженням. Це відкриває дуже приємне місце атаки для зловмисників, які розпізнають, який вхід робить процес збоєм і повторно надсилає той самий запит. Немає миттєвих засобів для цього, але кілька методів можуть полегшити біль: Попереджуйте з критичною суворістю будь-який час, коли процес виходить з ладу через невідправлену помилку, перевірити введення даних та уникнути збоїв процесу через недійсне введення користувача, оберніть усі маршрути з уловкою та вважайте, що не виходить з ладу, коли помилка виникла в запиті (на відміну від того, що відбувається в усьому світі)

В іншому випадку: це лише освічена здогадка: зважаючи на багато додатків Node.js, якщо ми спробуємо передати порожній корпус JSON для всіх POST-запитів, - кілька програм перестануть. У цей момент ми можемо просто повторити надсилання того ж запиту, щоб легко знімати програми

6. Відрегулюйте заголовки відповідей HTTP для посилення безпеки

TL; DR: Ваша програма повинна використовувати захищені заголовки, щоб запобігти використанню зловмисників поширених атак, таких як міжсайтовий сценарій (XSS), джек-джек та інші зловмисні атаки. Їх можна легко налаштувати за допомогою модулів, таких як шолом.

В іншому випадку: Зловмисники можуть здійснювати прямі атаки на користувачів вашої програми, що призводить до величезних уразливості безпеки

Детальніше: Використання захисних заголовків у вашій програмі

7. Постійно та автоматично перевіряйте на наявність вразливих залежностей

TL; DR: З екосистемою npm зазвичай існує багато залежностей для проекту. Залежності завжди слід перевіряти, коли виявляються нові вразливості. Використовуйте такі інструменти, як npm audit, nsp або snyk для відстеження, контролю та виправлення вразливих залежностей. Інтегруйте ці інструменти у свій інсталятор CI, щоб ви потрапили на вразливу залежність, перш ніж вона перетвориться на виробництво.

В іншому випадку: Зловмисник може виявити ваш веб-фреймворк і атакувати всі відомі йому вразливості.

Детальніше: Захист залежності

8. Уникайте використання крипто-бібліотеки Node.js для обробки паролів, використовуйте Bcrypt

TL; DR: паролі або секрети (ключі API) слід зберігати, використовуючи захищену хеш-сольову функцію, як bcrypt, що має бути кращим вибором щодо її реалізації JavaScript через ефективність та безпеку.

В іншому випадку: паролі чи секрети, які зберігаються без використання захищеної функції, вразливі для грубої форсировки та атаки словника, що призведе до їх розкриття з часом.

Детальніше: Використовуйте Bcrypt

9. Вихід HTML, JS та CSS

TL; DR: ненадійні дані, що надсилаються до браузера, можуть бути виконані замість того, щоб просто відображатися, це зазвичай називається атакою міжсайтового сценарію (XSS). Пом'якшіть це за допомогою спеціальних бібліотек, які явно позначають дані як чистий вміст, який ніколи не повинен виконуватися (тобто кодування, виходу з екрана)

В іншому випадку: Зловмисник може зберігати зловмисний код JavaScript у вашій БД, який потім буде надісланий таким, як він є бідним клієнтам

Детальніше: Вихідний вихід

10. Перевірка вхідних схем JSON

TL; DR: перевірити навантаження на вхідні запити та переконайтесь, що воно відповідає очікуванням, невдало швидко, якщо цього не відбувається. Щоб уникнути нудного кодування перевірки у кожному маршруті, ви можете використовувати легкі схеми перевірки на основі JSON, такі як jsonschema або joi

В іншому випадку: ваша щедрість і вседозволений підхід значно збільшує поверхню атаки і спонукає зловмисника спробувати багато входів, поки вони не знайдуть якусь комбінацію для збою програми

Детальніше: Перевірка вхідних схем JSON

11. Підтримка чорних списків JWT-маркерів

TL; DR: Коли використовуються маркери JWT (наприклад, з Passport.js), за замовчуванням не існує механізму, щоб відкликати доступ із виданих жетонів. Виявивши деяку шкідливу діяльність користувача, немає жодного способу заборонити їм отримувати доступ до системи, якщо вони мають дійсний маркер. Пом'якшіть це, застосувавши чорний список ненадійних жетонів, які перевіряються під час кожного запиту.

В іншому випадку: Маркери, що втратили чинність, або неправильно розміщені маркери можуть зловмисно використовуватися третьою стороною для доступу до програми та видавати себе за власника маркера.

Детальніше: Чорний список JWT

12. Запобігайте жорстоким атакам проти авторизації

TL; DR: проста і потужна методика - обмежити спроби авторизації за допомогою двох показників:

  1. Перший - це кількість послідовних невдалих спроб одного і того ж користувача унікального ідентифікатора / імені та IP-адреси.
  2. Друга - кількість невдалих спроб з IP-адреси протягом певного тривалого періоду часу. Наприклад, блокуйте IP-адресу, якщо вона робить 100 невдалих спроб за один день.

В іншому випадку: Зловмисник може випустити необмежену кількість автоматичних спроб пароля отримати доступ до привілейованих облікових записів програми

Детальніше: Обмеження швидкості входу

13. Запустіть Node.js як некористувацький користувач

TL; DR: Існує загальний сценарій, коли Node.js працює як користувач root з необмеженими дозволами. Наприклад, така поведінка за замовчуванням у контейнерах Docker. Рекомендується створити некористувального користувача і ввести його в зображення Docker (приклади, наведені нижче) або запустити процес від імені цього користувача, викликавши контейнер з прапором "-u ім'я користувача"

В іншому випадку: Зловмисник, якому вдається запустити скрипт на сервері, отримує необмежену владу над локальною машиною (наприклад, змінити iptable і перенаправити трафік на свій сервер)

Детальніше: Запустіть Node.js як некористувацький користувач

14. Обмежте розмір корисної навантаження за допомогою реверсивного проксі-сервера або проміжного програмного забезпечення

TL; DR: Чим більше навантаження на кузов, тим важче працює ваша одна нитка при її обробці. Це можливість для зловмисників поставити сервери на коліна без величезної кількості запитів (DOS-DDOS-атаки). Пом'якшіть це обмеження розміру тіла вхідних запитів на межі (наприклад, брандмауер, ELB) або конфігуруючи експрес-аналізатор тіла, щоб приймати лише корисні навантаження невеликого розміру

В іншому випадку: Вашій програмі доведеться вирішувати великі запити, не в змозі обробити іншу важливу роботу, яку вона має виконати, що призведе до наслідків для продуктивності та вразливості щодо DOS-атак

Детальніше: Обмежте розмір корисної навантаження

Отримуйте найкращі практики щотижня через наш канал у Twitter

15. Уникайте Java-заяв eval

TL; DR: eval - це зло, оскільки воно дозволяє виконувати спеціальний код JavaScript під час виконання. Це не лише ступінь продуктивності, але й важлива проблема безпеки через шкідливий код JavaScript, який може бути отриманий за допомогою введення користувача. Ще одна мовна особливість, якої слід уникати, - це новий конструктор функцій. setTimeout та setInterval також ніколи не повинні передаватись динамічним кодом JavaScript.

В іншому випадку: Зловмисний код JavaScript знаходить шлях до тексту, переданого в eval, або інших мовних функцій JavaScript в реальному часі, і отримає повний доступ до дозволів JavaScript на сторінці. Ця вразливість часто виявляється як атака XSS.

Детальніше: Уникайте Java-заяв eval

16. Запобігайте злому RegEx від перевантаження вашого виконання одного потоку

TL; DR: Регулярні вирази, хоча вони зручні, становлять реальну загрозу для JavaScript-програм узагалі, і платформи Node.js зокрема. Для введення користувачем тексту для відповідності тексту може знадобитися обробляти неабияку кількість циклів процесора. Обробка RegEx може виявитися неефективною, оскільки один запит, що підтверджує 10 слів, може блокувати весь цикл подій протягом 6 секунд і встановити ЦП на . З цієї причини віддайте перевагу стороннім пакетам перевірки, наприклад validator.js, замість того, щоб писати власні шаблони Regex, або використовуйте безпечний-регулярний вираз для виявлення вразливих шаблонів регексу.

В іншому випадку: погано написані регулярні вирази можуть сприйняти атаки DoS регулярної експресії, які повністю перекриють цикл подій. Наприклад, популярний пакет моментів виявився вразливим від зловмисного використання RegEx у листопаді 2017 року

Детальніше: Запобігайте зловмисному RegEx

17. Уникайте завантаження модуля за допомогою змінної

TL; DR: уникайте вимагати / імпортувати інший файл із контуром, який був заданий як параметр через стурбованість тим, що він міг виникнути від введення користувача. Це правило може бути розширено для доступу до файлів загалом (тобто fs.readFile ()) або іншого чутливого доступу до ресурсів з динамічними змінними, що походять від введення користувача. Eslint-плагін-захисний лайнер може вловлювати такі зразки та попереджати досить рано

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

Детальніше: Безпечне завантаження модуля

18. Запустіть небезпечний код у пісочниці

TL; DR: Коли потрібно виконати зовнішній код, який задається під час виконання (наприклад, плагін), використовуйте будь-яке середовище виконання "пісочниці", яке ізолює та захищає основний код від плагіна. Цього можна досягти за допомогою виділеного процесу (наприклад, cluster.fork ()), безсерверного середовища або виділених пакетів npm, які діють як пісочниця

В іншому випадку: плагін може атакувати за допомогою безлічі різноманітних варіантів, таких як нескінченна кількість циклів, перевантаження пам'яті та доступ до чутливих змінних середовищ технологічного середовища

Детальніше: Запустіть небезпечний код у пісочниці

19. Будьте особливо уважні при роботі з дитячими процесами

TL; DR: Уникайте використання дочірніх процесів, коли це можливо, і підтверджуйте та санітизуйте введення, щоб пом'якшити атаки введення оболонки, якщо вам все-таки доведеться. Віддайте перевагу використанню child_process.execFile, який за визначенням виконає лише одну команду з набором атрибутів і не дозволить розширити параметр оболонки.

В іншому випадку: Наївне використання дочірніх процесів може призвести до віддаленого виконання команд або атак введення оболонки через зловмисне введення користувачем, передане несанкціонованій системній команді.

Детальніше: Будьте обережні, працюючи з дитячими процесами

20. Сховати дані про помилки від клієнтів

TL; DR: Інтегрований експрес-обробник помилок приховує деталі помилок за замовчуванням. Однак великі шанси на те, що ви реалізуєте власну логіку поводження з помилками з користувацькими об'єктами помилок (багато хто вважається найкращою практикою). Якщо ви зробите це, переконайтеся, що не повертайте клієнту весь об’єкт Помилка, який може містити деякі чутливі дані програми

В іншому випадку: чутливі відомості про додатки, такі як шляхи до файлів до сервера, використовувані сторонні модулі та інші внутрішні робочі процеси програми, які може бути використаний зловмисником, можуть просочуватися з інформації, знайденої в сліді стека

Детальніше: Сховати дані про помилки від клієнтів

21. Налаштуйте 2FA для npm або пряжі

TL; DR: Будь-який крок у ланцюжку розробок повинен бути захищений MFA (багатофакторною автентифікацією), npm / пряжа - це приємна можливість для зловмисників, які можуть потрапити на пароль певного розробника. Використовуючи облікові дані розробників, зловмисники можуть вводити шкідливий код у бібліотеки, які широко встановлені в різних проектах та службах. Можливо, навіть в Інтернеті, якщо публікується публічно. Увімкнення 2-факторної аутентифікації в npm залишає майже нульові шанси зловмисникам змінити код вашого пакета.

В іншому випадку: Ви чули про розробника програми eslint, у якого було викрадено пароль?

22. Змініть налаштування проміжного програмного забезпечення сесії

TL; DR: Кожен веб-фреймворк і технологія мають свої відомі слабкі сторони - сказати зловмиснику, який веб-фреймворк ми використовуємо - це їм велика допомога. Використовуючи налаштування за замовчуванням для середнього рівня сеансу, ви можете піддавати програмі додаткові викрадення, пов'язані з модулями та рамками, аналогічно заголовку X-Powered-By. Спробуйте приховати все, що ідентифікує та виявляє ваш стек технологій (наприклад, Node.js, express)

В іншому випадку: куки-файли можуть надсилатися через незахищені з'єднання, а зловмисник може використовувати ідентифікацію сеансу для ідентифікації базових рамок веб-програми, а також уразливості, що стосуються модуля

Детальніше: Захист файлів cookie та сеансів

23. Уникайте DOS-атак, чітко встановлюючи, коли процес повинен вийти з ладу

TL; DR: Процес вузла завершиться, коли помилки не обробляються. Багато кращих практик навіть рекомендують вийти, хоча помилка була виявлена ​​та її вирішено. Наприклад, Express вийде з ладу за будь-якою асинхронною помилкою - якщо ви не обмотаєте маршрути із застереженням. Це відкриває дуже приємне місце атаки для зловмисників, які розпізнають, який вхід робить процес збоєм і повторно надсилає той самий запит. Немає миттєвих засобів для цього, але декілька методів можуть полегшити біль: Попереджуйте з критичною суворістю, коли процес виходить з ладу через не оброблену помилку, перевірити введення даних та уникнути збоїв процесу через недійсне введення користувача, оберніть усі маршрути з уловкою та вважайте, що не виходить з ладу, коли помилка виникла в запиті (на відміну від того, що відбувається в усьому світі)

В іншому випадку: це лише освічена здогадка: зважаючи на багато додатків Node.js, якщо ми спробуємо передати порожній корпус JSON для всіх POST-запитів, - кілька програм перестануть. У цей момент ми можемо просто повторити надсилання того ж запиту, щоб легко знімати програми.

24. Не допускайте небезпечних переадресацій

TL; DR: Переспрямовування, що не підтверджує введення даних користувача, може зловмисникам запускати фішинг-афери, красти облікові дані користувачів та виконувати інші шкідливі дії.

В іншому випадку: Якщо зловмисник виявить, що ви не підтверджуєте зовнішній, наданий користувачем вхід, він може скористатися цією вразливістю, розмістивши спеціально створені посилання на форумах, соціальних мережах та інших громадських місцях, щоб користувачі могли натиснути її.

Читайте більше: Запобігайте небезпечним переадресаціям

25. Уникайте публікації секретів у реєстрі npm

TL; DR: Необхідно вживати запобіжних заходів, щоб уникнути ризику випадкової публікації секретів у публічних регістрах npm. Файл .npmignore може використовуватися для чорного списку певних файлів або папок, або масив файлів у package.json може виступати як білий список.

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

Детальніше: Уникайте публікації секретів

Цінуйте зусилля? Будь ласка, позначте наш проект на GitHub

26. Список 40 загальних порад щодо безпеки (не стосується конкретно Node.js)

Наведені нижче пункти - це добре відомі та важливі заходи безпеки, які слід застосовувати в кожній програмі. Оскільки вони не обов'язково пов'язані з Node.js і реалізуються аналогічно незалежно від рамки програми - ми включаємо їх сюди як додаток. Елементи групуються за їх класифікацією OWASP. Зразок включає наступні моменти:

  • Потрібен MFA / 2FA для кореневого рахунку
  • Часто обертайте паролі та ключі доступу, включаючи SSH-ключі
  • Застосовуйте чітку політику щодо паролів, як для ops, так і для керування користувачами в додатках, див. Рекомендацію щодо пароля OWASP
  • Не надсилайте та не розгортайте будь-які облікові дані за замовчуванням, особливо для користувачів адміністратора
  • Використовуйте лише стандартні методи аутентифікації, такі як OAuth, OpenID тощо. - уникайте базової аутентифікації
  • Обмеження швидкості аутентичності: забороняйте більше X спроб входу (включаючи відновлення пароля тощо) протягом періоду Y хвилин
  • Під час входу в систему не повідомляйте користувача про те, чи не вдалося підтвердити ім'я користувача або пароль, просто поверніть загальну помилку авторизації
  • Подумайте про використання централізованої системи управління користувачами, щоб уникнути керування кількома обліковими записами на одного співробітника (наприклад, GitHub, AWS, Jenkins тощо) та скористатись випробуваною в бою системою управління користувачем.

Повний список 40 загальних порад щодо безпеки можна знайти в офіційному сховищі кращих практик Node.js!

Детальніше: 40 Загальні поради щодо безпеки

Інші хороші читання:

  • Передовий досвід виробництва Node.js - Йоні Голдберг
  • Огляд безпеки Node.js - Гергелі Немет
  • Передовий досвід експрес-безпеки - Експрес офіційний
  • YouTube: Дорожня карта безпеки Node.js - Майк Самуель

Автори - про нас

  • Yoni Goldberg - консультант Node.js, який обслуговує клієнтів у США, Європі та Ізраїлі
  • Kyle Martin - Full Stack Developer, що базується в Новій Зеландії
  • Bruno Scheufler - повнорозмірний веб-розробник та ентузіаст Node.js
Цінуйте зусилля? Похлопування на дні (до 50 разів) може зробити наш день