hacktricks/mobile-pentesting/ios-pentesting/ios-basics.md

22 KiB

<details>

<summary><strong>Aprenda hacking no AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>

Outras formas de apoiar o HackTricks:

* Se você quer ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**material oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos
* **Junte-se ao grupo** 💬 [**Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga**-me no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Compartilhe suas técnicas de hacking enviando PRs para os repositórios github** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).

</details>


# Separação de Privilégios e Sandbox

Aplicações acessíveis pelo usuário rodam como o usuário **mobile** enquanto processos críticos do sistema rodam como **root**.\
No entanto, o sandbox permite um melhor controle sobre ações que processos e aplicações podem executar.

Por exemplo, mesmo que dois processos rodem como o mesmo usuário (mobile), eles **não têm permissão para acessar ou modificar os dados um do outro**.

Cada aplicação é instalada em **`private/var/mobile/Applications/{ID aleatório}`**\
Uma vez instaladas, as aplicações têm acesso limitado de leitura a algumas áreas e funções do sistema (SMS, chamada telefônica...). Se uma aplicação deseja acessar uma **área protegida,** um **pop-up solicitando permissão** aparece.

# Proteção de Dados

Desenvolvedores de aplicativos podem aproveitar as APIs de _Proteção de Dados_ do iOS para implementar **controle de acesso refinado** para dados do usuário armazenados na memória flash. As APIs são construídas em cima do **Secure Enclave Processor** (SEP). O SEP é um coprocessador que fornece **operações criptográficas para proteção de dados e gerenciamento de chaves**. Uma chave de hardware específica do dispositivo - o **device UID** (ID Único) - é **embutida no enclave seguro**, garantindo a integridade da proteção de dados mesmo quando o kernel do sistema operacional está comprometido.

Quando um **arquivo é criado** no disco, uma nova chave **AES de 256 bits é gerada** com a ajuda do gerador de números aleatórios baseado em hardware do enclave seguro. O **conteúdo do arquivo é então criptografado com a chave gerada**. E então, essa **chave é salva criptografada com uma chave de classe** junto com **o ID da classe,** com **ambos os dados criptografados pela chave do sistema,** dentro do **metadado** do arquivo.

![](<../../.gitbook/assets/image (473).png>)

Para descriptografar o arquivo, o **metadado é descriptografado usando a chave do sistema**. Então, **usando o ID da classe** a **chave de classe é recuperada** **para descriptografar a chave do arquivo e descriptografar o arquivo.**

