Як я можу захистити ім’я користувача та пароль MySQL від декомпіляції?


87

.classФайли Java можна досить легко декомпілювати. Як я можу захистити свою базу даних, якщо мені потрібно використовувати дані для входу в код?


Сподіваюся, ви не проти, що я повторно позначив ваше запитання. Я видалив "ім'я користувача" та "пароль" і додав "зворотне проектування" та "декомпіляцію". Я думаю, що вони є більш описовими, ніж оригінали. До речі, відмінне запитання про основи!
Вільям Брендель

6
Зверніть увагу, що той факт, що ви використовуєте Java, насправді тут не є актуальним. Наявність жорстко закодованих паролів будь-якою мовою проблематично майже однаково ("strings thebinary" так само добре відображає константи рядків у програмах C).
Йоахім Зауер

@saua: Правда, але, можливо, хтось опублікує якийсь зразок коду, як розділити імена користувачів та паролі в Java. Я навіть міг би зробити це сам, якщо маю час.
Вільям Брендель

1
Я помітив, що багато відповідей вважають, що ви намагаєтеся приховати ім'я користувача / паролі від несанкціонованого користувача, поки користувач, який запускає програму, у порядку. Я вважаю, що ви хочете приховати пароль від ВСІХ . Будь ласка, поясніть це у питанні.
pek

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

Відповіді:


123

Ніколи не вводьте жорсткий код паролів у свій код. Це нещодавно було піднято в Топ-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 налаштувань і прочитати облікові дані для входу, але це не є ризиком для безпеки, оскільки користувач знав ці дані для початку.

Другий випадок: спроба приховати облікові дані для входу від користувача

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

Правильний випадок: Використання багаторівневої архітектури

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

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

Основний порядок операцій:

  1. Клієнт виконує автентифікацію за рівнем бізнес-логіки, використовуючи особисте ім’я користувача / пароль користувача. Ім'я користувача та пароль відомі користувачеві і жодним чином не пов'язані з обліковими даними для входу в базу даних.
  2. Якщо автентифікація успішна, клієнт робить запит до рівня бізнес-логіки з проханням отримати інформацію з бази даних. Наприклад, інвентаризація продукції. Зверніть увагу, що запит клієнта не є запитом SQL; це віддалений виклик процедури, такий як getInventoryList.
  3. Рівень бізнес-логіки підключається до бази даних і отримує запитувану інформацію. Рівень бізнес-логіки відповідає за формування безпечного запиту SQL на основі запиту користувача. Будь-які параметри запиту SQL слід дезінфікувати, щоб запобігти атакам ін'єкції SQL.
  4. Рівень бізнес-логіки надсилає список запасів назад до клієнтської програми.
  5. Клієнт відображає користувачеві інвентарний список.

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


4
Як саме це заважає комусь отримати ім’я користувача / пароль? Тоді ви не можете просто прочитати його з файлу?
Джо Філліпс,

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

Я думаю, що ідея полягає в тому, що користувач, який запускає програму, не той, від кого ви намагаєтесь утримати її. Якщо це так, то вам доведеться його зашифрувати.
Michael Haren

Так, Майкл має рацію. По суті, ідея полягає в тому, що ви вже знаєте ім’я користувача / пароль, тому немає необхідності приховувати його від себе. Однак це буде приховано від інших користувачів через дозволи файлів.
Вільям Брендель

7
Якщо ви розгортаєте (приклад) додаток для редагування БД для користувача, і ви не хочете, щоб він знав ім'я користувача та пароль бази даних, то ви неправильно сконструювали рішення, і клієнтське програмне забезпечення повинно спілкуватися із сервером (через наприклад, веб-сервіс), який виконує роботи з БД.
JeeBee

15

Введіть пароль у файл, який програма прочитає. НІКОЛИ не вбудовуйте паролі у вихідний файл. Період.

Для такого використання Ruby має маловідомий модуль DBI :: DBRC . Я не сумніваюся, що Java має еквівалент. У будь-якому випадку, це не складно написати.


