Selamat siang, Habr! Saya mempersembahkan kepada Anda terjemahan artikel tentang prinsip-prinsip dasar keamanan data rahasia dalam aplikasi iOS
"Wajib Keamanan Aplikasi untuk setiap Aplikasi iOS" oleh Arlind Aliu.
Keamanan aplikasi adalah salah satu aspek terpenting dari pengembangan perangkat lunak. Pengguna aplikasi berharap bahwa informasi yang mereka berikan dilindungi dengan aman. Karenanya, Anda tidak bisa memberikan informasi rahasia kepada seseorang.
Untungnya, dalam artikel ini kita akan membahas kesalahan yang dilakukan pengembang dalam aplikasi mereka, serta cara untuk mengatasinya.
Berlanjut di bawah potongan.
Penyimpanan data di tempat yang salah
Saya melakukan studi tentang beberapa aplikasi dari AppStore dan banyak membuat kesalahan yang sama: informasi rahasia disimpan di tempat yang seharusnya tidak.
Jika Anda menyimpan data pribadi di
UserDefaults , maka Anda berisiko.
UserDefaults disimpan dalam file dengan daftar properti, yang terletak di dalam folder "Pengaturan" di aplikasi Anda. Data disimpan dalam aplikasi tanpa sedikit pun enkripsi.
Dengan menginstal program pihak ketiga pada mac, seperti iMazing, Anda bahkan tidak perlu meretas telepon, tetapi segera melihat semua data
UserDefaults dari aplikasi yang diinstal dari AppStore. Program semacam itu memungkinkan Anda untuk menonton dan mengelola data dari aplikasi yang diinstal pada iPhone. Anda dapat dengan mudah mendapatkan
UserDefaults dari aplikasi apa pun.
Ini adalah alasan utama mengapa saya memutuskan untuk menulis artikel - Saya menemukan banyak aplikasi di AppStore yang menyimpan data di
UserDefaults , seperti: token, langganan aktif dan terbarukan, jumlah uang yang tersedia, dan sebagainya. Semua data ini dapat dengan mudah diperoleh dan digunakan dengan niat jahat, mulai dari mengelola langganan berbayar di aplikasi hingga peretasan di tingkat jaringan dan lebih buruk.
Dan sekarang tentang cara menyimpan data.
Ingat, hanya sejumlah kecil informasi yang harus disimpan dalam
UserDefaults , seperti pengaturan dalam aplikasi, yaitu data yang tidak dirahasiakan bagi pengguna.
Gunakan layanan keamanan khusus Apple untuk menyimpan informasi pribadi. Layanan Keychain API memungkinkan Anda untuk menyimpan sejumlah data pengguna dalam database terenkripsi. Di sana Anda dapat menyimpan kata sandi dan data penting lainnya untuk pengguna, seperti informasi kartu kredit, atau bahkan catatan penting kecil.
Juga, mungkin ada kunci dan sertifikat terenkripsi yang dengannya Anda bekerja.
Layanan API Keychain
Berikut ini adalah contoh cara menyimpan kata sandi pengguna di Keychain.
class KeychainService { func save(_ password: String, for account: String) { let password = password.data(using: String.Encoding.utf8)! let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: account, kSecValueData as String: password] let status = SecItemAdd(query as CFDictionary, nil) guard status == errSecSuccess else { return print("save error") } }
Bagian dari kamus
kSecClass: kSecClassGenericPassword berarti bahwa informasi yang perlu dienkripsi adalah kata sandi. Kemudian kami menambahkan kata sandi baru ke gantungan kunci dengan memanggil metode
SecItemAdd . Mengambil data dari bundel mirip dengan menyimpan.
func retrivePassword(for account: String) -> String? { let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: account, kSecMatchLimit as String: kSecMatchLimitOne, kSecReturnData as String: kCFBooleanTrue] var retrivedData: AnyObject? = nil let _ = SecItemCopyMatching(query as CFDictionary, &retrivedData) guard let data = retrivedData as? Data else {return nil} return String(data: data, encoding: String.Encoding.utf8) }
Mari kita tulis cek kecil tentang kebenaran menyimpan dan menerima data.
func testPaswordRetrive() { let password = "123456" let account = "User" keyChainService.save(password, for: account) XCTAssertEqual(keyChainService.retrivePassword(for: account), password) }
Pada pandangan pertama, sepertinya Keychain API cukup sulit digunakan, terutama jika Anda perlu menyimpan lebih dari satu kata sandi, jadi saya mendorong Anda untuk menggunakan pola Facade untuk keperluan ini. Ini akan memungkinkan Anda untuk menyimpan dan mengubah data tergantung pada kebutuhan aplikasi.
Jika Anda ingin tahu lebih banyak tentang pola ini, serta cara membuat pembungkus sederhana untuk subsistem kompleks, maka
artikel ini akan membantu Anda. Juga di Internet penuh dengan pustaka terbuka yang membantu menggunakan Keychain API, misalnya,
SAMKeychain dan
SwiftKeychainWrapper .
Penghematan Kata Sandi dan Otorisasi
Dalam karier pengembangan saya, saya terus-menerus menghadapi masalah yang sama. Pengembang dapat menyimpan kata sandi dalam aplikasi, atau membuat permintaan ke server, yang mengirimkan nama pengguna dan kata sandi secara langsung.
Jika Anda menyimpan data di
UserDefault , maka setelah membaca informasi dari bagian pertama artikel, Anda sudah memahami seberapa besar risiko Anda. Dengan menyimpan kata sandi di Gantungan Kunci, Anda secara serius meningkatkan tingkat keamanan aplikasi Anda, tetapi sekali lagi, sebelum Anda menyimpan informasi rahasia di mana saja, Anda harus terlebih dahulu mengenkripsinya.
Misalkan seorang hacker dapat menyerang kami melalui jaringan kami. Dengan demikian, ia akan menerima kata sandi dalam bentuk teks mentah. Tentu saja, lebih baik hash semua kata sandi.
Enkripsi data pribadi
Hashing bisa tampak sedikit
berlebihan jika Anda melakukannya sendiri, jadi dalam artikel ini kita akan menggunakan pustaka
CryptoSwift . Ia telah mengumpulkan banyak algoritma enkripsi andal standar yang digunakan di Swift.
Mari mencoba menyimpan dan mengambil kata sandi dari gantungan kunci menggunakan algoritma
CryptoSwift .
func saveEncryptedPassword(_ password: String, for account: String) { let salt = Array("salty".utf8) let key = try! HKDF(password: Array(password.utf8), salt: salt, variant: .sha256).calculate().toHexString() keychainService.save(key, for: account) }
Fungsi di atas mencatat nama pengguna dan kata sandi dan menyimpannya di Gantungan Kunci sebagai string terenkripsi.
Mari kita lihat apa yang terjadi di dalam:
- Login dan kata sandi ditulis ke variabel garam sebagai string
- sha256 mengisi hash SHA-2
- HKDF adalah fungsi pembuatan kunci (
KDF ) berdasarkan kode otentikasi pesan (
HMAC )
Kami menciptakan variabel garam untuk mempersulit tugas bagi peretas. Kami hanya dapat mengenkripsi kata sandi, tetapi dalam hal ini, penyerang dapat memiliki daftar kata sandi yang paling sering digunakan, ia akan mengenkripsi kata sandi tersebut tanpa masalah dan membandingkannya dengan kata sandi terenkripsi kami. Kemudian menemukan kata sandi untuk akun tertentu tidaklah sulit.
Sekarang kita bisa masuk menggunakan akun kita dan kunci yang dihasilkan.
authManager.login(key, user)
Tentu saja, server harus tahu apa yang dienkripsi dalam variabel garam kami. Backend akan dapat membandingkan kunci menggunakan algoritma yang sama untuk mengidentifikasi pengguna.
Menggunakan pendekatan ini akan sangat meningkatkan keamanan aplikasi Anda.
Selesai
Jangan pernah mengabaikan keamanan aplikasi Anda. Pada artikel ini, pertama-tama kita mengetahui apa yang bisa menjadi konsekuensi ketika menyimpan data sensitif di
UserDefaults dan mengapa Keychain diperlukan.
Pada bagian kedua, kita akan berbicara tentang tingkat keamanan yang lebih serius, mengenkripsi data sebelum menyimpannya, dan juga membahas cara mentransfer informasi dengan data pribadi ke server dengan benar.