Навіщо взагалі зберігати паролі користувачів?


10

Іноді я бачу запитання, як безпечно зберігати паролі користувачів для веб-програми (використовуючи RDBMS, я не говорю про Facebook чи Twitter). Звичайна відповідь - "соліть пароль, потім хешуйте його за допомогою сильного алгоритму, такого як TDES або SHA512".

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

Наприклад, якщо якийсь користувач X хоче створити пароль користувача облікового запису Y у своїй веб-програмі, як неправильно видавати такий запит:

CREATE USER X WITH ENCRYPTED PASSWORD Y IN GROUP baseuser;

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

Я бачу численні переваги цього методу:

  • Якщо RDBMS вирішить, що алгоритм шифрування потрібно змінити, мені не потрібно нічого торкатися, лише застосувати оновлення безпеки;
  • Мені легко керувати авторизаціями користувачів. Якщо користувач переходить на роль адміністратора, мені просто потрібно додати користувача до відповідної групи;
  • Ін'єкції SQL тепер безглузді, оскільки я керую дозволами, щоб дозволити саме те, що я хочу дозволити кожному користувачеві в базі даних (наприклад, на форумі, як SO, додавання нових публікацій, відповіді на повідомлення, коментування та редагування / видалення власних питань / відповіді / коментарі);
  • Обліковий запис користувача "анонімний" можна використовувати для несанкціонованого підключення до моєї програми;
  • Кожен користувач є власником наданих ним даних.

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

Примітка. Третій пункт дозволений політикою в PostgreSQL та політикою безпеки в Microsoft SQL Server. Я усвідомлюю, що ці поняття є новичками, але все одно, тепер, коли вони є тут, чому техніка, яку я описую, не стала стандартним способом обробки облікових записів користувачів?


2
Коментарі не для розширеного обговорення; ця розмова була переміщена до чату .
Пол Білий 9

До речі, звичайна відповідь неправильна. Ви повинні посолити пароль, а потім хеш- код з повільним алгоритмом, таким як bcrypt або argon2.
Тгр

Відповіді:


27

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

Як DBA, мені не хочеться керувати на рівні бази даних 10 000 активними користувачами середніх веб-додатків середнього розміру, або, можливо, 2+ мільйонів користувачів якогось раптово популярного додатка.

По-справжньому, це різниця у філософії між розробниками додатків та розробниками баз даних / DBA.

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

У деяких випадках це може бути недалекоглядним; у багатьох RDBMS є дивовижні функції, які можуть значно полегшити життя розробників додатків (безпека на рівні рядків, стовпчикові індекси, зберігання файлових потоків тощо).

Але деякі з цих функцій кулера доступні лише в новіших версіях, і організації не завжди швидко модернізують існуючі середовища (див. Цей графік з 2014 року ).

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


2
Існує "свята війна" в тому, чи буде бізнес-логіка в додатку чи в базі даних. Якщо ви створили додаток, у якому вся бізнес-логіка (зокрема безпека) знаходиться в базі даних (з використанням збережених процедур, поглядів тощо), можливо, може бути аргумент щодо використання механізмів захисту бази даних, оскільки ніхто не може безпосередньо підключитися і обійти ваш безпека. Я повністю погоджуюся, що вам слід уникати "перебудови" механізму захисту (тобто логін / пароль) у спеціальній таблиці. Чому це робити, коли у вас вже є активна безпека каталогу / O365.
Nick.McDermaid

1
@ Nick.McDermaid Мені подобається переконатись, що я досить добре змішую бізнес-логіку між БД і додатком, щоб допомогти усунути потенціал майбутніх розробників, щоб вони мали будь-яку підказку, що відбувається, а також допомагає мені підтримувати безпеку своєї роботи, оскільки ніхто не божевільний достатньо, щоб хотіти ним керувати.
Der Kommissar


8

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

Я б краще не давав додаткам (им) дозволів, необхідних для управління об'єктами схеми (логіни, користувачі та дозволи), оскільки потрібні нові користувачі, а старі залишають, тому що якщо ця програма зламається, зловмисник має доступ до цих прав полегшуючи подальше розтріскування бази даних. У MS SQL Server, якщо ви не використовуєте повністю містяться бази даних, входи в систему сервера, тому вам потрібно роздавати права за межі єдиної бази даних, що робить це ще більш ризикованим.

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

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


1
Гаразд, тому "додаток не повинно змінювати схему" є, на мою думку, першим хорошим моментом проти методики, яку я пропоную. Однак анонімний обліковий запис, здатний створювати нових користувачів, повинен створювати нових користувачів із самим основним доступом. Лише адміністратори можуть рекламувати користувачів та видаляти користувачів, що, напевно, потрібно шукати в додатках :-) Загальні дані видимі анонімному користувачеві, тому це з'єднання може використовуватися для вмісту, де автентифікація не потрібна. Переносність - це також хороший момент, але я думаю, що користувацькі команди зараз є частиною стандарту (не впевнений, чи не було років тому)
Fabian Pijcke

До речі, за допомогою цього параметра, якщо хакер отримає доступ до бази даних як анонімний користувач, він зможе створити стільки користувачів, скільки захоче, але це не проблема безпеки, він також міг би точно роздути базу даних за допомогою одного з створені облікові записи, це буде дратувати, але знову ж ніякого питання безпеки (і він міг би це зробити, використовуючи стандартний інтерфейс, все одно, це буде набагато повільніше: p)
Fabian Pijcke

3
Я погоджуюся, що з точки зору безпеки користувачі на рівні бази даних були б кращими. Однак в принципі неможливо керувати, наприклад, інтернет-магазинами, де у вас може бути 50 мільйонів зареєстрованих користувачів. Кожен з них повинен бути користувачем бази даних. Плюс: зазвичай це не добре працює з веб-програмами, що використовують пул підключень.
a_horse_with_no_name

