NSFileManager
como constantes que deben asignarse como el valor de la clave NSFileProtectionKey
en un NSDictionary
asociado a la instancia de NSFileManager
, y se pueden crear archivos o modificar su clase de protección de datos mediante el uso de funciones NSFileManager
como setAttributes:ofItemAtPath:error:
, attributesOfItemAtPath:error:
y createFileAtPath:contents:attributes:
. Además, las constantes de protección de datos correspondientes se definen para objetos NSData
como NSDataWritingOptions
que pueden pasarse como el argumento options
a las funciones NSData
writeToURL:options:error:
y writeToFile:options:error:
. Las definiciones de las diversas constantes de clases de protección de datos para NSFileManager
y NSData
son las siguientes:NSFileProtectionComplete
, NSDataWritingFileProtectionComplete
:NSFileProtectionCompleteUnlessOpen
, NSDataWritingFileProtectionCompleteUnlessOpen
:NSFileProtectionCompleteUntilFirstUserAuthentication
, NSDataWritingFileProtectionCompleteUntilFirstUserAuthentication
:NSFileProtectionNone
, NSDataWritingFileProtectionNone
:NSFileProtectionCompleteUnlessOpen
o NSFileProtectionCompleteUntilFirstUserAuthentication
, se podrá cifrar con una clave derivada del código de acceso del usuario y del UID del dispositivo, los datos seguirán siendo accesibles en determinadas circunstancias. Por lo tanto, deben revisarse con atención los usos de NSFileProtectionCompleteUnlessOpen
o NSFileProtectionCompleteUntilFirstUserAuthentication
para determinar si se necesita mayor protección con NSFileProtectionComplete
.Ejemplo 2: en el siguiente ejemplo, los datos solo están protegidos hasta que el usuario enciende el dispositivo y proporciona el código de acceso por primera vez (hasta que vuelva a reiniciarse):
...
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
como constantes que deben asignarse como el valor de la clave NSFileProtectionKey
en un Dictionary
asociado a la instancia de NSFileManager
, y se pueden crear archivos o modificar su clase de protección de datos mediante el uso de funciones NSFileManager
como setAttributes(_:ofItemAtPath:)
, attributesOfItemAtPath(_:)
y createFileAtPath(_:contents:attributes:)
. Además, se definen las constantes de protección de datos correspondientes para objetos NSData
en la enumeración NSDataWritingOptions
que pueden pasarse como el argumento options
a funciones NSData
writeToFile(_:options:)
. Las definiciones de las diversas constantes de clases de protección de datos para NSFileManager
y NSData
son las siguientes:NSFileProtectionComplete
, NSDataWritingOptions.DataWritingFileProtectionComplete
:NSFileProtectionCompleteUnlessOpen
, NSDataWritingOptions.DataWritingFileProtectionCompleteUnlessOpen
:NSFileProtectionCompleteUntilFirstUserAuthentication
, NSDataWritingOptions.DataWritingFileProtectionCompleteUntilFirstUserAuthentication
:NSFileProtectionNone
, NSDataWritingOptions.DataWritingFileProtectionNone
:NSFileProtectionCompleteUnlessOpen
o NSFileProtectionCompleteUntilFirstUserAuthentication
, se podrá cifrar con una clave derivada del código de acceso del usuario y del UID del dispositivo, los datos seguirán siendo accesibles en determinadas circunstancias. Por lo tanto, deben revisarse con atención los usos de NSFileProtectionCompleteUnlessOpen
o NSFileProtectionCompleteUntilFirstUserAuthentication
para determinar si se necesita mayor protección con NSFileProtectionComplete
.Ejemplo 2: en el siguiente ejemplo, los datos determinados solo están protegidos hasta que el usuario enciende el dispositivo y proporciona el código de acceso por primera vez (hasta el siguiente reinicio).
...
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
en el diccionario de atributos de las claves. Las definiciones de las diversas constantes de accesibilidad de las claves son las siguientes:kSecAttrAccessibleAfterFirstUnlock
:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleAfterFirstUnlock
se podrá cifrar con una clave derivada del código de acceso del usuario y del UID del dispositivo, los datos seguirán siendo accesibles en determinadas circunstancias. Por lo tanto, deben revisarse con atención los usos de kSecAttrAccessibleAfterFirstUnlock
para determinar si se necesita mayor protección.
...
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
en el diccionario de atributos de las claves. Las definiciones de las diversas constantes de accesibilidad de las claves son las siguientes:kSecAttrAccessibleAfterFirstUnlock
:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleAfterFirstUnlock
se podrá cifrar con una clave derivada del código de acceso del usuario y del UID del dispositivo, los datos seguirán siendo accesibles en determinadas circunstancias. Por lo tanto, deben revisarse con atención los usos de kSecAttrAccessibleAfterFirstUnlock
para determinar si se necesita mayor protección.
...
// 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
como constantes que deben asignarse como el valor de la clave NSFileProtectionKey
en un NSDictionary
asociado a la instancia de NSFileManager
, y se pueden crear archivos o modificar su clase de protección de datos mediante el uso de funciones NSFileManager
como setAttributes:ofItemAtPath:error:
, attributesOfItemAtPath:error:
y createFileAtPath:contents:attributes:
. Además, las constantes de protección de datos correspondientes se definen para objetos NSData
como NSDataWritingOptions
que pueden pasarse como el argumento options
a las funciones NSData
writeToURL:options:error:
y writeToFile:options:error:
. Las definiciones de las diversas constantes de clases de protección de datos para NSFileManager
y NSData
son las siguientes:NSFileProtectionComplete
, NSDataWritingFileProtectionComplete
:NSFileProtectionCompleteUnlessOpen
, NSDataWritingFileProtectionCompleteUnlessOpen
:NSFileProtectionCompleteUntilFirstUserAuthentication
, NSDataWritingFileProtectionCompleteUntilFirstUserAuthentication
:NSFileProtectionNone
, NSDataWritingFileProtectionNone
:NSFileProtectionNone
provoca un cifrado con una clave derivada exclusivamente del UID del dispositivo. Esto permite que se pueda acceder a dichos archivos siempre que el dispositivo está encendido, incluso cuando está bloqueado con un código de acceso o durante el arranque. Por lo tanto, deben revisarse con atención los usos de NSFileProtectionNone
para determinar si se necesita mayor protección con una clase de protección de datos más estricta.Ejemplo 2: en el siguiente ejemplo, los datos no están protegidos (son accesibles en todo momento cuando el dispositivo está encendido):
...
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
como constantes que deben asignarse como el valor de la clave NSFileProtectionKey
en un Dictionary
asociado a la instancia de NSFileManager
. Se pueden crear archivos o modificar su clase de protección de datos mediante el uso de funciones NSFileManager
como setAttributes(_:ofItemAtPath:)
, attributesOfItemAtPath(_:)
y createFileAtPath(_:contents:attributes:)
. Además, se definen constantes de protección de datos correspondientes para objetos NSData
en la enumeración NSDataWritingOptions
que pueden pasarse como el argumento options
a funciones NSData
como
writeToFile(_:options:)
. Las definiciones de las diversas constantes de clases de protección de datos para NSFileManager
y NSData
son las siguientes:NSFileProtectionComplete
, NSDataWritingOptions.DataWritingFileProtectionComplete
:NSFileProtectionCompleteUnlessOpen
, NSDataWritingOptions.DataWritingFileProtectionCompleteUnlessOpen
:NSFileProtectionCompleteUntilFirstUserAuthentication
, NSDataWritingOptions.DataWritingFileProtectionCompleteUntilFirstUserAuthentication
:NSFileProtectionNone
, NSDataWritingOptions.DataWritingFileProtectionNone
:NSFileProtectionNone
provoca un cifrado con una clave derivada exclusivamente del UID del dispositivo. Esto permite que se pueda acceder a dichos archivos siempre que el dispositivo está encendido, incluso cuando está bloqueado con un código de acceso o durante el arranque. Por lo tanto, deben revisarse con atención los usos de NSFileProtectionNone
para determinar si se necesita mayor protección con una clase de protección de datos más estricta.Ejemplo 2: en el siguiente ejemplo, los datos determinados no están protegidos (es decir, son accesibles en todo momento cuando el dispositivo está encendido).
...
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
en el diccionario de atributos de las claves. Las definiciones de las diversas constantes de accesibilidad de las claves son las siguientes:kSecAttrAccessibleAfterFirstUnlock
:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleAlways
provoca un cifrado con una llave derivada exclusivamente del UID del dispositivo. Esto permite que se pueda acceder a dichos archivos siempre que el dispositivo está encendido, incluso cuando está bloqueado con un código de acceso o durante el arranque. Por lo tanto, deben revisarse con atención los usos de kSecAttrAccessibleAlways
para determinar si se necesita mayor protección con un nivel de accesibilidad de las llaves más estricto.
...
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
en el diccionario de atributos de las claves. Las definiciones de las diversas constantes de accesibilidad de las claves son las siguientes:kSecAttrAccessibleAfterFirstUnlock
:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleAlways
provoca un cifrado con una llave derivada exclusivamente del UID del dispositivo. Esto permite que se pueda acceder a dichos archivos siempre que el dispositivo está encendido, incluso cuando está bloqueado con un código de acceso o durante el arranque. Por lo tanto, deben revisarse con atención los usos de kSecAttrAccessibleAlways
para determinar si se necesita mayor protección con un nivel de accesibilidad de las llaves más estricto.
...
// 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
sin cifrar:
Realm realm = Realm.getDefaultInstance();
Realm
sin cifrar:
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];
Realm
sin cifrar:
let realm = try! Realm()
UIImageWriteToSavedPhotosAlbum
para guardar las imágenes en el álbum de fotos:
- (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
para guardar las imágenes en el álbum de fotos:
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
, si luego roban su dispositivo y se establece un código de acceso, el ladrón deberá desbloquear el dispositivo para descifrar los elementos de las llaves. Si no se introduce el código de acceso correcto, se bloqueará el descifrado de los elementos de las llaves del dispositivo robado. Sin embargo, si no se establece un código de acceso, el atacante solo necesitará deslizar el dedo para desbloquear el dispositivo y obtener las llaves para descifrar sus elementos. Por lo tanto, no exigir un código de acceso en el dispositivo puede debilitar el mecanismo de cifrado de las llaves.
...
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
, si luego roban su dispositivo y se establece un código de acceso, el ladrón deberá desbloquear el dispositivo para descifrar los elementos de las llaves. Si no se introduce el código de acceso correcto, se bloqueará el descifrado de los elementos de las llaves del dispositivo robado. Sin embargo, si no se establece un código de acceso, el atacante solo necesitará deslizar el dedo para desbloquear el dispositivo y obtener las llaves para descifrar sus elementos. Por lo tanto, no exigir un código de acceso en el dispositivo puede debilitar el mecanismo de cifrado de las llaves.
...
// 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)
...
Access Control Policy
que concede acceso anónimo completo al contenedor foo
.
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();
Access Control Policy
que concede un permiso anónimo de lectura de la ACP en el contenedor foo
.
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();
Access Control Policy
que concede acceso anónimo de lectura al contenedor foo
.
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();
Access Control Policy
que concede un permiso anónimo de escritura de la ACP en el contenedor foo
.
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();
Access Control Policy
que concede acceso anónimo de escritura al contenedor foo
.
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
, que comparte por defecto el contenido del portapapeles entre los dispositivos del usuario mediante Universal Clipboard.Ejemplo 2: En el siguiente código, los datos se escriben en el portapapeles general llamando al método
...
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
NSDictionary *items = @{
UTTypePlainText : sensitiveDataString,
UTTypePNG : [UIImage imageWithData:medicalImageData]
};
[pasteboard setItems: @[items]];
...
setObjects:localOnly:expirationDate:
con el comportamiento Universal Clipboard explícitamente habilitado configurando el parámetro localOnly
en NO
.
...
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
[pasteboard setObjects:@[sensitiveDataString, [UIImage imageWithData:medicalImageData]]
localOnly:NO
expirationDate:[NSDate distantFuture]];
...
setItems(_:options:)
, que comparte de forma predeterminada el contenido del portapapeles entre los dispositivos del usuario usando Universal Clipboard.Ejemplo 2: En el siguiente código, los datos se escriben en el portapapeles general utilizando el método
...
let pasteboard = UIPasteboard.general
let items: [[String: Any]] = [
["text": sensitiveDataString],
["image": UIImage(data: medicalImageData)!]
]
pasteboard.setItems(items)
...
setObjects(_:localOnly:expirationDate:)
con el comportamiento Universal Clipboard habilitado explícitamente configurando el parámetro localOnly
en false
.
...
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
, lo que creaba un problema de seguridad ya que si alguien tenía acceso a su dispositivo o lo robaba podía leer el contenido de las llaves. En la actualidad, el atributo predeterminado es kSecAttrAccessibleWhenUnlocked
, que es un valor predeterminado razonablemente restrictivo. Sin embargo, la documentación pública de Apple no está de acuerdo sobre cuál debe ser el atributo predeterminado. Por lo tanto, como precaución, debe configurar este atributo de manera explícita en todos los elementos de las llaves.
...
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
, lo que creaba un problema de seguridad ya que si alguien tenía acceso a su dispositivo o lo robaba podía leer el contenido de las llaves. En la actualidad, el atributo predeterminado es kSecAttrAccessibleWhenUnlocked
, que es un valor predeterminado razonablemente restrictivo. Sin embargo, la documentación pública de Apple no está de acuerdo sobre cuál debe ser el atributo predeterminado. Por lo tanto, como precaución, debe configurar este atributo de manera explícita en todos los elementos de las llaves.
...
// 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)
...
...
if (tmpnam_r(filename)){
FILE* tmp = fopen(filename,"wb+");
while((recv(sock,recvbuf,DATA_SIZE, 0) > 0)&&(amt!=0))
amt = fwrite(recvbuf,1,DATA_SIZE,tmp);
}
...
tmpnam()
, tempnam()
, mktemp()
y sus equivalentes de C++ precedidos de un _
(carácter de subrayado), así como de la función GetTempFileName()
de la API de Windows. Este grupo de funciones presenta una condición de carrera subyacente en relación con el nombre de archivo seleccionado. Aunque las funciones garantizan que el nombre de archivo es exclusivo en el momento de seleccionarlo, no hay ningún mecanismo que impida que otro proceso o un usuario malintencionado cree un archivo con el mismo nombre tras seleccionarlo, pero antes de que la aplicación intente abrirlo. Más allá del riesgo de conflicto legítimo provocado por otra llamada a la misma función, hay una alta probabilidad de que un usuario malintencionado pueda crear un conflicto malicioso debido a que los nombres de archivo generados por estas funciones no son lo suficientemente aleatorios para que sean difíciles de adivinar.open()
mediante los indicadores O_CREAT
y O_EXCL
, o a CreateFile()
mediante el atributo CREATE_NEW
, que presentará errores si el archivo ya existe y, por lo tanto, impide los tipos de ataques descritos anteriormente. Sin embargo, si un usuario malintencionado puede predecir con precisión una secuencia de nombres de archivo temporales, es posible que se impida que la aplicación abra el almacenamiento temporal necesario, lo que provocaría un ataque de denegación de servicio (DoS). Este tipo de ataque no sería difícil de implementar dado el reducido nivel de aleatoriedad empleado en la selección de los nombres de archivo generados por estas funciones.tmpfile()
y sus equivalentes de C++ precedidos de _
(carácter de subrayado), así como de una función de biblioteca C mkstemp()
con un comportamiento más eficaz.tmpfile()
crean un nombre de archivo exclusivo y abren el archivo del mismo modo que lo haría fopen()
si transfiriese los indicadores "wb+"
, es decir, como un archivo binario en modo de lectura/escritura. Si el archivo ya existe, tmpfile()
se truncará para establecer el tamaño cero, posiblemente en un intento por apaciguar las inquietudes de seguridad mencionadas anteriormente en cuanto a la condición de carrera que se produce entre la selección del nombre de archivo supuestamente exclusivo y la posterior apertura del archivo seleccionado. Sin embargo, este comportamiento no soluciona claramente los problemas de seguridad de la función. En primer lugar, un atacante puede crear previamente el archivo con permisos de acceso moderados que probablemente conservará el archivo abierto por tmpfile()
. Además, en los sistemas basados en Unix, si el usuario malintencionado crea previamente el archivo como vínculo a otro archivo importante, la aplicación puede utilizar los permisos posiblemente elevados para truncar ese archivo, dañándolo en nombre del usuario malintencionado. Por último, si tmpfile()
crea un nuevo archivo, los permisos de acceso aplicados al mismo variarán de un sistema operativo a otro, lo que puede dejar vulnerable la aplicación, incluso aunque el usuario malintencionado pueda predecir por adelantado el nombre de archivo que se va a usar.mkstemp()
supone un método razonablemente seguro para crear archivos temporales. Este intentará crear y abrir un archivo exclusivo basado en una plantilla de nombre de archivo proporcionada por el usuario, junto con una serie de caracteres generados aleatoriamente. Si no puede crear este archivo, presentará errores y devolverá -1
. En los sistemas modernos, el archivo se abre mediante el modo 0600
, lo que implica que el archivo se protegerá frente a su manipulación a menos que el usuario cambie de forma explícita los permisos de acceso. No obstante, mkstemp()
aún presenta problemas en relación con el uso de nombres de archivo predecibles y puede dejar vulnerable una aplicación frente a ataques de denegación de servicio si un usuario malintencionado provoca que mkstemp()
presente fallos mediante la predicción y la creación previa de los nombres de archivo que se van a utilizar.
...
try:
tmp_filename = os.tempnam()
tmp_file = open(tmp_filename, 'w')
data = s.recv(4096)
while True:
more = s.recv(4096)
tmp_file.write(more)
if not more:
break
except socket.timeout:
errMsg = "Connection timed-out while connecting"
self.logger.exception(errMsg)
raise Exception
...
open()
mediante los indicadores os.O_CREAT
y os.O_EXCL
, que presentará errores si el archivo ya existe y, por lo tanto, impedirá los tipos de ataques descritos anteriormente. Sin embargo, si un usuario malintencionado puede predecir con precisión una secuencia de nombres de archivo temporales, es posible que se impida que la aplicación abra el almacenamiento temporal necesario, lo que provocaría un ataque de denegación de servicio (DoS). Este tipo de ataque no sería difícil de implementar dado el reducido nivel de aleatoriedad empleado en la selección de los nombres de archivo generados por estas funciones.tmpfile()
.tmpfile()
crean un nombre de archivo exclusivo y abren el archivo del mismo modo que lo haría open()
si transfiriese los indicadores "wb+"
, es decir, como un archivo binario en modo de lectura/escritura. Si el archivo ya existe, tmpfile()
se truncará para establecer el tamaño cero, posiblemente en un intento por apaciguar las inquietudes de seguridad mencionadas anteriormente en cuanto a la condición de carrera que se produce entre la selección del nombre de archivo supuestamente exclusivo y la posterior apertura del archivo seleccionado. Sin embargo, este comportamiento no soluciona claramente los problemas de seguridad de la función. En primer lugar, un atacante puede crear previamente el archivo con permisos de acceso moderados que probablemente conservará el archivo abierto por tmpfile()
. Además, en los sistemas basados en Unix, si el usuario malintencionado crea previamente el archivo como vínculo a otro archivo importante, la aplicación puede utilizar los permisos posiblemente elevados para truncar ese archivo, dañándolo en nombre del usuario malintencionado. Por último, si tmpfile()
crea un nuevo archivo, los permisos de acceso aplicados al mismo variarán de un sistema operativo a otro, lo que puede dejar vulnerable la aplicación, incluso aunque el usuario malintencionado pueda predecir por adelantado el nombre de archivo que se va a usar.
...
FINAL(client) = cl_apc_tcp_client_manager=>create(
i_host = ip_adress
i_port = port
i_frame = VALUE apc_tcp_frame(
frame_type =
if_apc_tcp_frame_types=>co_frame_type_terminator
terminator =
terminator )
i_event_handler = event_handler ).
...
client
y el servidor remoto es vulnerable a compromisos, porque se transmite a través de un canal no cifrado y no autenticado.
...
HttpRequest req = new HttpRequest();
req.setEndpoint('http://example.com');
HTTPResponse res = new Http().send(req);
...
HttpResponse
, res
, se haya visto comprometido, ya que se proporciona a través de un canal no cifrado ni autenticado.
var account = new CloudStorageAccount(storageCredentials, false);
...
String url = 'http://10.0.2.2:11005/v1/key';
Response response = await get(url, headers: headers);
...
response
, se haya visto comprometida, ya que se proporciona a través de un canal no cifrado ni autenticado.
helloHandler := func(w http.ResponseWriter, req *http.Request) {
io.WriteString(w, "Hello, world!\n")
}
http.HandleFunc("/hello", helloHandler)
log.Fatal(http.ListenAndServe(":8080", nil))
URL url = new URL("http://www.android.com/");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
readStream(in);
...
}
instream
, se haya visto comprometida, ya que se proporciona a través de un canal no cifrado ni autenticado.
var http = require('http');
...
http.request(options, function(res){
...
});
...
http.IncomingMessage
, res
, se haya visto comprometido debido que se proporciona a través de un canal sin cifrar ni autenticar.
NSString * const USER_URL = @"http://localhost:8080/igoat/user";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:USER_URL]];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
...
stream_socket_enable_crypto($fp, false);
...
require 'net/http'
conn = Net::HTTP.new(URI("http://www.website.com/"))
in = conn.get('/index.html')
...
in
, se haya visto comprometida, ya que se proporciona a través de un canal no cifrado ni autenticado.
val url = Uri.from(scheme = "http", host = "192.0.2.16", port = 80, path = "/")
val responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(uri = url))
responseFuture
, se haya visto comprometida, ya que se proporciona a través de un canal no cifrado ni autenticado.
let USER_URL = "http://localhost:8080/igoat/user"
let request : NSMutableURLRequest = NSMutableURLRequest(URL:NSURL(string:USER_URL))
let conn : NSURLConnection = NSURLConnection(request:request, delegate:self)
Config.PreferServerCipherSuites
controla si el servidor sigue las preferencias de los conjuntos de cifrado del cliente o del servidor. Usar el conjunto de cifrado preferido por el cliente puede introducir vulnerabilidades de seguridad si se sabe que el conjunto de cifrado tiene deficiencias.PreferServerCipherSuites
como false
.
conf := &tls.Config{
PreferServerCipherSuites: false,
}
client = SSHClient()
algorithms_to_disable = { "ciphers": untrusted_user_input }
client.connect(host, port, "user", "password", disabled_algorithms=algorithms_to_disable)
SSHClient.connect(...)
a utilizar el algoritmo más débil 3DES-CBC.
...
Using(SqlConnection DBconn = new SqlConnection("Data Source=210.10.20.10,1433; Initial Catalog=myDataBase;User ID=myUsername;Password=myPassword;"))
{
...
}
...
...
insecure_config = {
'user': username,
'password': retrievedPassword,
'host': databaseHost,
'port': "3306",
'ssl_disabled': True
}
mysql.connector.connect(**insecure_config)
...
NSURLSession
,NSURLConnection
, oCFURL
en iOS 9 o OS X El Capitan, lo que obliga a la aplicación a usar HTTPS
con TLS 1.2
en todas las comunicaciones de red con el servidor back-end.Info.plist
deshabilitarán por completo App Transport Security:Ejemplo 2: Las siguientes entradas de la aplicación
<key>NSAppTransportSecurity</key>
<dict>
<!--Include to allow all connections (DANGER)-->
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Info.plist
deshabilitarán App Transport Security para yourserver.com
:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>yourserver.com</key>
<dict>
<!--Include to allow subdomains-->
<key>NSIncludesSubdomains</key>
<true/>
<!--Allow plain HTTP requests-->
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
<!--Downgrades TLS version-->
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>TLSv1.1</string>
</dict>
</dict>
</dict>