Cara mencari database MySQL dengan bidang terenkripsi

15

Misalkan saya perlu mengenkripsi tabel-bidang tertentu dari database MySQL . Selain itu, saya perlu mencari beberapa bidang yang saya enkripsi.

Bagaimana cara mencari bidang itu?

Mengurai sandi setiap langkah demi langkah bukanlah pilihan: Misalkan saya memiliki beberapa dari ribuan catatan. Butuh terlalu banyak waktu dan ruang untuk mendekripsi setiap catatan dan memeriksa apakah setiap rekaman cocok dengan pencarian.

UPDATE 2012-09-07

Menambahkan rincian lebih lanjut ke skema database akan baik-baik saja , karena saya akan mengimplementasikan aplikasi baru. Selanjutnya, saya perlu memperluas aplikasi yang sedang berjalan dalam produksi. Tetapi bahkan untuk aplikasi itu, menambahkan rincian lebih lanjut tidak masalah

UPDATE 2012-09-08

Enkripsi adalah inti dari pertanyaan ini.

Pembatasan akses, seperti yang diusulkan oleh beberapa jawaban, sudah berlaku - tetapi tidak sesuai dengan persyaratan formal untuk mengenkripsi data.

Persyaratan formal ini bukan Standar Keamanan Data Industri Kartu Pembayaran [PCI].

SteAp
sumber

Jawaban:

11

Jelas mereka tidak dimaksudkan untuk dilihat, oleh karena itu mencari mereka akan bermasalah.

Salah satu trik yang saya gunakan di masa lalu adalah dengan hash data terenkripsi sebelum mengenkripsi itu, dan menyimpan hash di kolom yang diindeks. Tentu saja, ini hanya berfungsi jika Anda mencari seluruh nilai; nilai parsial tidak akan memiliki hash yang sama.

Anda mungkin bisa memperpanjang ini dengan membuat indeks hash "teks lengkap", jika perlu, tetapi bisa menjadi rumit dengan sangat cepat.

TAMBAHAN

Disarankan agar saya menambahkan catatan kaki pada jawaban saya per debat yang cukup panjang dalam obrolan tentang kerentanan terhadap serangan kamus, jadi saya akan membahas risiko keamanan potensial ini dengan pendekatan di atas.

Serangan Kamus: Serangan kamus adalah ketika seseorang melakukan pra-hash daftar nilai yang diketahui, dan membandingkan hash dengan kolom hash Anda dalam database. Jika mereka dapat menemukan kecocokan, kemungkinan bahwa nilai yang diketahui sebenarnya adalah apa yang hash (meskipun tidak pasti, karena hash tidak dijamin unik). Ini biasanya dimitigasi dengan hashing nilai dengan "garam" acak ditambahkan atau didahului sehingga hash tidak akan cocok dengan kamus, tetapi jawaban di atas tidak dapat menggunakan garam karena Anda kehilangan pencarian.

Serangan ini berbahaya ketika berurusan dengan hal-hal seperti kata sandi: jika Anda membuat kamus hash kata sandi populer, Anda kemudian dapat dengan cepat mencari nilai hash dan mengidentifikasi pengguna yang memiliki kata sandi seperti itu dan secara efektif mengekstraksi kredensial untuk mencuri identitas pengguna itu. .

Itu tidak terlalu berbahaya untuk barang-barang dengan tingkat kardinalitas tinggi, seperti SSN, nomor kartu kredit, GUID, dll. (Tetapi ada risiko berbeda [baca: legal] terkait dengan menyimpannya, jadi saya tidak cenderung menyarankan untuk menyimpannya) ).

Alasannya adalah agar serangan kamus berfungsi, Anda harus membuat kamus yang berisi nilai-nilai yang mungkin dan hash-nya. Secara teori, Anda dapat membuat kamus dari semua SSN yang mungkin (satu miliar baris, dengan asumsi semua permutasi pemformatan dihapus; beberapa lusin trilyunan entri untuk kartu kredit) ... tetapi itu biasanya bukan titik serangan kamus, dan pada dasarnya menjadi sebanding dengan serangan brute-force di mana Anda secara sistematis menyelidiki setiap nilai.

Anda juga dapat mencari SSN atau nomor kartu kredit tertentu , jika Anda mencoba mencocokkan SSN dengan seseorang. Sekali lagi, biasanya bukan titik serangan kamus, tetapi mungkin dilakukan, jadi jika ini adalah risiko yang perlu Anda hindari, jawaban saya bukanlah solusi yang baik untuk Anda.

