.class
Файли Java можна досить легко декомпілювати. Як я можу захистити свою базу даних, якщо мені потрібно використовувати дані для входу в код?
.class
Файли Java можна досить легко декомпілювати. Як я можу захистити свою базу даних, якщо мені потрібно використовувати дані для входу в код?
Відповіді:
Ніколи не вводьте жорсткий код паролів у свій код. Це нещодавно було піднято в Топ-25 найнебезпечніших помилок програмування :
Твердо кодувати секретний рахунок і пароль у своєму програмному забезпеченні надзвичайно зручно - для досвідчених інженерів-реверсистів. Якщо пароль однаковий у всьому вашому програмному забезпеченні, тоді кожен клієнт стає вразливим, коли цей пароль неминуче стає відомим. І оскільки це жорстко закодовано, виправити це величезний біль.
Ви повинні зберігати інформацію про конфігурацію, включаючи паролі, в окремому файлі, який програма читає під час запуску. Це єдиний реальний спосіб запобігти витоку пароля в результаті декомпіляції (ніколи не компілюйте його в двійковий файл для початку).
Для отримання додаткової інформації про цю поширену помилку ви можете прочитати статтю CWE-259 . Стаття містить більш ретельне визначення, приклади та багато іншої інформації про проблему.
У Java один з найпростіших способів це зробити - використовувати клас Preferences. Він призначений для зберігання всіляких налаштувань програми, деякі з яких можуть містити ім’я користувача та пароль.
import java.util.prefs.Preferences;
public class DemoApplication {
Preferences preferences =
Preferences.userNodeForPackage(DemoApplication.class);
public void setCredentials(String username, String password) {
preferences.put("db_username", username);
preferences.put("db_password", password);
}
public String getUsername() {
return preferences.get("db_username", null);
}
public String getPassword() {
return preferences.get("db_password", null);
}
// your code here
}
У наведеному вище коді ви можете викликати setCredentials
метод після відображення діалогового вікна askign для імені користувача та пароля. Коли вам потрібно підключитися до бази даних, ви можете просто використовувати методи getUsername
і getPassword
для отримання збережених значень. Реєстраційні дані не будуть жорстко закодовані у ваші двійкові файли, тому декомпіляція не представлятиме ризику для безпеки.
Важлива примітка: Файли налаштувань - це просто текстові XML-файли. Обов’язково вживайте відповідних заходів, щоб не дозволити несанкціонованим користувачам переглядати необроблені файли (дозволи UNIX, дозволи Windows тощо). Принаймні, в Linux це не проблема, оскільки виклик Preferences.userNodeForPackage
створить файл XML у домашньому каталозі поточного користувача, який і так не читається іншими користувачами. У Windows ситуація може бути іншою.
Більш важливі примітки: У коментарях до цієї відповіді та інших було багато дискусій щодо того, яка правильна архітектура для цієї ситуації. В оригінальному запитанні насправді не згадується контекст, в якому використовується додаток, тому я розповім про дві ситуації, яких я можу подумати. Перший - це випадок, коли особа, яка використовує програму, вже знає (і уповноважена знати) облікові дані бази даних. Другий - випадок, коли ви, розробник, намагаєтесь зберегти таємницю облікових даних бази даних від особи, яка використовує програму.
Перший випадок: користувач має право знати облікові дані для входу в базу даних
У цьому випадку згадане вище рішення буде працювати. Клас Java Preference
зберігатиме ім’я користувача та пароль у звичайному тексті, але файл налаштувань читатиме лише авторизований користувач. Користувач може просто відкрити файл XML налаштувань і прочитати облікові дані для входу, але це не є ризиком для безпеки, оскільки користувач знав ці дані для початку.
Другий випадок: спроба приховати облікові дані для входу від користувача
Це більш складний випадок: користувач не повинен знати облікові дані для входу, але все одно потребує доступу до бази даних. У цьому випадку користувач, який запускає додаток, має прямий доступ до бази даних, що означає, що програма повинна знати облікові дані для входу заздалегідь. Рішення, про яке я згадав вище, не підходить для цього випадку. Ви можете зберігати облікові дані бази даних у файлі налаштувань, але користувач зможе прочитати цей файл, оскільки вони будуть власником. Насправді дійсно не існує хорошого способу безпечного використання цієї справи.
Правильний випадок: Використання багаторівневої архітектури
Правильний спосіб зробити це - мати середній рівень, між сервером бази даних і вашим клієнтським додатком, який автентифікує окремих користувачів і дозволяє виконувати обмежений набір операцій. Кожен користувач мав би власні облікові дані для входу, але не для сервера баз даних. Повноваження дозволяли б доступ до середнього рівня (рівень бізнес-логіки) і були б різними для кожного користувача.
Кожен користувач мав би своє власне ім'я користувача та пароль, які можна було б зберігати локально у файлі налаштувань без будь-якого ризику безпеки. Це називається трирівневою архітектурою (ярусами є ваш сервер баз даних, сервер бізнес-логіки та клієнтська програма). Це складніше, але насправді це найбезпечніший спосіб зробити подібні речі.
Основний порядок операцій:
getInventoryList
.Зверніть увагу, що протягом усього процесу клієнтська програма ніколи не підключається безпосередньо до бази даних . Рівень бізнес-логіки отримує запит від автентифікованого користувача, обробляє запит клієнта на список інвентаризації і лише потім виконує запит SQL.
Введіть пароль у файл, який програма прочитає. НІКОЛИ не вбудовуйте паролі у вихідний файл. Період.
Для такого використання Ruby має маловідомий модуль DBI :: DBRC . Я не сумніваюся, що Java має еквівалент. У будь-якому випадку, це не складно написати.
Ви пишете веб-програму? Якщо так, використовуйте JNDI, щоб налаштувати його зовні для програми. Огляд доступний тут :
JNDI забезпечує єдиний спосіб для програми знаходити та отримувати доступ до віддалених послуг через мережу. Віддаленою послугою може бути будь-яка корпоративна послуга, включаючи службу обміну повідомленнями або службу, яка стосується конкретного додатка, але, звичайно, програма JDBC зацікавлена головним чином у службі баз даних. Як тільки об’єкт DataSource створений та зареєстрований у службі імен JNDI, програма може використовувати API JNDI для доступу до цього об’єкта DataSource, який потім можна використовувати для підключення до джерела даних, яке він представляє.
Незалежно від того, що ви робите, конфіденційна інформація буде десь зберігатися в якомусь файлі. Ваша мета - якомога важче дістатись. Скільки цього ви зможете досягти, залежить від вашого проекту, потреб та товщини гаманця вашої компанії.
Найкращий спосіб - ніде не зберігати паролі. Це досягається використанням хеш-функцій для генерації та зберігання хеш-паролів:
hash("hello") = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
hash("hbllo") = 58756879c05c68dfac9866712fad6a93f8146f337a69afe7dd238f3364946366
Алгоритми хеш-функції є односторонніми функціями. Вони перетворюють будь-яку кількість даних у "відбиток пальця" фіксованої довжини, який неможливо змінити. Вони також мають властивість, що якщо вхідні дані змінюються хоча б на крихітний біт, отриманий хеш зовсім інший (див. Приклад вище). Це чудово підходить для захисту паролів, оскільки ми хочемо зберігати паролі у формі, яка захищає їх, навіть якщо сам файл пароля скомпрометований, але в той же час ми повинні мати можливість перевірити правильність пароля користувача.
Примітка, не пов’язана з цим. За старих часів Інтернету, коли ви натискаєте посилання „забув мій пароль”, веб-сайти надсилатимуть вам електронний лист із паролем у звичайному тексті. Вони, мабуть, десь зберігали їх у базі даних. Коли хакери отримали доступ до своєї бази даних, вони отримали доступ до всіх паролів. Оскільки багато користувачів використовують один і той же пароль на кількох веб-сайтах, це була величезна проблема безпеки. На щастя, в наш час це не є звичною практикою.
Тепер постає питання: який найкращий спосіб зберігати паролі? Я вважав би це рішення (аутентифікація та управління послугами користувача stormpath) досить проклятим ідеальним:
Очевидно, що ви не гугл чи банк, тому це рішення для вас надмірне. Але тоді виникає питання: Скільки безпеки вимагає ваш проект, скільки часу та грошей у вас є?
Для багатьох програм, хоча і не рекомендується, зберігання жорстко закодованого пароля в коді може бути досить хорошим рішенням. Однак, легко додавши кілька додаткових кроків безпеки із наведеного вище списку, ви можете зробити свою програму набагато безпечнішою.
Наприклад, припустимо, що крок 1 не є прийнятним рішенням для вашого проекту. Ви не хочете, щоб користувачі щоразу вводили пароль, або ви навіть не хочете / потребуєте, щоб користувачі знали пароль. Все-таки у вас десь є конфіденційна інформація, і ви хочете захистити її. У вас проста програма, немає сервера для зберігання ваших файлів, або це занадто багато клопоту для вашого проекту. Ваша програма працює в середовищах, де неможливо надійно зберігати файли. Це один з найгірших випадків, але все ж за допомогою додаткових заходів безпеки ви можете отримати набагато безпечніше рішення. Наприклад, ви можете зберігати конфіденційну інформацію у файлі, а також можете зашифрувати файл. У коді можна жорстко закодувати приватний ключ шифрування. Ви можете заплутати код, тому ви ускладнюєте комусь його зламати.це посилання . (Я хочу ще раз попередити вас, що це не на 100% безпечно. Розумний хакер, який володіє належними знаннями та інструментами, може це зламати. Але, виходячи з ваших вимог та потреб, це може бути досить хорошим рішенням для вас).
Це запитання показує, як зберігати паролі та інші дані у зашифрованому файлі: 256-бітове шифрування за допомогою пароля AES Java
MD5 є алгоритмом хешування, а не алгоритмом шифрування, коротше кажучи, ви не можете повернутися до хешу, а можете лише порівнювати. В ідеалі його слід використовувати під час зберігання інформації про автентифікацію користувача, а не db ім'я користувача та пароль. db ім'я користувача та pwd повинні бути зашифровані та зберігатися у конфігураційному файлі, щоб зробити щонайменше.