설명
Core Data 또는 Realm 로컬 데이터베이스에 비밀번호, 토큰, API 키 같은 민감 값을 평문으로 저장하면 백업, 디버그 추출, 탈옥된 기기에서 값이 노출될 수 있습니다.
잠재적 영향
- 인증 토큰 또는 세션 탈취
- 로컬 백업과 디버그 추출을 통한 민감 정보 노출
- 탈취한 값 재사용을 통한 계정 접근
해결 방법
- 민감 값은 가능한 한 로컬 데이터베이스에 저장하지 않습니다.
- 저장이 필요하면 Keychain, SQLCipher, Realm encryption key 등 검증된 암호화 저장소를 사용합니다.
- 데이터베이스에 저장하기 전 값 단위 암호화를 적용하고 키는 Keychain에서 관리합니다.
예시
변경 후 예시는 Core Data의 access_token 속성이 Binary Data 형식이라고 가정합니다. 키 조회와 컨텍스트 저장 코드는 생략했습니다.
변경 전
swift
let user = NSEntityDescription.insertNewObject(forEntityName: "User", into: context)
user.setValue(accessToken, forKey: "access_token")
변경 후
swift
import CoreData
import CryptoKit
enum StorageEncryptionError: Error {
case missingCombinedRepresentation
}
func storeToken(
context: NSManagedObjectContext,
accessToken: Data,
databaseKey: SymmetricKey
) throws {
let sealedBox = try AES.GCM.seal(accessToken, using: databaseKey)
guard let encryptedToken = sealedBox.combined else {
throw StorageEncryptionError.missingCombinedRepresentation
}
let user = NSEntityDescription.insertNewObject(
forEntityName: "User", into: context)
user.setValue(encryptedToken, forKey: "access_token")
}
설명:
- 변경 전: 인증 토큰을 로컬 데이터베이스에 평문으로 저장합니다.
- 변경 후: CryptoKit의 AES-GCM으로 인증 암호화를 적용한 결합 표현만 저장합니다.
databaseKey는 데이터베이스나 소스 코드가 아니라 Keychain 같은 별도 보안 저장소에서 관리해야 합니다.