Основи безпеки веб-додатків

Сучасна веб-розробка має багато викликів, і з цих питань безпека є дуже важливою і часто підкресленою. Хоча такі методи, як аналіз загроз, все частіше визнаються важливими для будь-якого серйозного розвитку, є також деякі основні практики, які кожен розробник може і повинен робити як звичайно.

безпеки

05 січня 2017 року

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

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

Зміст

  • Довіра
  • Відхилити несподіване введення форми
    • Недовірене введення
    • Перевірка вводу
    • На практиці
    • Коротко
  • Кодування виводу HTML
    • Вихідні ризики
    • Вихідне кодування
    • Застереження та застереження
    • Коротко
  • Параметри прив'язки для запитів до бази даних
    • Маленькі столи Боббі
    • Прив’язка параметрів до порятунку
    • Чистий та безпечний код
    • Поширені помилки
    • Функції прив'язки параметрів
    • Коротко
  • Захист даних під час транзиту
    • HTTPS та безпека транспортного рівня
    • Отримайте сертифікат сервера
    • Налаштуйте свій сервер
    • Використовуйте HTTPS для всього
    • Використовуйте HSTS
    • Захистіть файли cookie
    • Інші ризики
    • Перевірте свою конфігурацію
    • Коротко
  • Хешуйте і соліть паролі своїх користувачів
    • Жити небезпечно
      • Ризики
    • Я можу хешувати парольz
    • Тире солі
    • Використовуйте хеш, який вартий його солі
    • Ще раз із хешированием
    • Остаточні поради
    • Коротко
  • Безпечна автентифікація користувачів
    • Зрозумійте свої варіанти
    • Переатестуйте для важливих дій
    • Приховати, чи існують користувачі
    • Запобігання атакам грубої сили
    • Не використовуйте облікові дані за замовчуванням або з жорстким кодом
    • У рамках
    • Коротко
  • Захист сеансів користувачів
    • Створіть ідентифікатори безпечної сесії
    • Не виставляйте ідентифікатори сеансів
    • Захистіть свої файли cookie
    • Управління життєвим циклом сеансу
    • Перевірте це
    • У рамках
    • Коротко
  • Авторизуйте дії
    • Авторизуйтесь на сервері
    • Заборонити за замовчуванням
    • Авторизуйте дії над ресурсами
    • Використовуйте політику для авторизації поведінки
      • Впровадження RBAC
      • Впровадження ABAC
    • Інші способи моделювання політики
    • Міркування щодо впровадження
    • Коротко

Бічні панелі

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

Десь, внизу списку вимог, швидко, дешево та гнучко це «безпечно». Тобто, поки щось не піде не так, поки система, яку ви будуєте, не скомпрометована, тоді раптом безпека є, і завжди була, найголовнішим.

Безпека - це багатофункціональна проблема, подібна до продуктивності. І трохи не схожий на Performance. Як і ефективність, власники наших підприємств часто знають, що їм потрібна безпека, але не завжди впевнені, як оцінити їх кількісно. На відміну від Performance, вони часто не знають “достатньо безпечного”, коли бачать це.

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

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

Безпека - це велика тема, навіть якщо ми обмежимо сферу застосування лише веб-програмами на базі браузера. Ці статті будуть ближче до "найкращого", ніж вичерпний каталог усього, що вам потрібно знати, але ми сподіваємось, що це забезпечить спрямований перший крок для розробників, які намагаються швидко наростись.

Довіра

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

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

Відхилити несподіване введення форми

Форми HTML можуть створити ілюзію управління введенням. Автор розмітки форми може вважати, що оскільки вони обмежують типи значень, які користувач може ввести у форму, дані будуть відповідати цим обмеженням. Але будьте впевнені, це не більше, ніж ілюзія. Навіть перевірка форми JavaScript на стороні клієнта абсолютно не надає жодної цінності з точки зору безпеки.

Недовірене введення

У нашому масштабі довіри дані, що надходять із браузера користувача, незалежно від того, надаємо ми форму чи ні, і незалежно від того, захищено з'єднання HTTPS, фактично дорівнюють нулю. Користувач міг дуже легко змінити розмітку перед її відправленням або скористатися програмою командного рядка, як curl, щоб подати несподівані дані. Або абсолютно невинний користувач міг би мимоволі надіслати змінену версію форми з ворожого веб-сайту. Політика того самого походження не заважає ворожому веб-сайту подавати інформацію до кінцевої точки обробки вашої форми. Щоб забезпечити цілісність вхідних даних, перевірку потрібно обробляти на сервері.

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

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

Цей код може бути або не бути небезпечним, залежно від того, як реалізований метод sendError. Ми сподіваємось, що логіка подальшого потоку правильно обробляє ненадійний вміст. Це могло б. Але це може і не так. Нам значно краще, якщо ми зможемо повністю виключити можливість непередбачуваного потоку управління.

Отже, що може зробити розробник, щоб мінімізувати небезпеку того, що ненадійний ввід матиме небажані наслідки в коді програми? Введіть перевірка вхідних даних.

Перевірка вводу

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

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

Перевірка вхідних даних є більш ефективною для входів, які можуть бути обмежені невеликим набором. Числові типи зазвичай можуть бути обмежені значеннями в межах певного діапазону. Наприклад, немає сенсу для користувача вимагати переказу від’ємної суми грошей або додавання кількох тисяч предметів до свого кошика для покупок. Ця стратегія обмеження вхідних даних до відомих прийнятних типів відома як позитивна перевірка або білий список. Білий список може обмежуватися рядком певної форми, наприклад, URL-адресою або датою форми “рррр/мм/дд”. Це може обмежити довжину введення, одне прийнятне кодування символів або, для прикладу вище, лише значення, доступні у вашій формі.

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

Вам доведеться зробити вибір щодо того, що саме робити, коли введення не вдається перевірити. Найбільш обмежувальним і, можливо, найбажанішим є його повністю відхилити, без зворотного зв’язку, та переконатися, що інцидент зафіксований за допомогою реєстрації або моніторингу. Але чому без зворотного зв’язку? Чи повинні ми надавати своєму користувачеві інформацію про те, чому дані недійсні? Це трохи залежить від вашого контракту. У наведеному вище прикладі форми, якщо ви отримуєте будь-яке значення, крім "електронної пошти" або "тексту", відбувається щось забавне: у вас або є помилка, або на вас нападають. Крім того, механізм зворотного зв'язку може забезпечити точку атаки. Уявіть, що метод sendError записує текст назад на екран як повідомлення про помилку на кшталт "Ми не можемо відповісти за допомогою communicationType". Це все добре, якщо тип комунікації - "голуб-перевізник", але що станеться, якщо це буде виглядати так?

Тепер ви зіткнулися з можливістю відбивної атаки XSS, яка викрадає файли cookie сеансу. Якщо вам потрібно надати відгук користувачів, вам найкраще буде запропоновано відповідь, що не відображає ненадійних даних користувачів, наприклад "Ви повинні вибрати електронну пошту або текст". Якщо вам дійсно не вдається уникнути введення даних користувача на них, переконайтесь, що вони правильно закодовані (докладніше про кодування виводу див. Нижче).