Бързи съвети, които могат да спасят вашето приложение Node от атаки за сигурност

Node.js е една от най-популярните среди за изпълнение, използвани заедно с рамки като Express. Той има процъфтяваща общност от разработчици и е обичан от всички. Докато разработването с Node.js е удоволствие и също така е важно да мислите за приложението, което сте създали от гледна точка на сигурността.

John Au-Yeung е написал бърз прочит по тази тема, както и тук за методи като предотвратяване на атаки с груба сила срещу оторизация, използване на root, изявления за оценка и други. В тази статия ще обсъдим някои прости, но ефективни съвети за защита на вашите Node.js/Express.js приложения от атаки, които се разширяват по-нататък от статията. Заедно това може да бъде полезно ръководство за подобряване на механизмите за сигурност във вашите приложения Node.js.

Нека се потопим направо в него!

Валидиране на въведените данни от потребителите

Валидации на формуляри

Един от ключовите принципи при разработването на всяко софтуерно приложение е да се гарантира, че данните, влизащи във вашето приложение, винаги са валидирани според вашите условия. Без проверка злонамереното въвеждане може да влезе във вашето приложение.

В Node.js имаме лукса да използваме регистъра на NPM, който има огромен брой библиотеки. За целите на валидирането можем да използваме библиотеките validator и express-validator.

Например с пакета валидатор можете да извършвате прости проверки, за да проверите дали низът, който се въвежда, е имейл:

const validator = require('validator');
validator.isEmail("[email protected]");

По същия начин той предлага огромен набор от операции като isAlpha и дезинфекциращи функции като escape или trim.

Express validator е друга библиотека, която е междинен софтуер за Express.js. Тук е показан прост пример за валидиране на полетата в тялото на заявката на извикване на API:

// ...rest of the initial code omitted for simplicity.
const { body, validationResult } = require('express-validator');

app.post(
  '/user',
  // username must be an email
  body('username').isEmail(),
  // password must be at least 5 chars long
  body('password').isLength({ min: 5 }),
  (req, res) => {
    // Finds the validation errors in this request and wraps them in an object with handy functions
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }

    User.create({
      username: req.body.username,
      password: req.body.password,
    }).then(user => res.json(user));
  },
);

Вижте тази страница за подробна документация.

Предотвратяване на SQL инжектиране

Още веднъж, атаките чрез SQL инжектиране възникват, когато входът от потребителите не е дезинфекциран. Това може да доведе до изпълнение на SQL заявка, подадена в полетата на формуляра, в базата данни. Представете си как операция като DROP DATABASE dbName; ще се отрази на вашето приложение! Това ще изтрие данните чисти.

В този случай най-простият подход е също да използвате библиотека като валидатор (споделена по-горе), за да дезинфекцирате напълно входа, за да гарантирате, че специалните символи, странните низове на заявки и т.н. са премахнати, преди да отидете в слоя база данни във вашия код.

Избягване на несъответствия на типа

След това трябва да избягваме несъответствия на типове в нашия код. Например, не можем да получим низ, когато нашата функция очаква число. JavaScript е слабо въведен език. От нас няма да се изисква да посочим типа на променливата предварително и JavaScript ще се опита да я „напише“ съответно.

Въпреки че това може да бъде по-лесно при разработване, може да доведе до някои пропуски и грешки в сигурността. За да избегнем това, можем да използваме собствени функции за кастинг в JavaScript като:

  • Число („123“)
  • низ (123)

Има много други преобразувания на типове, които можете да използвате. Вижте тази страница за повече информация.

Управление на сметки

Хеширане на парола

Решаваща част от вашето приложение е управлението на потребителите. Вашето приложение най-вероятно съдържа потребителски акаунти, които позволяват на потребителите да влизат. Такива функции най-вероятно ще използват парола за влизане.

Паролите се класифицират като чувствителна информация и трябва да се съхраняват по възможен сигурен начин, така че да не бъдат злоупотребени в ръцете на грешния човек. Основната мярка при управлението на пароли е осоляването и хеширането.

Хеширането се отнася до еднопосочна функция, която преобразува входа в низ от недекодируеми байтове. Въпреки това, използването само на хеширане няма да реши проблема. Нападателят може лесно да използва справочни таблици, които съдържат предварително изчислени хешове на най-популярните пароли, за да сравни хешовете в базата данни на вашето приложение (в случай на хакване).

Тук се намесва солирането. Като добавим произволна „сол“, ние добавяме уникален низ от знаци към паролата в обикновен текст, предоставена от потребителя, и след това я хешираме. С това вероятността за декодиране на хеширана парола с таблица за търсене е значително намалена.

За приложения Node.js или Express.js можем да се възползваме от библиотеката BCrypt.