Jadi begitulah. Seperti semua data terenkripsi, biasanya dienkripsi karena suatu alasan, jadi waspadai data Anda dan apa yang Anda coba lindungi.

Jeremy Holovacs
sumber
Diskusi tentang jawaban ini telah dipindahkan ke obrolan .
Paul White Reinstate Monica
5

Anda mungkin ingin melihat CryptDB . Ini adalah ujung depan untuk MySQL dan PostgreSQL yang memungkinkan penyimpanan transparan dan permintaan data terenkripsi. Ini bekerja dengan mengenkripsi dan mendekripsi data saat melewati antara aplikasi dan database, menulis ulang pertanyaan untuk beroperasi pada data yang dienkripsi. dan dengan secara dinamis menyesuaikan mode enkripsi setiap kolom untuk memaparkan informasi sebanyak yang diperlukan untuk permintaan yang digunakan aplikasi.

Berbagai metode enkripsi yang digunakan oleh CryptDB meliputi:

  • RND , skema enkripsi aman IND-CPA sepenuhnya yang tidak membocorkan informasi tentang data (kecuali keberadaannya dan, untuk tipe panjang variabel, panjang) tetapi hanya memungkinkan penyimpanan dan pengambilan, tidak ada permintaan.

  • DET , varian RND yang bersifat deterministik, sehingga dua nilai yang identik (dalam kolom yang sama) dienkripsi ke ciphertext yang sama. Mendukung pertanyaan kesetaraan formulir WHERE column = 'constant'.

  • OPE , skema enkripsi pelestarian pesanan yang mendukung permintaan ketimpangan seperti WHERE column > 'constant'.

  • HOM , skema enkripsi sebagian homomorfik (Paillier) yang memungkinkan menambahkan nilai terenkripsi bersama dengan mengalikan ciphertext. Mendukung SUM()kueri, penambahan, dan penambahan.

  • SEARCH , skema yang mendukung pencarian kata kunci dari formulir WHERE column LIKE '% word %'.

  • IKUTI dan OPE-JOIN , varian DET dan OPE yang memungkinkan nilai dalam kolom yang berbeda untuk dibandingkan satu sama lain. Mendukung kesetaraan dan jangkauan bergabung masing-masing.

Kekuatan sebenarnya dari CryptDB adalah bahwa ia mengadaptasi metode enkripsi setiap kolom secara dinamis dengan permintaan yang dilihatnya, sehingga skema yang lebih lambat dan / atau kurang aman hanya digunakan untuk kolom yang membutuhkannya. Ada juga berbagai fitur bermanfaat lainnya, seperti chaining kunci enkripsi untuk kata sandi pengguna.

Jika Anda tertarik, Anda disarankan untuk melihat makalah yang ditautkan dari situs web CryptDB, khususnya "CryptDB: Melindungi Kerahasiaan dengan Pemrosesan Query yang Dienkripsi" oleh Popa, Redfield, Zeldovich dan Balakrishnan ( SOSP 2011 ). Makalah-makalah tersebut juga menjelaskan berbagai pengorbanan keamanan dan kinerja yang terlibat dalam mendukung berbagai jenis kueri secara lebih rinci.

Ilmari Karonen
sumber
1
It works by encrypting and decrypting data as it passes between the application and the database: Tentunya ini dapat menyebabkan masalah jika data yang dicari sudah ada di database (terenkripsi) tetapi jelas permintaan itu sendiri yang mencari database hanya kemudian diteruskan ke CryptDB (dan kemudian dienkripsi?). Saya tidak mengerti bagaimana metode ini bisa efisien?
Martin
3

Saya tidak mengerti mengapa jawaban saat ini belum mempertanyakan persyaratan sepenuhnya, jadi saya akan bertanya dan meninggalkannya sebagai jawaban.

Apa alasan bisnisnya? Data apa yang Anda butuhkan untuk mengenkripsi dan mengapa? Jika Anda mencari kepatuhan PCI, saya bisa menulis esai.

Pertanyaan tentang kebutuhan Anda:

  • Apakah Anda perlu mengembalikan yang ada / tidak ada sebagai hasilnya, atau data aktual?
  • Apakah Anda memerlukan kemampuan LIKE '% OMG_SEKRIT%'?
  • Siapa yang tidak bisa melihat data dan mengapa?

Keamanan RDBMS biasanya dilakukan atas dasar izin yang diberlakukan oleh pengguna / peran. Data biasanya dienkripsi oleh RDBMS pada disk, tetapi tidak dalam data kolom itu sendiri, karena itu tidak benar-benar masuk akal untuk aplikasi yang dirancang untuk secara efisien menyimpan dan mengambil data.

