Як шукати базу даних MySQL із зашифрованими полями


15

Припустимо , що мені потрібно , щоб зашифрувати певні таблиці-поля з в MySQL бази даних. Крім того, мені потрібно шукати деякі з тих полів, які я шифрував.

Як би можна було шукати ці поля в будь-якому випадку?

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

ОНОВЛЕННЯ 2012-09-07

Додавання додаткових подробиць до схеми бази даних було б добре , оскільки я збираюся реалізувати нову програму. Крім того, мені потрібно розширити програми, які зараз працюють у виробництві. Але навіть для цих застосувань було б добре додати більше деталей.

ОНОВЛЕННЯ 2012-09-08

Шифрування є ядром цього питання.

Обмеження доступу, запропоновані деякими відповідями, вже застосовуються, але не відповідають формальній вимозі шифрування даних.

Ця формальна вимога не є стандартом безпеки даних платіжних карток [PCI].

Відповіді:


11

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

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

Можливо, ви могли б розширити це, зробивши "повнотекстовий" індекс хешей, якщо вам потрібно, але це може ускладнитися дуже швидко.

ДОБАВЛЕННЯ

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

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

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

Він менш небезпечний для предметів з високим ступенем кардинальності, як-от SSN, номери кредитних карток, GUID тощо (але існують різні ризики [читайте: юридичні], пов’язані із їх зберіганням, тому я не схильний радити їх зберігати. ).

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

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

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


Обговорення цієї відповіді було переміщено до чату .
Пол Білий 9

5

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

Різні методи шифрування, що використовуються CryptDB, включають:

  • RND - цілком захищена схема шифрування IND-CPA, яка не пропускає ніякої інформації про дані (окрім її наявності та для типів змінної довжини, довжини), але дозволяє лише зберігання та пошук, без запитів.

  • DET - варіант RND, який є детермінованим, так що два однакових значення (в одному стовпці) шифруються в одному і тому ж шифротексті. Підтримує запити рівності форми WHERE column = 'constant'.

  • OPE - схема шифрування, що зберігає замовлення, яка підтримує запити нерівності, такі як WHERE column > 'constant'.

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

  • ПОШУК - схема, яка підтримує пошук за ключовими словами форми WHERE column LIKE '% word %'.

  • ПРИЄДНУЙТЕСЯ та OPE-JOIN , варіанти DET і OPE, які дозволяють порівнювати значення в різних стовпцях один з одним. Підтримка рівності та діапазону приєднується відповідно.

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

Якщо ви зацікавлені, радимо ознайомитись з документами, пов’язаними з веб-сайту CryptDB, зокрема "CryptDB: Захист конфіденційності при обробці зашифрованих запитів" Popa, Redfield, Zeldovich та Balakrishnan ( SOSP 2011 ). Ці документи також детальніше описують різні компроміси щодо безпеки та ефективності, пов'язані із підтримкою різних типів запитів.


1
It works by encrypting and decrypting data as it passes between the application and the database: Безумовно, це може спричинити проблеми, якщо дані, що шукаються, вже знаходяться в базі даних (зашифровані), але очевидно, що сам запит, який шукає базу даних, лише потім передається в CryptDB (а потім шифрується?). Я не можу зрозуміти, як цей метод може бути взагалі ефективним?
Мартін

3

Я не розумію, чому нинішні відповіді не поставили під сумнів вимоги в повному обсязі, тому я попрошу і залишу це як відповідь.

Які ділові причини? Які дані потрібно для шифрування і чому? Якщо ви шукаєте відповідність PCI, я можу написати есе.

Питання щодо вашої вимоги:

  • Вам потрібно буде повернути існування / не існує в результаті або фактичні дані?
  • Вам потрібна можливість LIKE '% OMG_SEKRIT%'?
  • Хто не може бачити дані та чому?

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

Обмежити за користувачем / роллю / api. Шифрувати на диску. Якщо ви зберігаєте важливіші дані, я хотів би дізнатися, чому ви використовуєте MySQL.


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

Які критерії "важливіших даних"?
арканін

2

Я розглядаю це і натрапив на ваше запитання. Я схиляюся до підходу, викладеного в розділі 5.4 статті "Практичні методи пошуку зашифрованих даних" http://www.cs.berkeley.edu/~dawnsong/papers/se.pdf

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


1

Програмно, ефективне рішення - це

  1. отримати ВСІ записи на ТОЛЬКО те поле, в якому ви шукаєте, з ідентифікатором запису
  2. розшифруйте їх у тимчасову таблицю
  3. виконати пошук по цій таблиці
  4. використовуйте ідентифікатори для отримання повних записів (усіх полів), які відповідають критеріям пошуку
  5. розшифруйте їх та поверніть їх користувачеві

Справа в тому, що 1 і 4 є значно меншими наборами даних, ніж отримання та розшифрування всіх полів усіх записів на початку.

Сподіваюся, що це допомагає.


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

1

Це можливо завдяки повному функціоналу пошуку, використовуючи функції внутрішнього шифрування MYSQL.

Ось приклад:

!!! Я ВИКОРИСТОВУЮ MYSQL ENCODE () ТУТ ДЛЯ ПРОСТОЛЬКОСТІ, MYSQL_ENCODE СЕЙЧАС НЕБЕЗПЕЧЕНО ЗАБЕЗПЕЧЕНО, ВИКОРИСТОВУЙТЕ ОДНУ ІНТЕРНЕТУ ФУНКЦІЇ MYSQL ВСТАНОВИТИ !!!

UPDATE my_table
SET field=ENCODE('my_data', 'my_password')
WHERE ID=1;

SELECT DECODE(field, 'my_password') as field FROM my_table
WHERE field LIKE 'data';

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

Якщо ви робите це в додатку, такому як php, ви можете це зробити у вашому db шлюзі чи сховищах класів, зберігаючи список / масив зашифрованих стовпців кожної таблиці у відповідному класі шлюзу.

class UserGateway
{
    protected $encrypted_fields = array(
        'username',
        'email'
    );

    public function get($fields, ...)
    {
        foreach ($fields as $k => $field) {
            if (in_array($field, $fields)) {
                $fields[$k] = $this->decodeSelect($field);
            }
        }

        $sql = 'SELECT '.implode(',', $fields);

        //......
    }

    protected function decodeSelect($field)
    {
        return "DECODE($field, $pass) AS $field";
    }
}

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


-1

Припускаючи, що ви шукаєте в SQL і проти повного значення, а не часткового (наприклад, LIKE 'value%') ... при захопленні даних пошуку, зашифруйте ці дані за допомогою того самого алгоритму, який застосовувався під час шифрування даних, і шукайте їх.

Наприклад:

Що було б:

SELECT FieldA, FieldB 
FROM Table1 
WHERE FieldC = 'Value'

Може замість цього виглядати:

SELECT FieldA, FieldB 
FROM Table1 
WHERE FieldC = 'hsk&%67ghhks83'

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