const bcrypt = require('bcrypt');
const saltRounds = 10;
bcrypt.genSalt(saltRounds, function(err, salt) {
    bcrypt.hash(userPassword, salt, function(err, hash) {
         dbHelper.save(hash);
    });
});

По-горе е прост пример как можете да постигнете това само с няколко реда!

saltRounds е броят кръгове на солния процес, който е свързан със сигурността на хеша. Повече кръгове = по-сигурно, но повече кръгове = по-скъпа операция.

Упълномощаване

Следващата част от управлението на акаунта е оторизацията. Просто казано,

Упълномощаването е функцията за определяне на права/привилегии за достъп до ресурси, което е свързано с общата информационна сигурност и компютърната сигурност и по-специално с контрола на достъпа.
Кредити: Wikipedia

Следователно, използвайки оторизация, можем да гарантираме, че само правилните хора/потребители имат достъп до правилните ресурси.

В Node.js/Express.js можем да постигнем това с помощта на ACL библиотеката. Например,

// allow function accepts arrays as any parameter
acl.allow("member", "blogs", ["edit", "view", "delete"]);

Горният пример от документите показва, че позволяваме на „члена“ да „редактира“, „преглежда“ и „изтрива“ ресурса, наречен „блогове“.

Упълномощаването заедно с удостоверяването е важно. Не бъркайте двете и всяка е важна в самия си аспект.

Удостоверяването е процес на установяване, че някой наистина е този, за когото се представя.

Упълномощаването се отнася до правила, които определят кой какво има право да прави. напр. Адам може да бъде упълномощен да създава и изтрива бази данни, докато Усама е упълномощен само да чете.
Кредити: StackOverflow

Мрежова сигурност

HTTPS и SSL

Освен вашето приложение, вие също трябва да предавате и получавате данни по сигурен начин, за да избегнете подслушване. Днес всяко приложение трябва да поддържа HTTPS като де факто стандарт.

Въпреки че не е уникален за Node.js/Express.js, най-лесният начин да наложите SSL криптиране за вашите приложения е да използвате LetsEncrypt. Това е безплатна за използване услуга, която предоставя безплатни SSL сертификати за защита на домейна на вашето приложение.

Това трябва да работи на ниво уеб сървър, като например с Nginx. Разгледайте документите тук.

Друг начин е разбира се да получите SSL сертификати от вашия доставчик на облак, като например Amazon Certificate Manager (ACM) на AWS.

Защитни заглавки

Много атаки могат да бъдат предотвратени само с наличието на някои ключови защитни заглавки. За да приложим това, можем да използваме „шлем“. Само с един ред код можете да активирате няколко заглавки за сигурност:

app.use(helmet());

Горното се превежда на:

app.use(helmet.contentSecurityPolicy());
app.use(helmet.dnsPrefetchControl());
app.use(helmet.expectCt());
app.use(helmet.frameguard());
app.use(helmet.hidePoweredBy());
app.use(helmet.hsts());
app.use(helmet.ieNoOpen());
app.use(helmet.noSniff());
app.use(helmet.permittedCrossDomainPolicies());
app.use(helmet.referrerPolicy());
app.use(helmet.xssFilter());

Просто, лесно и ефективно!

други

Смекчаване на CSRF / XSRF

Друга популярна атака, която може да се наложи да смекчите, е Cross-Site Request Forgery. Тази атака подвежда легитимен потребител да изпрати злонамерено съдържание. Например, каране на потребител да изпълни злонамерен скрипт, когато е влязъл в системата (състояние на удостоверяване).

Тази атака може да бъде смекчена с помощта на csurf библиотека. Този пакет изисква използването на сесиен мидълуер или парсер на бисквитки. Най-често се използва с Express.js като междинен софтуер. Разгледайте документите тук.

Този междинен софтуер помага за създаването на csrf-токен, който ще бъде предаден заедно с мрежовите повиквания. След това този токен ще бъде валидиран спрямо сесията на потребителя или бисквитката. Прочетете повече тук.

Пакети и зависимости

Въпреки че хранилището на NPM е огромно и предоставя лесен и достъпен начин за разширяване на вашите приложения, ние също трябва да вземем предпазни мерки, за да бъдем изложени на рискове за сигурността поради остарели пакети.

Следователно са необходими редовни монитори, за да се гарантира, че всички пакети са актуални. Можем да направим това лесно с помощта на командата npm audit и да коригираме автоматично поправими проблеми с npm audit fix.

Толкова е просто!

Заключение

Днес сигурността на приложенията, които разработваме, има огромен приоритет при осигуряването на стабилност, надеждност и издръжливост на вашите услуги. Разбира се, защитата на доверието на потребителите е друга голяма отговорност, която имаме като разработчици. Горните съвети са някои начини, по които можем да разширим нашите приложения на Node, за да работят безопасно и да сведат до минимум рисковете за сигурността.

Приятно кодиране! 💻

Повече съдържание на plainenglish.io