7
Хоча це трохи спрощує зміну паролів пізніше, це не вирішує основну проблему безпеки.
Brian Knoblauch

Так. Дивіться також відповідь Вільяма Бренделя.
Келтія

1
Метод, який ми з Келтією зазначили, є загальноприйнятим способом вирішення цієї проблеми. Від'єднання облікових даних для входу від скомпільованого коду є однією з найосновніших практик захисту програмного забезпечення. Поміщення облікових даних для входу в окремий файл є ефективним способом досягнення цього.
Вільям Брендель

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

4
Добре, тому файл може прочитати лише користувач, який запускає програму. Чудово. Це нічого не вирішує. :-) Я, користувач , який ми намагаємося зберегти пароль в таємниці від, може читати його так само легко , як додаток ...
Брайан Knoblauch

3

Ви пишете веб-програму? Якщо так, використовуйте JNDI, щоб налаштувати його зовні для програми. Огляд доступний тут :

JNDI забезпечує єдиний спосіб для програми знаходити та отримувати доступ до віддалених послуг через мережу. Віддаленою послугою може бути будь-яка корпоративна послуга, включаючи службу обміну повідомленнями або службу, яка стосується конкретного додатка, але, звичайно, програма JDBC зацікавлена ​​головним чином у службі баз даних. Як тільки об’єкт DataSource створений та зареєстрований у службі імен JNDI, програма може використовувати API JNDI для доступу до цього об’єкта DataSource, який потім можна використовувати для підключення до джерела даних, яке він представляє.


надане посилання погане
Джеймс Оравець

2

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

Найкращий спосіб - ніде не зберігати паролі. Це досягається використанням хеш-функцій для генерації та зберігання хеш-паролів:

hash("hello") = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
hash("hbllo") = 58756879c05c68dfac9866712fad6a93f8146f337a69afe7dd238f3364946366

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

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

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

  1. Ваш користувач вводить облікові дані, і це перевіряється на основі хешу паролів
  2. Генеруються та зберігаються хеші паролів, а не паролі
  3. Хеші виконуються кілька разів
  4. Хеші генеруються за допомогою випадково сформованої солі
  5. Хеші шифруються приватним ключем
  6. Закритий ключ зберігається у фізично іншому місці, ніж хеші
  7. Приватні ключі оновлюються за часом
  8. Зашифровані хеші діляться на шматки
  9. Ці шматки зберігаються у фізично окремих місцях

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

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

Наприклад, припустимо, що крок 1 не є прийнятним рішенням для вашого проекту. Ви не хочете, щоб користувачі щоразу вводили пароль, або ви навіть не хочете / потребуєте, щоб користувачі знали пароль. Все-таки у вас десь є конфіденційна інформація, і ви хочете захистити її. У вас проста програма, немає сервера для зберігання ваших файлів, або це занадто багато клопоту для вашого проекту. Ваша програма працює в середовищах, де неможливо надійно зберігати файли. Це один з найгірших випадків, але все ж за допомогою додаткових заходів безпеки ви можете отримати набагато безпечніше рішення. Наприклад, ви можете зберігати конфіденційну інформацію у файлі, а також можете зашифрувати файл. У коді можна жорстко закодувати приватний ключ шифрування. Ви можете заплутати код, тому ви ускладнюєте комусь його зламати.це посилання . (Я хочу ще раз попередити вас, що це не на 100% безпечно. Розумний хакер, який володіє належними знаннями та інструментами, може це зламати. Але, виходячи з ваших вимог та потреб, це може бути досить хорошим рішенням для вас).


1

Це запитання показує, як зберігати паролі та інші дані у зашифрованому файлі: 256-бітове шифрування за допомогою пароля AES Java


1
Десь у вихідному коді все ще потрібно розшифрувати зашифрований пароль для створення з'єднання. Цей розглянутий пароль все ще є.
Bear0x3f

0

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


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