Application security is one of the most important aspects of software development. App users always hope that their information is secure.
In this article, we will discuss the common mistakes developers make about application security and how to easily fix them.
Store important data in the wrong places
I have researched many applications from the AppStore and many of them are making this mistake, storing important data where it shouldn’t. If you are storing important data in UserDefaults
, then you are quite risky with the application information.
UserDefaults
is simply stored as a list of properties located in the application’s Preferences
folder. It is saved in the application without being encrypted in any way.
Basically, using third-party mac apps such as iMazed, even without jailbreaking the device, you can easily view UserDefaults
data for any application downloaded from AppStore. .
The apps on this mac are simply designed to allow you to discover and manage application files on your iPhone. And you can easily explore UserDefaults
of any application.
The reason that motivated me to write this article is because I discovered that many of the applications that I have installed from AppStore store important data on UserDefaults
.
For example: Access Tokens, Active Renewable, subscription flags, the number of coins available, etc. All this data can be easily retrieved and changed and damages applications, from the free use of the Premium features come with network layer hacks and more.
The right way
You should always keep in mind that when saving data on an iOS app, UserDefaults
only designed to store a small amount of data such as user preferences in the app, which are completely unimportant.
To save important data in the application, we recommend using the security services provided by Apple.
The Keychain Services API helps you solve these problems by providing the application a way to store a small amount of user data in an encrypted database, called Keychain
.
In Keychain
, you can freely save passwords and other important user data, such as credit card information or even short sensitive notes.
You can also store items such as key codes and Certificates, Trust Services.
Keychain Services API
Below we will describe how you can save a user’s password inside Keychain
.
1 2 3 4 5 6 7 8 9 10 11 | 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") } } |
kSecClass: kSecClassGenericPassword
indicates that the item is a password, from which the keychain service understands that the data requires encryption. Then, add a new password to the keychain by calling SecItemAdd
with the generated query
. Getting the data is similar:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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) } |
We write a simple test to ensure that data is saved and retrieved correctly
1 2 3 4 5 6 7 | func testPaswordRetrive() { let password = "123456" let account = "User" keyChainService.save(password, for: account) XCTAssertEqual(keyChainService.retrivePassword(for: account), password) } |
In addition, there are many open source libraries that make API Keychain easier to use. Some of them are SAMKeychain
and SwiftKeychainWrapper
.
Encrypt sensitive data
Implementing a hash manually can be very complicated and overkill, so in this article we will use the help of the CryptoSwift
Open Source Encryption CryptoSwift
.
CryptoSwift
is a growing collection of standard and extremely secure encryption algorithms implemented in Swift.
Let’s try to save and retrieve the password on the keychain
using the algorithms provided by CryptoSwift
.
1 2 3 4 5 6 | 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) } |
This method takes an account and password and stores the processed string on Keychain instead of the direct chain.
We create salt
to make it harder for hackers to attack applications. If we only hash our passwords, hackers can have a list of the most used passwords and generate their hashes, comparing them with the generated password. You can then easily find the password for a given account. We can now authenticate with the server using an account and a custom key instead of a direct password.
1 2 | authManager.login(key, user) |
Of course, applications and servers should share the same salt
. You will then have to compare the same keys using the same algorithm to verify the user. By using this method, we take security to the next level and make our application hacking an extremely complex task.
Summary
Deploying security for applications should be a task that should never be missed.
Initially, in this article, we discussed issues that may arise from saving sensitive data to UserDefaults
, why you must save them on Keychain
to prevent hackers from easily viewing them.
In the second part, we talked more about taking security to the next level by encrypting sensitive data before saving, using encrypted data to interact with the server.
Thank you for watching this article, hope it is useful to you all.
Source: medium.com