Arquivos podem ser atribuídos a uma de **quatro** **diferentes** **classes de proteção**, que são explicadas em mais detalhes no [Guia de Segurança da Plataforma Apple](https://help.apple.com/pdf/security/en_US/apple-platform-security-guide.pdf):

* **Proteção Completa (NSFileProtectionComplete)**: Uma chave derivada do código de acesso do usuário e do device UID protege esta chave de classe. A chave derivada é apagada da memória logo após o dispositivo ser bloqueado, tornando os dados inacessíveis até que o usuário desbloqueie o dispositivo.
* **Protegido a Menos que Aberto (NSFileProtectionCompleteUnlessOpen)**: Esta classe de proteção é semelhante à Proteção Completa, mas, se o arquivo estiver aberto quando desbloqueado, o aplicativo pode continuar acessando o arquivo mesmo se o usuário bloquear o dispositivo. Esta classe de proteção é usada quando, por exemplo, um anexo de e-mail está sendo baixado em segundo plano.
* **Protegido Até a Primeira Autenticação do Usuário (NSFileProtectionCompleteUntilFirstUserAuthentication)**: O arquivo pode ser acessado assim que o usuário desbloquear o dispositivo pela primeira vez após a inicialização. Ele pode ser acessado mesmo se o usuário bloquear o dispositivo subsequentemente e a chave de classe não for removida da memória.
* **Sem Proteção (NSFileProtectionNone)**: A chave para esta classe de proteção é protegida apenas com o UID. A chave de classe é armazenada em "Armazenamento Apagável", que é uma região da memória flash no dispositivo iOS que permite o armazenamento de pequenas quantidades de dados. Esta classe de proteção existe para apagamento remoto rápido (deleção imediata da chave de classe, o que torna os dados inacessíveis).

Todas as chaves de classe, exceto `NSFileProtectionNone`, são criptografadas com uma chave derivada do device UID e do código de acesso do usuário. Como resultado, a descriptografia só pode ocorrer no próprio dispositivo e requer o código de acesso correto.

Desde o iOS 7, a classe de proteção de dados padrão é "Protegido Até a Primeira Autenticação do Usuário".

[**FileDP**](https://github.com/abjurato/FileDp-Source) é um programa que você pode carregar e usar dentro do iPhone para **inspecionar a classe de proteção de dados** de cada arquivo.

## O Keychain

O keychain é um **container criptografado** onde cada aplicativo pode **armazenar** pedaços de **informação sensível** e apenas o mesmo aplicativo (ou aplicativos autorizados) pode recuperar o conteúdo.\
O iOS **gera sua própria senha para o keychain** e **armazena** uma versão **criptografada** desta chave no dispositivo. Esta senha é criptografada com AES usando uma chave AES criada por uma função **PBKDF2** do **código de acesso do usuário + sal** (o **UID de 256 bits do dispositivo** **acessível** **apenas** pelo chipset do enclave **seguro** no dispositivo). Devido ao uso deste UID do dispositivo como sal, um dispositivo não será capaz de descriptografar o keychain de um dispositivo diferente mesmo conhecendo o código de acesso dos usuários.

O acesso ao Keychain é gerenciado pelo daemon **`securityd`**, que concede acesso de acordo com os `Keychain-access-groups`, `application-identifier` e `application-group` entitlements do aplicativo.

A [API Keychain](https://developer.apple.com/library/content/documentation/Security/Conceptual/keychainServConcepts/02concepts/concepts.html) inclui as seguintes operações principais:

* `SecItemAdd`
* `SecItemUpdate`
* `SecItemCopyMatching`
* `SecItemDelete`

As únicas maneiras de tentar força bruta (BF) nesta senha é despejando a chave criptografada e BF o código de acesso + sal (a função **pbkdf2** usa **pelo menos 10000 iterações**). Ou tentando **BF dentro do dispositivo** para evitar BFing o sal, no entanto, o enclave seguro garante que haja pelo menos um **atraso de 5s entre 2 tentativas de senha falhadas**.

Você pode configurar **proteção de dados para itens do Keychain** definindo a chave `kSecAttrAccessible` na chamada para `SecItemAdd` ou `SecItemUpdate`. Os seguintes valores de acessibilidade configuráveis para kSecAttrAccessible são as classes de Proteção de Dados do Keychain:

* **`kSecAttrAccessibleAlways`**: Os dados no item do Keychain podem **sempre ser acessados**, independentemente de o dispositivo estar bloqueado.
* **`kSecAttrAccessibleAlwaysThisDeviceOnly`**: Os dados no item do Keychain podem **sempre** **ser** **acessados**, independentemente de o dispositivo estar bloqueado. Os dados **não serão incluídos em um backup do iCloud** ou local.
* **`kSecAttrAccessibleAfterFirstUnlock`**: Os dados no item do Keychain não podem ser acessados após uma reinicialização até que o **dispositivo tenha sido desbloqueado uma vez** pelo usuário.
* **`kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly`**: Os dados no item do Keychain não podem ser acessados após uma reinicialização até que o **dispositivo tenha sido desbloqueado uma vez** pelo usuário. Itens com este atributo **não migram para um novo dispositivo**. Assim, após restaurar de um backup de um dispositivo diferente, esses itens não estarão presentes.
* **`kSecAttrAccessibleWhenUnlocked`**: Os dados no item do Keychain podem ser acessados **apenas enquanto o dispositivo está desbloqueado** pelo usuário.
* **`kSecAttrAccessibleWhenUnlockedThisDeviceOnly`**: Os dados no item do Keychain podem ser acessados **apenas enquanto o dispositivo está desbloqueado** pelo usuário. Os dados **não serão incluídos em um backup do iCloud ou local**.
* **`kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly`**: Os dados no Keychain podem ser acessados **apenas quando o dispositivo está desbloqueado**. Esta classe de proteção **está disponível apenas se um código de acesso estiver configurado** no dispositivo. Os dados **não serão incluídos em um backup do iCloud ou local**.

**`AccessControlFlags`** definem os mecanismos com os quais os usuários podem autenticar a chave (`SecAccessControlCreateFlags`):

* **`kSecAccessControlDevicePasscode`**: Acessar o item via um código de acesso.
* **`kSecAccessControlBiometryAny`**: Acessar o item via uma das impressões digitais registradas no Touch ID. Adicionar ou remover uma impressão digital não invalidará o item.
* **`kSecAccessControlBiometryCurrentSet`**: Acessar o item via uma das impressões digitais registradas no Touch ID. Adicionar ou remover uma impressão digital _irá_ invalidar o item.
* **`kSecAccessControlUserPresence`**: Acessar o item via uma das impressões digitais registradas (usando Touch ID) ou recorrer ao código de acesso.

Observe que as chaves protegidas pelo Touch ID (via `kSecAccessControlBiometryAny` ou `kSecAccessControlBiometryCurrentSet`) são protegidas pelo Secure Enclave: O Keychain mantém apenas um token, não a chave real. A chave reside no Secure Enclave.

O iPhone usa o **código de acesso introduzido pelo usuário ao desbloquear o dispositivo para descriptografar os segredos no keychain**.

O iOS usa o _**AppIdentifierPrefix**_ (ID da Equipe) e o _**BundleIdentifier**_ (fornecido pelo desenvolvedor) para impor **controle de acesso sobre itens do keychain**. Então, a mesma equipe **pode** **configurar** **2 aplicativos para compartilhar itens do keychain**.

Quando um processo de backup é iniciado, os **dados do keychain que são salvos permanecem criptografados e a senha do keychain não está incluída no backup**.

{% hint style="warning" %}
**Em um dispositivo com jailbreak, o keychain não está protegido.**
{% endhint %}

### **Persistência de Dados do Keychain**

No iOS, quando um aplicativo é desinstalado, os dados do Keychain usados pelo aplicativo são retidos pelo dispositivo, ao contrário dos dados armazenados pelo sandbox do aplicativo, que são apagados. No caso de um **usuário vender seu dispositivo sem realizar uma redefinição de fábrica, o comprador do dispositivo pode ser capaz de acessar as contas de aplicativos e dados do usuário anterior reinstalando** os mesmos aplicativos usados pelo usuário anterior. Isso não requereria habilidade técnica para ser realizado.

Não há uma API do iOS que os desenvolvedores possam usar para forçar a limpeza de dados quando um aplicativo é desinstalado. Em vez disso, os desenvolvedores devem tomar as seguintes medidas para evitar que os dados do Keychain persistam entre instalações de aplicativos:

* Quando um aplicativo é lançado pela primeira vez após a instalação, limpe todos os dados do Keychain associados ao aplicativo. Isso impedirá que o segundo usuário do dispositivo ganhe acesso acidental às contas do usuário anterior. O seguinte exemplo em Swift é uma demonstração básica deste procedimento de limpeza:
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
}
  • Ao desenvolver a funcionalidade de logout para uma aplicação iOS, certifique-se de que os dados do Keychain são apagados como parte do logout da conta. Isso permitirá que os usuários limpem suas contas antes de desinstalar uma aplicação.

Capacidades da Aplicação

Cada aplicação tem um diretório caseiro único e é isolada (sandboxed), de modo que não podem acessar recursos protegidos do sistema ou arquivos armazenados pelo sistema ou por outras aplicações. Essas restrições são implementadas através de políticas de sandbox (também conhecidas como profiles), que são aplicadas pelo Trusted BSD (MAC) Mandatory Access Control Framework através de uma extensão do kernel.

Algumas capacidades/permissões podem ser configuradas pelos desenvolvedores da aplicação (por exemplo, Proteção de Dados ou Compartilhamento de Keychain) e terão efeito direto após a instalação. No entanto, para outras, o usuário será explicitamente solicitado na primeira vez que a aplicação tentar acessar um recurso protegido.

Purpose strings ou strings de descrição de uso são textos personalizados que são oferecidos aos usuários no alerta de solicitação de permissão do sistema ao pedir permissão para acessar dados ou recursos protegidos.

Se tiver o código-fonte original, você pode verificar as permissões incluídas no arquivo Info.plist:

  • Abra o projeto com o Xcode.
  • Encontre e abra o arquivo Info.plist no editor padrão e procure pelas chaves que começam com "Privacy -".

Você pode mudar a visualização para exibir os valores brutos clicando com o botão direito e selecionando "Show Raw Keys/Values" (desta forma, por exemplo, "Privacy - Location When In Use Usage Description" se transformará em NSLocationWhenInUseUsageDescription).

Se tiver apenas o IPA:

  • Descompacte o IPA.
  • O Info.plist está localizado em Payload/<appname>.app/Info.plist.
  • Converta-o se necessário (por exemplo, plutil -convert xml1 Info.plist) conforme explicado no capítulo "iOS Basic Security Testing", seção "The Info.plist File".
  • Inspecione todas as chaves de strings de propósito no Info.plist, geralmente terminando com UsageDescription:
<plist version="1.0">
<dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Sua localização é usada para fornecer direções passo a passo até seu destino.</string>

Capacidades do Dispositivo

As capacidades do dispositivo são usadas pela App Store para garantir que apenas dispositivos compatíveis sejam listados e, portanto, tenham permissão para baixar a aplicação. Elas são especificadas no arquivo Info.plist da aplicação sob a chave UIRequiredDeviceCapabilities.

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

Normalmente, você encontrará a capacidade armv7, o que significa que o aplicativo é compilado apenas para o conjunto de instruções armv7, ou se é um aplicativo universal de 32/64 bits.

Por exemplo, um aplicativo pode depender completamente do NFC para funcionar (por exemplo, um aplicativo "NFC Tag Reader"). De acordo com o arquivo de referência de compatibilidade de dispositivos iOS, o NFC está disponível apenas a partir do iPhone 7 (e iOS 11). Um desenvolvedor pode querer excluir todos os dispositivos incompatíveis definindo a capacidade do dispositivo nfc.

Entitlements

Entitlements são pares de chave-valor que são assinados em um aplicativo e permitem autenticação além de fatores de tempo de execução, como o ID de usuário UNIX. Como os entitlements são assinados digitalmente, eles não podem ser alterados. Entitlements são usados extensivamente por aplicativos do sistema e daemons para realizar operações privilegiadas específicas que, de outra forma, exigiriam que o processo fosse executado como root. Isso reduz muito o potencial de escalonamento de privilégios por um aplicativo do sistema ou daemon comprometido.

Por exemplo, se você quiser definir a capacidade "Proteção de Dados Padrão", você precisaria ir até a aba Capabilities no Xcode e habilitar Data Protection. Isso é escrito diretamente pelo Xcode no arquivo <appname>.entitlements como o entitlement com.apple.developer.default-data-protection com o valor padrão NSFileProtectionComplete. No IPA, podemos encontrar isso no embedded.mobileprovision como:

<key>Entitlements</key>
<dict>
...
<key>com.apple.developer.default-data-protection</key>
<string>NSFileProtectionComplete</string>
</dict>

Para outras capacidades, como HealthKit, o usuário deve ser solicitado a dar permissão, portanto, não é suficiente adicionar os direitos, chaves especiais e strings devem ser adicionadas ao arquivo Info.plist do aplicativo.

Fundamentos de Objective-C e Swift

Objective-C possui um runtime dinâmico, então quando um programa Objective-C é executado no iOS, ele chama bibliotecas cujos endereços são resolvidos em tempo de execução comparando o nome da função enviada na mensagem contra uma lista de todos os nomes de funções disponíveis.

No início, apenas aplicativos criados pela Apple rodavam nos iPhones, então eles tinham acesso a tudo já que eram confiáveis. No entanto, quando a Apple permitiu aplicativos de terceiros, a Apple simplesmente removeu os arquivos de cabeçalho das funções poderosas para "escondê-las" dos desenvolvedores. No entanto, os desenvolvedores descobriram que funções "seguras" precisavam de algumas dessas funções não documentadas e apenas criando um arquivo de cabeçalho personalizado com os nomes das funções não documentadas, era possível invocar essas poderosas funções ocultas. De fato, a Apple, antes de permitir a publicação de um aplicativo, verifica se o aplicativo chama alguma dessas funções proibidas.

Então, apareceu o Swift. Como Swift é estaticamente vinculado (não resolve o endereço das funções em tempo de execução como Objective-C), é mais fácil verificar as chamadas que um programa Swift vai fazer através de análise estática de código.

Gerenciamento de Dispositivos

A partir da versão 6 do iOS, existe suporte integrado para capacidade de gerenciamento de dispositivos com controles de granulação fina que permitem a uma organização controlar os dispositivos apple corporativos.
O registro pode ser iniciado pelo usuário instalando um agente para acessar os aplicativos corporativos. Neste caso, o dispositivo geralmente pertence ao usuário.
Ou a empresa pode indicar os números de série dos dispositivos comprados ou o ID do pedido de compra e especificar o perfil MDM para instalar nesses dispositivos. Note que a Apple não permite registrar um dispositivo particular desta forma duas vezes. Uma vez que o primeiro perfil é deletado, o usuário precisa dar consentimento para instalar outro.

O usuário pode ver as políticas instaladas em Configurações --> Geral --> Gerenciamento de Dispositivos e Perfis

Como essas políticas MDM estão verificando e limitando outros aplicativos, elas estão rodando com mais privilégios.
Uma política MDM pode exigir que os usuários tenham um código de acesso definido com uma complexidade mínima de senha.
Os perfis são vinculados ao deviceID, assinados e criptografados pelo servidor MDM e são à prova de adulteração. Eles não podem ser removidos sem perder todos os dados corporativos.
Perfis MDM permitem apagar todos os dados se houver X tentativas falhas de senha. Além disso, o administrador pode apagar remotamente o iPhone a qualquer momento via interface MDM.

Agentes MDM também verificam possíveis jailbreaks do dispositivo, pois isso é um estado muito perigoso para um iPhone.

Aprenda hacking no AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras maneiras de apoiar o HackTricks: