iOS Basics

Support HackTricks

Separação de Privilégios e Sandbox

No iOS, existe uma distinção de privilégio entre os aplicativos acessíveis ao usuário e os processos centrais do sistema. Os aplicativos são executados sob a identidade do usuário mobile, enquanto os processos cruciais do sistema operam como root. Essa separação é aprimorada por um mecanismo de sandbox, que impõe limitações rigorosas sobre quais ações os aplicativos podem realizar. Por exemplo, mesmo que os aplicativos compartilhem a mesma identidade de usuário, eles são proibidos de acessar ou modificar os dados uns dos outros.

Os aplicativos são instalados em um diretório específico (private/var/mobile/Applications/{random ID}) e têm acesso de leitura restrito a certas áreas e funcionalidades do sistema, como SMS e chamadas telefônicas. O acesso a áreas protegidas aciona um pedido de permissão do usuário.

Proteção de Dados

O iOS oferece aos desenvolvedores as APIs de Proteção de Dados, construídas sobre o Secure Enclave Processor (SEP) — um coprocessador dedicado para operações criptográficas e gerenciamento de chaves. O SEP garante a integridade da proteção de dados por meio de uma chave específica do dispositivo, o UID do dispositivo, incorporada a ele.

Ao criar um arquivo, uma chave de criptografia AES de 256 bits única é gerada, criptografando o conteúdo do arquivo. Essa chave de criptografia, juntamente com um ID de classe, é então criptografada usando uma chave de classe e armazenada nos metadados do arquivo. A descriptografia de um arquivo envolve o uso da chave do sistema para acessar os metadados, recuperando a chave de classe com o ID de classe e, em seguida, descriptografando a chave de criptografia única do arquivo.

O iOS define quatro classes de proteção para segurança de dados, que determinam quando e como os dados podem ser acessados:

  • Proteção Completa (NSFileProtectionComplete): Os dados são inacessíveis até que o dispositivo seja desbloqueado usando o código de acesso do usuário.

  • Protegido, a Menos que Esteja Aberto (NSFileProtectionCompleteUnlessOpen): Permite o acesso ao arquivo mesmo após o dispositivo estar bloqueado, desde que o arquivo tenha sido aberto quando o dispositivo foi desbloqueado.

  • Protegido Até a Primeira Autenticação do Usuário (NSFileProtectionCompleteUntilFirstUserAuthentication): Os dados são acessíveis após a primeira desbloqueio do usuário após a inicialização, permanecendo acessíveis mesmo que o dispositivo seja bloqueado novamente.

  • Sem Proteção (NSFileProtectionNone): Os dados são protegidos apenas pelo UID do dispositivo, facilitando a exclusão remota rápida de dados.

A criptografia de todas as classes, exceto NSFileProtectionNone, envolve uma chave derivada tanto do UID do dispositivo quanto do código de acesso do usuário, garantindo que a descriptografia só seja possível no dispositivo com o código de acesso correto. A partir do iOS 7, a classe de proteção padrão é "Protegido Até a Primeira Autenticação do Usuário".

Os desenvolvedores podem usar FileDP, uma ferramenta para inspecionar a classe de proteção de dados de arquivos em um iPhone.

# Example code to use FileDP for checking file protection class
# Note: Ensure your device is jailbroken and has Python installed to use FileDP.
# Installation and usage of FileDP:
git clone https://github.com/abjurato/FileDp-Source
cd FileDp-Source
python filedp.py /path/to/check

O Keychain

No iOS, um Keychain serve como um container criptografado seguro para armazenar informações sensíveis, acessível apenas pelo aplicativo que o armazenou ou aqueles explicitamente autorizados. Essa criptografia é reforçada por uma senha única gerada pelo iOS, que por sua vez é criptografada com AES. Esse processo de criptografia utiliza uma função PBKDF2, combinando o código de acesso do usuário com um sal derivado do UID do dispositivo, um componente que apenas o chipset de enclave seguro pode acessar. Consequentemente, mesmo que o código de acesso do usuário seja conhecido, o conteúdo do Keychain permanece inacessível em qualquer dispositivo que não seja aquele onde foi originalmente criptografado.

Gerenciamento e acesso aos dados do Keychain são tratados pelo daemon securityd, com base em direitos específicos do aplicativo, como Keychain-access-groups e application-identifier.

Operações da API do Keychain

A API do Keychain, detalhada na documentação dos Serviços de Keychain da Apple, fornece funções essenciais para gerenciamento seguro de armazenamento:

  • SecItemAdd: Adiciona um novo item ao Keychain.

  • SecItemUpdate: Atualiza um item existente no Keychain.

  • SecItemCopyMatching: Recupera um item do Keychain.

  • SecItemDelete: Remove um item do Keychain.

Forçar a senha do Keychain envolve atacar a chave criptografada diretamente ou tentar adivinhar o código de acesso no próprio dispositivo, dificultado significativamente pela aplicação de um atraso entre tentativas falhas pelo enclave seguro.

Configurando a Proteção de Dados do Item do Keychain