6

Перестановка питання

Навіщо взагалі зберігати паролі користувачів?

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

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

Але те, що ви насправді запитуєте, це

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

Безпека

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

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

У шарах цибулі безпеки нормальною системою є:

  • База даних, яка дозволяє лише з'єднання з певних машин.
  • База даних дозволяє лише з'єднання як певні комбінації користувача / пароля.
  • Сервери з дозволами бази даних, які дозволяють з'єднання з додатками.
  • Програми запускаються на сервері.
  • Програми мають інформацію про підключення до бази даних з обмеженими привілеями.
  • Програми аутентифікують користувачів, перш ніж вони дозволяють змінювати базу даних (за винятком можливостей створення нових облікових записів).

У цій системі:

  • Кінцеві користувачі знають комбінації користувачів / паролів, які будуть працювати в базі даних, правда, з дуже низькими привілеями.
  • Потрібно лише створити сервер або переконливо прикинутися авторизованим сервером.

Ми втратили весь рівень безпеки програми. І ми добровільно відмовилися від частини шару бази даних. Тож нам потрібні лише два подвиги:

  1. Підробляти або компрометувати авторизований сервер.
  2. Збільшити доступ до облікового запису з обмеженими правами.

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

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

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


5

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

Щоб продовжити ваш приклад із stackexechange: Як би ви зробили видалену публікацію видимою лише високопоставленому користувачеві? Тому для правил доступу вам все одно знадобиться логіка в коді. Замість того, щоб поділяти логіку доступу між правилами бази даних та прикладними правилами доступу, більшість розробників вважають за краще їх розміщувати в одному місці.

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

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

Інший момент: як би ви створили пул зв’язків? Я знаю лише jdbc (java <-> db), і вам потрібно надати ім'я користувача + пароль, щоб отримати з'єднання, яке ви зможете потім об'єднати.

Я подумав про деякі інші моменти, які буде важче / складніше здійснити, ніж усталеним способом:

  • обробка відновлення пароля
  • Через 2 роки після первинної реалізації менеджер продукту попросить вас додати підтримку схеми oauth або дозволити подвійний фактор auth

Щось на зразок CREATE POLICY deleted_posts_high_rep ON posts FOR SELECT TO baseuser USING ((SELECT rep FROM users WHERE name = current_user()) > 10000)відповідає на ваше перше запитання. Я ніколи не говорив, що мені вже не потрібна таблиця користувачів, і забезпечити синхронізацію з таблицею користувачів db дещо складно, але можливо. Основним моментом обговорюваної техніки є безпека. Що стосується пулу підключень, я працюю з OCaml, і я повинен сказати, що не розумію, чому мені потрібен пул з'єднань. Зараз я використовую хеш-карту, пов’язану значеннями файлів cookie з 0-арними функціями, що повертають з'єднання :-)
Fabian Pijcke,

5
Пул підключень реалізований для підвищення продуктивності: з ними вам не потрібно встановлювати з'єднання для кожного запиту користувача (тому ви зберігаєте cpu / io / затримку при створенні tcp-посилання + все з'єднання та обмін аутентифікацією з базою даних). Що стосується визначення політики: ваша база даних буде постійно перевіряти право доступу на кожен доступ до даних, навіть коли ви вже перевіряли їх один раз. Також "заборонено чи заборонено доступ" не є "ОК, немає результату". Не впевнені, що хлопці з охорони праці віддають перевагу версії ОК.
Тьєррі

3
Фабіан, об'єднання з'єднань є основоположним у будь-якому масштабі, це дійсно дефолт, який ви навіть не могли б використовувати. Ось кілька орієнтирів, щоб дати вам уявлення про те, наскільки це важливо: підвищення продуктивності в 600 разів із об'єднанням з'єднань ( vladmihalcea.com/2014/04/17/the-anatomy-of-connection-pooling ) та збільшення продуктивності на понад 4000 разів із об'єднання з'єднань ( progress.com/tutorials/jdbc/… ). Це кілька порядків різниці величин, це не "приємно мати", програми перестали б зупинятися без цього.
Іван МакА

1
Цікаві цифри. І справді, я ніколи не бачив програми, яка не використовує пули підключення. Але я не знав (і очікував), щоб вони зробили стільки прискорень. Інший аспект, який ви отримуєте з пулом підключень, - це контроль над ресурсами: завдяки їм величезний приріст клієнта, який намагається з'єднати все відразу, зробить вашу програму повільною, але на вашу базу даних це не вплине сильно (якщо пул добре налаштований) .
Тьєррі

Гаразд, я просто шукав додаткову інформацію про пули підключення, і я погоджуюся, що це дуже вірний момент, як тільки веб-сайт повинен обробляти більше ста підключень в секунду, що не так вже й багато. Здається, що кожне з'єднання в PostgreSQL їсть близько 10 Мбіт оперативної пам’яті! Я ніколи не думав, що це так багато.
Фабіан Піцке

1

Ще один момент: багато [1] веб-додатків дозволяють вам зареєструвати та створити обліковий запис користувача в режимі он-лайн через сам додаток. Це означає, що ваш анонімний користувач (який повинен мати найменші привілеї, які можна було б припустити) повинен мати права створювати користувачів та надавати привілеї!

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

Я знаю, що на одному рівні ця проблема все одно існує, але у вас є шари захисту, особливо до видалення даних, якщо ви не дозволяєте веб-додатку керувати користувачами БД.

Також це запобіжить будь-якому використанню об'єднаних або повторно використаних з'єднань БД.

[1] Більшість я б сказав, але не цифри, які підтверджують це

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.