# Análise estática no iOS: binário, Info.plist e entitlements

> As mesmas perguntas do Android, do lado do IPA: proteções do binário, App Transport Security, entitlements e o que não deveria estar dentro do pacote.

- Autor: Marcelo Silva
- Publicado em: 2026-10-14
- Tema: Segurança
- Série: Segurança Mobile, parte 9 de 11 (https://marcelxsilva.dev/series/seguranca-mobile/)
- URL: https://marcelxsilva.dev/artigos/analise-estatica-ios/

O Android tem o APK; o iOS tem o IPA, também um arquivo ZIP, só que com uma estrutura interna diferente e um conjunto próprio de proteções para checar. Boa parte das perguntas é parecida com as que os artigos anteriores desta série já fizeram para Android, mas as respostas vêm de ferramentas e formatos específicos da Apple.

## Abrindo o pacote

Dentro de um IPA descompactado, o app em si fica numa pasta `Payload/<Nome>.app/`. O binário executável, que tem o mesmo nome definido na chave `CFBundleExecutable` do `Info.plist`, é o alvo principal da análise estática: é nele que ficam compiladas as strings, a lógica nativa e, como visto no [artigo sobre segredos no binário](https://marcelxsilva.dev/artigos/segredos-no-binario/), as variáveis de ambiente embutidas no build.

```bash
mkdir -p pentest-ios && cd pentest-ios
unzip -q -o example.ipa -d ipa-out
A=$(ls -d ipa-out/Payload/*.app)
B="${A}/$(/usr/libexec/PlistBuddy -c 'Print CFBundleExecutable' "${A}/Info.plist")"
```

As duas variáveis, `A` (o caminho do `.app`) e `B` (o caminho do binário dentro dele), são usadas nos comandos a seguir.

## Proteções do binário

O macOS já vem com um conjunto de ferramentas de linha de comando, parte do Xcode, que permitem inspecionar essas proteções sem precisar de nada além do próprio sistema:

| Proteção | Ferramenta | O que verificar |
|---|---|---|
| [PIE](https://developer.apple.com/library/archive/documentation/Security/Conceptual/SecurityOverview/BuildingProtectionsIntoiPhoneOS/BuildingProtectionsIntoiPhoneOS.html) (Position Independent Executable) | `otool -hv` | Precisa estar presente. Sem PIE, o endereço de carregamento do binário é previsível, o que facilita explorar vulnerabilidades de memória |
| Stack canary | `otool -Iv` (procurando `___stack_chk_guard`) | Detecta estouro de pilha (buffer overflow) antes que ele corrompa o fluxo de execução |
| ARC (Automatic Reference Counting) | `otool -Iv` (procurando `_objc_release`) | Gerenciamento automático de memória em Objective-C, reduz uma classe inteira de bugs de memória |
| Criptografia do binário (`cryptid`) | `otool -Vl` (seção `LC_ENCRYPT`) | Em um IPA baixado da App Store, o valor esperado é `1` (binário cifrado pela Apple). Builds locais ou de teste normalmente saem com `cryptid 0`, o que é esperado nesse contexto e não é, sozinho, uma falha |

```bash
otool -hv "${B}" | grep PIE
otool -Iv "${B}" | grep -w ___stack_chk_guard
otool -Iv "${B}" | grep -w _objc_release
otool -arch all -Vl "${B}" | grep -A4 LC_ENCRYPT
```

Essas quatro proteções existem no nível do compilador e do sistema operacional, então a ausência de qualquer uma delas num app atual costuma indicar uma configuração de build incomum, mais do que uma escolha deliberada.

## Funções criptográficas e de manipulação de memória fracas

O mesmo `otool` ajuda a localizar o uso de funções historicamente associadas a vulnerabilidades: algoritmos de hash considerados fracos para uso em segurança, como [MD5](https://datatracker.ietf.org/doc/html/rfc6151) e [SHA-1](https://csrc.nist.gov/News/2022/nist-retires-sha-1-cryptographic-algorithm), geradores de número pseudoaleatório não criptográficos (`rand`, `random`) usados para gerar algo que precisaria ser imprevisível (como um token), e funções clássicas de manipulação de string em C sem checagem de limite, como `strcpy`, `sprintf` e `gets`, historicamente associadas a estouros de buffer.

```bash
for f in _CC_MD5 _CC_SHA1 _random _srand _rand _gets _strcpy _sprintf _vsprintf _malloc; do
  c=$(otool -Iv "${B}" | grep -cw "$f"); [ "$c" != 0 ] && echo "$f $c"
done
```

A simples presença de uma dessas funções no binário raramente é, por si só, uma vulnerabilidade: a maior parte vem embutida em bibliotecas de terceiros, não no código do app. O passo seguinte é sempre confirmar se o uso é do código próprio do app (por exemplo, hashear uma senha com MD5) ou de uma dependência que a usa para outra finalidade.

## Info.plist

O [`Info.plist`](https://developer.apple.com/documentation/bundleresources/information-property-list) é o arquivo de configuração central de um app iOS, e vale uma leitura dedicada depois de convertido para JSON com a ferramenta `plutil`, também nativa do macOS:

```bash
plutil -convert json -o info.json "${A}/Info.plist"
```

```python
import json
d = json.load(open('info.json'))
print('ATS:', json.dumps(d.get('NSAppTransportSecurity')))
print('URL schemes:', [s for t in d.get('CFBundleURLTypes', []) for s in t.get('CFBundleURLSchemes', [])])
for k in d:
    if any(x in k.upper() for x in ('SECRET', 'KEY', 'TOKEN', 'CLIENT', 'API', 'PASS')):
        print('chave suspeita:', k)
```

Dois pontos de atenção recorrentes:

- **App Transport Security (ATS)**: a chave `NSAppTransportSecurity` controla as regras de conexão de rede do app. A chave `NSAllowsArbitraryLoads: true` desliga essa proteção por completo, permitindo conexões HTTP sem criptografia para qualquer domínio. Mesmo quando essa chave está ausente, vale checar se existem exceções por domínio específico (`NSExceptionDomains`) além do que seria esperado para ambientes de teste local.
- **Esquemas de URL customizados**: declarados em `CFBundleURLTypes`, definem como outros apps (ou um navegador) conseguem abrir o app por um link como `meuapp://`. Como no Android, todo parâmetro recebido por esse caminho é entrada não confiável.

## Entitlements

[Entitlements](https://developer.apple.com/documentation/bundleresources/entitlements) são permissões especiais concedidas ao app pela Apple, assinadas junto com o binário:

```bash
codesign -d --entitlements :- "${A}" | plutil -p -
```

Alguns merecem checagem redobrada num app de produção:

| Entitlement | Esperado em produção |
|---|---|
| `get-task-allow` | `false`. Com `true`, qualquer debugger pode anexar ao processo do app, incluindo num aparelho sem jailbreak |
| `aps-environment` | `production`, para que as notificações push usem o ambiente correto da Apple |
| `com.apple.developer.associated-domains` | Só os domínios realmente controlados pelo dono do app. Um domínio associado permite que esse domínio abra o app diretamente (Universal Links) e participe de recursos como AutoFill de senha |

## Arquivos soltos dentro do `.app`

Por fim, vale uma varredura pela pasta do app em busca de arquivos que não deveriam estar ali: variáveis de ambiente (`.env`), certificados privados (`.p12`, `.pem`), código-fonte TypeScript não compilado ou sourcemaps (`.ts`, `.map`):

```bash
find "${A}" -maxdepth 2 -type f \( -iname '*.env*' -o -iname '*.json' -o -iname '*.p12' -o -iname '*.pem' -o -iname '*.ts' -o -iname '*.map' \)
```

Em apps React Native, o arquivo `modules.json`, quando presente, lista as dependências JavaScript do projeto com suas versões, informação que, embora não seja um segredo, ajuda quem procura uma vulnerabilidade conhecida (CVE) numa dessas dependências. Já um arquivo como `GoogleService-Info.plist`, do Firebase, é esperado e normalmente não representa risco por si só: ele contém identificadores de projeto, não segredos.

Por fim, as mesmas buscas do bundle JavaScript, descritas no [artigo sobre abrir um APK](https://marcelxsilva.dev/artigos/abrindo-um-apk/), valem para o bundle do iOS, que fica em `${A}/main.jsbundle`, e o `strings` do binário principal continua sendo um atalho rápido para achar algo óbvio:

```bash
strings "${B}" | grep -iE 'secret|client_id|api_key|https://' | sort -u | head -50
```

## O que falta: o app em execução

Tudo isso, de novo, é análise estática. Ela identifica proteções presentes ou ausentes e configurações de risco, mas não confirma como o app se comporta de fato quando está rodando, conectado à rede e manipulando dados reais. É esse o assunto do próximo artigo: a análise dinâmica, com o app instrumentado por ferramentas que observam e alteram seu comportamento em tempo real.