Os níveis de proteção de dados para itens do Keychain são definidos usando o atributo kSecAttrAccessible durante a criação ou atualização do item. Esses níveis, conforme especificado pela Apple, determinam quando e como os itens do Keychain são acessíveis:

  • kSecAttrAccessibleAlways: Acessível a qualquer momento, independentemente do status de bloqueio do dispositivo.

  • kSecAttrAccessibleAlwaysThisDeviceOnly: Sempre acessível, mas não incluído em backups.

  • kSecAttrAccessibleAfterFirstUnlock: Acessível após o primeiro desbloqueio após a reinicialização.

  • kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly: Igual ao acima, mas não transferível para novos dispositivos.

  • kSecAttrAccessibleWhenUnlocked: Apenas acessível quando o dispositivo está desbloqueado.

  • kSecAttrAccessibleWhenUnlockedThisDeviceOnly: Acessível quando desbloqueado, não incluído em backups.

  • kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly: Requer código de acesso do dispositivo, não incluído em backups.

AccessControlFlags refinam ainda mais os métodos de acesso, permitindo autenticação biométrica ou uso de código de acesso.

Aviso sobre Dispositivos Jailbroken

Em dispositivos jailbroken, as proteções do Keychain estão comprometidas, representando um risco significativo à segurança.

Persistência dos Dados do Keychain

Ao contrário dos dados específicos do aplicativo que são excluídos após a desinstalação do aplicativo, os dados do Keychain persistem no dispositivo. Essa característica pode permitir que novos proprietários de um dispositivo de segunda mão acessem os dados do aplicativo do proprietário anterior simplesmente reinstalando os aplicativos. Os desenvolvedores são aconselhados a limpar proativamente os dados do Keychain ao instalar o aplicativo ou durante o logout para mitigar esse risco. Aqui está um exemplo de código Swift demonstrando como limpar os dados do Keychain na primeira execução do aplicativo:

let userDefaults = UserDefaults.standard

if userDefaults.bool(forKey: "hasRunBefore") == false {
// Remove Keychain items here

// Update the flag indicator
userDefaults.set(true, forKey: "hasRunBefore")
userDefaults.synchronize() // Forces the app to update UserDefaults
}

Capacidades do App

No âmbito do desenvolvimento de aplicativos, sandboxing desempenha um papel crucial na melhoria da segurança. Este processo garante que cada aplicativo opere dentro de seu próprio diretório exclusivo, impedindo assim que acesse arquivos do sistema ou dados pertencentes a outros aplicativos. A aplicação dessas restrições é realizada por meio de políticas de sandbox, que fazem parte do Trusted BSD (MAC) Mandatory Access Control Framework.

Os desenvolvedores têm a capacidade de configurar certas capacidades ou permissões para seus aplicativos, como Data Protection ou Keychain Sharing. Essas permissões são aplicadas imediatamente após a instalação do aplicativo. No entanto, para acessar certos recursos protegidos, o aplicativo deve obter consentimento explícito do usuário no momento da primeira tentativa. Isso é alcançado por meio do uso de purpose strings ou usage description strings, que são apresentados aos usuários em um alerta de solicitação de permissão.

Para aqueles com acesso ao código-fonte, a verificação das permissões incluídas no arquivo Info.plist pode ser feita da seguinte forma:

  1. Abrir o projeto no Xcode.

  2. Localizar e abrir o arquivo Info.plist.

  3. Procurar por chaves prefixadas com "Privacy -", com a opção de visualizar chaves/valores brutos para clareza.

Ao lidar com um arquivo IPA, os seguintes passos podem ser seguidos:

  1. Descompactar o IPA.

  2. Localizar o arquivo Info.plist dentro de Payload/<appname>.app/.

  3. Converter o arquivo para o formato XML, se necessário, para uma inspeção mais fácil.

Por exemplo, as purpose strings no arquivo Info.plist podem parecer assim:

<plist version="1.0">
<dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Your location is used to provide turn-by-turn directions to your destination.</string>

Device Capabilities

O arquivo Info.plist de um aplicativo especifica capacidades do dispositivo que ajudam a App Store a filtrar aplicativos para compatibilidade com o dispositivo. Estas são definidas sob a chave UIRequiredDeviceCapabilities. Por exemplo:

<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>

Este exemplo indica que o aplicativo é compatível com o conjunto de instruções armv7. Os desenvolvedores também podem especificar capacidades como nfc para garantir que seu aplicativo esteja disponível apenas para dispositivos que suportam NFC.

Entitlements

Entitlements são outro aspecto crítico do desenvolvimento de aplicativos iOS, servindo como pares chave-valor que concedem permissões aos aplicativos para realizar certas operações além das verificações em tempo de execução. Por exemplo, habilitar Data Protection em um aplicativo envolve adicionar um entitlement específico no projeto Xcode, que é então refletido no arquivo de entitlements do aplicativo ou no arquivo de provisionamento móvel incorporado para IPAs.

References

Support HackTricks

Last updated