https://github.com/OWASP/owasp-mstg/blob/master/Document/0x06d-Testing-Data-Storage.md
Data Storage on iOS
인증 토큰이나 개인 정보와 같은 중요한 데이터의 보호는 모바일 보안의 주요 초점입니다. 이 장에서는 iOS가 로컬 데이터 저장을 위해 제공하는 API를 사용하는 모범사례에 대해 배우게됩니다.
Testing Local Data Storage
가능한 한 민감한 데이터는 영구적 인 로컬 저장소에 저장해야합니다. 그러나 가장 실용적인 시나리오에서는 적어도 일부 유형의 사용자 관련 데이터를 저장해야합니다. 다행히도 iOS는 개발자들이 모든 iOS기기에서 사용할 수 있는 암호화 하드웨어를 사용할 수 있게 해 주는 보안 스토리지 API를 제공합니다.이러한 API가 올바르게 사용된다고 가정하면, 하드웨어 지원 256비트 AES암호화를 사용하여 주요 데이터 및 파일을 보호할 수 있습니다.
Data Protection API
앱 개발자는 iOS Data Protection API를 활용하여 플래시 메모리에 저장된 사용자 데이터에 대한 세부적인 액세스 제어를 구현할 수 있습니다. 이 API는 iPhone 5S에서 소개 된 SEP (Secure Enclave Processor) 위에 구축되었습니다. SEP는 데이터 보호 및 키 관리를위한 암호화 작업을 제공하는 보조 프로세서입니다. 디바이스 고유의 하드웨어 키 - 디바이스 UID (Unique ID) - 는 보안 영역에 내장되어 운영 체제 커널이 손상 되더라도 데이터 보호의 무결성을 보장합니다.
데이터 보호 아키텍처는 키 계층을 기반으로합니다. PBKDF2 알고리즘을 사용하여 사용자의 passpharse 로부터 파생 된 UID와 사용자 암호 코드 키는이 계층의 맨 위에 위치합니다. 이 키를 함계 사용하여 서로 다른 장치 상태 (예 : 장치 잠금 / 잠금 해제)와 관련된 클래스 키를 "잠금 해제"하는 데 사용할 수 있습니다.
iOS 파일 시스템에 저장된 모든 파일은 파일 메타 데이터에 포함 된 개별 개별 파일 키로 암호화됩니다. 메타 데이터는 파일 시스템 키로 암호화되고 파일을 만들 때 앱이 선택한 보호 클래스에 따라 클래스 키 중 하나로 래핑됩니다.
* [iOS 데이터 보호 키 계층 구조] (https://www.apple.com/business/docs/iOS_Security_Guide.pdf "iOS 보안 가이드") *
파일은 4 가지 보호 클래스 중 하나에 할당 할 수 있습니다. 자세한 내용은 iOS 보안 가이드 참고 :
Complete Protection (NSFileProtectionComplete) : 사용자 패스코드 및 디바이스 UID에서 파생된 키가 이 클래스 키를 보호하는 데 사용됩니다. 장치가 잠긴 직후에 메모리에서 지워지므로 사용자가 장치 잠금을 해제할 때까지 데이터에 액세스 할 수 없게 됩니다.
Protected Unless Open (NSFileProtectionCompleteUnlessOpen) : Complete Protection과 유사하지만 잠금 해제시 파일을 열면 사용자가 장치를 잠그더라도 파일에 계속 액세스 할 수 있습니다. 이 보호 클래스는 예를 들어 메일 첨부 파일이 백그라운드에서 다운로드 될 때 사용됩니다.
Protected Until First User Authentication (NSFileProtectionCompleteUntilFirstUserAuthentication) : 부팅 후 사용자가 처음 장치를 잠금 해제 한 순간부터 파일에 액세스 할 수 있습니다. 나중에 사용자가 장치를 잠그고 클래스 키가 메모리에서 제거 되더라도 액세스 할 수 있습니다.
No Protection (NSFileProtectionNone) : 이 보호 클래스의 클래스 키는 UID로만 보호됩니다. 소량의 데이터를 저장할 수있는 iOS 장치의 플래시 메모리 영역 인 소위 말하는 "Effaceable Storage"에 저장됩니다. 이 보호 클래스는 fast remote wipe를 가능하게합니다. 즉, 클래스 키를 즉시 삭제하여 데이터에 액세스 할 수 없도록 합니다.
NSFileProtectionNone을 제외한 모든 클래스 키는 장치 UID 및 사용자의 암호에서 파생 된 키로 암호화됩니다. 결과적으로 암호 해독은 장치 자체에서만 발생하며 올바른 암호를 입력해야 합니다.
iOS 7부터 기본 데이터 보호 클래스는 "Protected Until First User Authentication"입니다.
The Keychain
iOS 키체인은 암호화 키 및 세션 토큰과 같은 중요하고 짧은 데이터 비트를 안전하게 저장하는 데 사용할 수 있습니다. 이 데이터베이스는 키 체인 API를 통해서만 액세스 할 수 있는 SQLite데이터베이스로 구현됩니다.
MacOS에서는 모든 사용자 애플리케이션이 원하는 만큼의 키체인을 생성할 수 있으며 모든 로그인 계정에 자체 키체인이 있습니다. 항목에 대한 액세스는 kSecAttrAccessGroup 속성의 액세스 그룹 기능을 사용하여 동일한 개발자가 서명한 애플리케이션간에 공유할 수 있습니다.
키 체인에 대한 액세스는 애플리케이션의 Keychain-access-groups , application-identifier 및 application-group 자격에 따라 액세스 권한을 부여하는 securityd 데몬에 의해 관리됩니다.
KeyChain API는 다음과 같은 주요 작업으로 구성되어 있습니다.
- SecItemAdd
- SecItemUpdate
- SecItemCopyMatching
- SecItemDelete
키 체인에 저장된 데이터는 파일 암호화에 사용되는 것과 유사한 클래스 구조를 통해 보호됩니다. 키 체인에 추가 된 항목은 바이너리 plist로 인코딩되며 Galois / Counter Mode (GCM)에서 항목 당 128 비트 AES 키를 사용하여 암호화됩니다.
데이터의 blob이 클수록 키 체인에 직접 저장되는 것은 아니라는 점에 유의하십시오. 바로 이것이 데이터 보호 API의 용도입니다.
.... to do.....
Static Analysis
iOS앱의 소스 코드에 액세스 할 수 있을 때 앱 전체에 저장되고 처리되는 중요한 데이터를 찾으려고 시도합니다. 여기에는 일반적인 비밀 번호, 비밀 키 및 개인 식별 정보(PII)가 포함되지만, 업계 규정, 법률 또는 회사 정책을 통해 중요한 것으로 식별되는 기타 데이터도 포함될 수 있습니다.
어떤 경우 든 보안 설정을 사용하여 키 체인에 비밀 키가 저장되도록 암호화가 구현되어야합니다 (이상적으로 kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly). 이렇게 하면 하드웨어 기반 저장 장치 메커니즘을 사용할 수 있습니다. 또한 AccessControlFlags가 키 체인의 지정된 키에 대한 보안 정책에 따라 적절하게 설정되어 있는지 확인하십시오.
KeyChain을 사용하여 데이터를 저장, 업데이트 또는 삭제하는 일반적인 예는 공식 Apple 설명서에서 찾을 수 있습니다.
TouchID 및 패스 코드로 보호 된 키를 사용하는 샘플은 공식 Apple 설명서에서 찾을 수 있습니다.
Swift에서 키를 만드는 데 사용할 수있는 샘플이 있습니다.
// private key parameters let privateKeyParams: [String: AnyObject] = [ kSecAttrLabel as String: "privateLabel", kSecAttrIsPermanent as String: true, kSecAttrApplicationTag as String: "applicationTag" ] // public key parameters let publicKeyParams: [String: AnyObject] = [ kSecAttrLabel as String: "publicLabel", kSecAttrIsPermanent as String: false, kSecAttrApplicationTag as String: "applicationTag" ] // global parameters let parameters: [String: AnyObject] = [ kSecAttrKeyType as String: kSecAttrKeyTypeEC, kSecAttrKeySizeInBits as String: 256, kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave, kSecPublicKeyAttrs as String: publicKeyParams, kSecPrivateKeyAttrs as String: privateKeyParams ] var pubKey, privKey: SecKeyRef? let status = SecKeyGeneratePair(parameters, &pubKey, &privKey) |
NSUserDefaults
NSUserDefaults 클래스는 기본 시스템과 상호 작용할 수있는 프로그래밍 방식의 인터페이스를 제공합니다. 기본 시스템에서는 애플리케이션의 동작을 사용자의 기본 설정에 맞게 커스터마이징할 수 있습니다. NSUserDefaults에서 저장한 데이터는 애플리케이션 번들에서 볼 수 있습니다. 또한 plist 파일에 데이터를 저장하지만 데이터 양이 적은 경우에 적합합니다.
File system
- NSData : NSData는 정적 데이터 객체를 만들고 NSMutableData는 동적 데이터 객체를 만듭니다. NSData및 NSmutableData는 일반적으로 데이터 저장에 사용되며, 애플리케이션 간에 데이터 개체에 포함된 데이터를 복사하거나 이동할 수 있는 분산 개체 애플리케이션에서도 유용합니다. 다음은 NSData 객체를 작성하는 데 사용되는 메소드입니다.
NSDataWritingWithoutOverwriting
NSDataWritingFileProtectionNone
NSDataWritingFileProtectionComplete
NSDataWritingFileProtectionCompleteUnlessOpen
NSDataWritingFileProtectionCompleteUntilFirstUserAuthentication
- writeToFile : 데이터를 NSData 클래스의 일부로 저장합니다.
- NSSearchPathForDirectoriesInDomains, NSTemporaryDirectory : 파일 경로를 관리하는 데 사용됩니다.
- NSFileManager 객체를 사용하면 파일 시스템의 내용을 검사하고 변경 내용을 적용 할 수 있습니다. 파일을 만들고 파일에 쓰는 방법은 createFileAtPath를 통해 수행 할 수 있습니다.
다음 예제에서는 createFileAtPath 메서드를 사용하여 안전하게 암호화 된 파일을 만드는 방법을 보여줍니다.
[[NSFileManager defaultManager] createFileAtPath:[self filePath] contents:[@"secret text" dataUsingEncoding:NSUTF8StringEncoding] attributes:[NSDictionary dictionaryWithObject:NSFileProtectionComplete forKey:NSFileProtectionKey]]; |
Core Data
Core Data는 응용 프로그램에서 개체의 모델 계층을 관리하는데 사용하는 프레임워크입니다. persistence을 포함하여 객체 생명주기 및 객체 그래프 관리와 관련된 일반 작업에 일반화되고 자동화 된 솔루션을 제공합니다. Core Data는 영구 저장소로 SQLite를 사용할 수 있지만 프레임 워크 자체는 데이터베이스가 아닙니다.
SQLite Databases
SQLite 3 라이브러리는 SQLite를 사용하기 위해 앱에 추가되어야합니다. 이 라이브러리는 SQLite 명령에 API를 제공하는 C ++ 래퍼입니다.
Realm databases
Realm Objective-C와 Realm Swift는 Apple에 의해 제공되지는 않지만 여기서도 주목할 가치가 있습니다. 구성에 암호화가 설정되어 있지 않으면 암호화되지 않은 모든 항목이 저장됩니다.
// Open the encrypted Realm file where getKey() is a method to obtain a key from the keychain or a server let config = Realm.Configuration(encryptionKey: getKey()) do { let realm = try Realm(configuration: config) // Use the Realm as normal } catch let error as NSError { // If the encryption key is wrong, `error` will say that it's an invalid database fatalError("Error opening realm: \(error)") } |
'Hacking > iOS Hacking' 카테고리의 다른 글
iOS# Reverse-Engineering-and-Tampering (0) | 2018.02.01 |
---|---|
iOS# Platform-Overview (0) | 2018.01.08 |