Повечето уеб приложения не биват пробивани с хитри нови атаки. Пробиват се заради кратък списък от известни грешки: слабо направен вход, липсваща проверка на правата в един-единствен адрес, непроверени входни данни, изтекла парола или API ключ, остаряла библиотека и липса на резервно копие или лог, с които да се възстанови и разследва случилото се. Да защитите приложението означава съзнателно да затворите всяка от тези пролуки и да ги проверявате отново при всяка промяна в кода. Списъкът по-долу е за собственици, които трябва да знаят какво да изискват, и за разработчици, които трябва да знаят какво да проверят.
#Вход и сесии
Автентикацията проверява дали човекът е този, за когото се представя. Повечето рамки (frameworks) имат добре работещо решение и най-сигурното е да използвате него, вместо да пишете собствено.
- Пазете паролите с бавен алгоритъм за хеширане със сол, създаден специално за пароли, като bcrypt или Argon2. Никога в чист вид и никога с бърз хеш с общо предназначение.
- Предложете двуфакторна автентикация и я направете задължителна за администраторите и за всеки, който вижда клиентски данни или управлява плащания.
- Ограничете опитите за вход за всеки акаунт и всеки IP адрес, за да не могат паролите да се налучкват масово.
- Направете възстановяването на парола безопасно: еднократни връзки с изтичащ срок и еднакъв отговор независимо дали имейлът съществува.
- Защитете бисквитките на сесията с атрибутите
Secure,HttpOnlyиSameSite, сменяйте идентификатора на сесията след вход и прекратявайте сесията при изход и след период на неактивност. - Използвайте CSRF защита за всяка форма и всяка заявка, която променя данни и разчита на бисквитки.
#Проверка на правата при всяка заявка
Авторизацията отговаря на друг въпрос: има ли влезлият потребител право да извърши точно това действие върху точно този запис. Тук се случват много от реалните пробиви и OWASP Top 10 нарежда нарушения контрол на достъпа сред най-сериозните рискове.
Типичната грешка е проста. Потребител отваря /invoices/1042, сменя числото на 1043 и вижда фактурата на друг клиент, защото кодът е проверил само дали е влязъл, но не и дали фактурата е негова. Същото се случва с API адреси, които интерфейсът не показва, и с административни действия, „защитени“ само със скрит бутон.
- Проверявайте правата на сървъра, при всяка заявка и за всеки запис. Скрита връзка в интерфейса не е защита.
- Дръжте правилата на едно място, например в политики (policies) или междинен слой (middleware), за да не може нов адрес да ги пропусне.
- Забранявайте по подразбиране. Нова роля или нов адрес нямат достъп, докато някой изрично не го даде.
- Напишете автоматични тестове, които се опитват да четат и променят чужди данни и очакват отказ.
#Проверка на входа и екраниране на изхода
Приемайте всичко, което идва отвън, за недоверено: полета от форми, параметри в адреса, заглавки, качени файлове, данни от уебкукита (webhooks) и отговори от API на партньори.
- Проверявайте на сървъра типа, дължината, формата и допустимите стойности. Проверката в браузъра помага на потребителя, но не защитава нищо.
- Използвайте параметризирани заявки или построителя на заявки на рамката за всяка заявка към базата данни. SQL, сглобен от низове с потребителски вход, е пътят към SQL инжекция.
- Екранирайте изхода според контекста. Шаблонните системи в съвременните рамки екранират HTML по подразбиране. Рискът е на местата, където разработчик изключва това, за да изведе суров HTML. Оттам влиза cross-site scripting (XSS).
- Внимавайте с качените файлове: проверявайте реалния им тип, ограничавайте размера, преименувайте ги, пазете ги извън публичната директория или в отделно хранилище и никога не ги изпълнявайте.
- Не изтегляйте от сървъра произволни адреси, подадени от потребители, без списък с разрешени адреси. Иначе сървърът ви може да бъде използван за достъп до вътрешни системи.
#Тайни и чужд код
Пароли, ключове и други тайни
Паролите за базата данни, API ключовете, данните за достъп до платежния доставчик и ключовете за подписване са най-ценното в проекта ви.
- Не дръжте тайни в хранилището с кода. Зареждайте ги от променливи на средата или от мениджър на тайни и пазете в хранилището само примерен файл със заместители.
- Ако тайна някога е попадала в хранилището, смятайте я за изтекла и я сменете. Изтриването на реда не я маха от историята.
- Всяка среда трябва да има свои данни за достъп, за да не отвори изтичане от тестов сървър и реалната система.
- Давайте на всеки ключ само нужния достъп: потребител само за четене за справките, API ключ, ограничен до действията, които интеграцията използва.
- Знайте кой до какво има достъп и го отнемайте, когато някой напусне проекта. Как акаунтите да останат на ваше име, описваме в статията чий е кодът и акаунтите.
Библиотеки и обновления
Обикновено в едно приложение има много повече чужд код, отколкото код, писан специално за него. Всяка библиотека може да има публикувана уязвимост.
- Пазете в хранилището lock файла (
composer.lock,package-lock.jsonи подобни), за да работи всяка среда със същите версии. - Пускайте редовно проверка за уязвимости, например
composer auditилиnpm audit, или включете автоматичните известия в услугата, където държите кода. - Прилагайте бързо поправките за сигурност и дръжте рамката, езика и базата данни на версии, които още получават такива поправки.
- Махнете плъгините и пакетите, които никой не използва. Неизползваният код също трябва да се обновява.
#Резервни копия и логове
Сигурността включва и възстановяването. Когато нещо се обърка, трябва да разберете какво е станало и да можете да върнете данните.
Резервни копия:
- Архивирайте автоматично базата данни и качените файлове, пазете копията на място, отделно от сървъра, и пазете няколко поколения, за да може да върнете и проблем, открит късно.
- Проверявайте възстановяването по график. Копие, от което никога не е възстановявано, е само предположение.
- Пазете копията като реалните данни. В тях има същата лична информация.
Логове и известия:
- Записвайте събитията, свързани със сигурността: входове, неуспешни опити, смяна на парола, промяна на права, действия на администратори и износ на данни.
- Никога не записвайте пароли, пълни номера на карти, токени или идентификатори на сесии.
- Изпращайте грешките и необичайните модели, например вълна от неуспешни входове, до човек, който ще реагира.
- Пазете логовете достатъчно дълго, за да разследвате инцидент, забелязан седмици по-късно.
#OWASP Top 10 като отправна точка
OWASP Top 10 е широко използван списък на най-критичните рискове за сигурността на уеб приложенията. Издава го Open Worldwide Application Security Project и го преработва през няколко години. Той дава общ език на собственици и разработчици и е разумна база за преглед на кода, но не е пълен стандарт. За по-подробен списък OWASP издава и Application Security Verification Standard (ASVS). Винаги проверявайте, че четете актуалното издание на всеки от двата документа.
Няколко навика помагат списъкът да се спазва:
- Сервирайте всичко през HTTPS и задайте заглавки за сигурност като
Content-Security-PolicyиStrict-Transport-Security. - Показвайте общи страници за грешка в реалната среда и дръжте режима за отстраняване на грешки (debug) изключен.
- Във всеки преглед на код задавайте въпроса за сигурността: кой може да извика това и с какви данни.
- За приложения с плащания или чувствителни лични данни поръчайте независим тест за сигурност преди пускането и след големи промени.
Сигурността е постоянна работа. Тези проверки са част от редовната поддръжка след пускането, а не еднократен одит.
#Как може да помогне PN Scripts
PN Scripts изработва уеб приложения с автоматични тестове на критичните места като плащания, вход и данни, поддържа документацията актуална и продължава с обновленията след пускането толкова дълго, колкото клиентът желае. Когато поемаме съществуващ код, първо правим преглед. Ако искате да обсъдим приложение, което да изработим или да проверим, вижте страницата за уеб разработка по поръчка.
Коментари
Коментари
Напишете първия коментар.
Оставете коментар