Batasi oleh pengguna / peran / api. Enkripsi di disk. Jika Anda menyimpan data yang lebih penting, saya ingin tahu mengapa Anda menggunakan MySQL.

Philᵀᴹ
sumber
Terutama, saya perlu mencari ada / tidak ada dan kemudian mencari catatan spesifik. Dukungan penuh SEPERTI akan baik-baik saja. Tetapi saya bertanya-tanya, bahwa sesuatu yang lebih dari sekadar pencocokan kata-kata adalah mungkin. Pengguna yang diizinkan diizinkan untuk melihat data. Aplikasi mendekripsi item-item itu, yang berhak dilihat oleh pengguna yang sah. Skema dasar izin tidak ada pilihan.
SteAp
Apa kriteria untuk "data yang lebih penting?"
arcanine
2

Saya melihat ini dan menemukan pertanyaan Anda. Saya condong ke arah pendekatan yang diuraikan dalam bagian 5.4 dari makalah "Teknik Praktis untuk Pencarian pada Data Terenkripsi" http://www.cs.berkeley.edu/~dawnsong/papers/se.pdf

Inti dasarnya adalah membuat indeks yang berisi kata kunci terenkripsi yang ada dalam dokumen pencarian terenkripsi. Caranya adalah dengan mengenkripsi lokasi dalam dokumen (atau basis data) tempat kata kunci tersebut ada.

M. Scott Ford
sumber
1

Secara pemrograman, solusi yang efisien adalah

  1. ambil SEMUA rekaman untuk HANYA bidang yang Anda cari dengan id rekaman
  2. mendekripsi mereka menjadi tabel sementara
  3. melakukan pencarian terhadap tabel itu
  4. gunakan id untuk mengambil catatan lengkap (semua bidang) yang cocok dengan kriteria pencarian
  5. mendekripsi dan mengembalikannya kepada pengguna

Intinya adalah bahwa 1 dan 4 secara signifikan lebih kecil set data daripada mengambil dan mendekripsi semua bidang semua catatan di awal.

Semoga itu bisa membantu.

Paul B. Hartzog
sumber
Tabel sementara dalam plaintext relatif (yaitu sangat) mudah untuk diambil dan dibaca, mengganggu server pada saat yang tepat atau cukup salin temp/folder dan bang, nilai plaintext untuk seluruh kolom ada di sana, ini bukan cara yang aman untuk beroperasi
Martin
1

Ini dimungkinkan dengan fungsi pencarian lengkap dengan menggunakan fungsi enkripsi internal MYSQL.

Ini sebuah contoh:

!!! SAYA MENGGUNAKAN MYSQL ENCODE () DI SINI UNTUK SIMPLISITAS, MYSQL_ENCODE SEKARANG DIPERTIMBANGKAN INSECURE, GUNAKAN SALAH SATU FUNGSI MYSQL INTERNAL LAINNYA BUKAN !!!

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';

Seperti komentar di atas menyarankan, JANGAN gunakan ENCODE (), gunakan salah satu fungsi enkripsi lainnya. Saya hanya menggunakan ENCODE dalam contoh ini karena kesederhanaannya.

Jika Anda melakukan ini di dalam aplikasi seperti php, Anda dapat melakukan ini dalam db gateway atau kelas repositori Anda dengan menyimpan daftar / larik kolom terenkripsi setiap tabel dalam kelas gateway masing-masing.

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";
    }
}

Tentu saja ini sangat kasar dan kode tidak aman yang tidak boleh digunakan dalam produksi tanpa peningkatan yang signifikan. Tetapi harus melayani tujuannya dalam memberikan gagasan umum.

Leigh Bicknell
sumber
-1

Dengan asumsi Anda mencari dalam SQL dan menentang nilai penuh dan tidak parsial (misalnya LIKE 'value%') ... ketika mengambil data pencarian, enkripsi data tersebut menggunakan algoritma yang sama yang digunakan ketika data dienkripsi dan cari itu.

Sebagai contoh:

Apa yang seharusnya:

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

Mungkin malah terlihat seperti:

SELECT FieldA, FieldB 
FROM Table1 
WHERE FieldC = 'hsk&%67ghhks83'
WellyBoot
sumber
1
Tidak. Enkripsi yang layak akan berfungsi dengan nilai garam jadi jika misalnya Anda memiliki garam unik untuk setiap baris, maka setiap baris garam harus digunakan pada string pencarian, ini akan menjadi kompleks, dan mahal, cukup cepat
Martin