
CVE-2026-105221 - gist RubyGem - Alta - MITM - Roubo de token OAuth do GitHub
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · cve-2026-105221-gist-tls
gist RubyGem < 6.1.0 - defunkt
Classe: Bypass de verificação TLS (roubo de credenciais) Alcance: Remoto (on-path)
http_connection define OpenSSL::SSL::VERIFY_NONE. O HTTPS para o GitHub ainda criptografa, mas qualquer certificado é aceito. Um par on-path pode ler o token OAuth que a CLI envia e, em seguida, ler e alterar os gists da vítima.
| ID | CVE-2026-105221 |
| Classe | Bypass de verificação TLS (roubo de credenciais) |
| Alcance | Remoto (on-path) |
| CWE | CWE-295 |
| CVSS | Alto: 7.4 CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N (VulnCheck 4.0: 9.1) |
| Produto | gist |
| Afetado | 4.0.0 até 6.0.0. Fixação do laboratório 6.0.0. Corrigido em 6.1.0 (07ccc1a). |
| Autenticação | MITM on-path da CLI gist |
| Licença | GNU Affero GPL v3.0 |
| Laboratório | somente 127.0.0.1 |
O atacante fica no caminho e captura o token do GitHub.
CN=mitm.invalid é suficiente.Authorization: token .... O login (gist --login) e o upload/listagem/exclusão de gists passam todos por http_connection. O token em ~/.gist trafega nesse socket.gist. Gists privados, atualizações, exclusões.Eles precisam de uma posição na rede: Wi-Fi hostil, um proxy, uma máquina no meio. Isso não é RCE remoto não autenticado contra um servidor.
A 6.1.0 define VERIFY_PEER. O mesmo certificado falso morre com certificate verify failed (self-signed certificate) e o token nunca sai do cliente.
A VulnCheck publicou CVE-2026-105221. Siyang Wu reportou. A Issue 373 é o ticket público. O PR 374 alterou o modo de verificação. Eu reproduzi a CVE pública em laboratório. Não havia PoC público.
lib/gist.rb http_connection na 6.0.0:
if uri.scheme == "https"
connection.use_ssl = true
connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
6.1.0 é VERIFY_PEER.
O laboratório de loopback é um stub HTTPS falso do GitHub Enterprise com um certificado autoassinado. GITHUB_URL=https://127.0.0.1:8443 coloca o gist em modo GHE (POST /api/v3/gists). Um token de laboratório CVE-2026-105221-WITNESS fica no arquivo ~/.gist.* correspondente. O gist 6.0.0 conclui o TLS, o stub captura Authorization: token CVE-2026-105221-WITNESS e grava o witness. O gist 6.1.0 contra o mesmo stub falha no TLS. A contagem de capturas no 6.1.0 permanece zero. Nada se comunica com api.github.com.
SUCCESS CVE-2026-105221 vuln-tls=ok token-captured=1 patched-tls=fail witness-written=yes CVE-2026-105221-WITNESS
Nenhum erro já registrado. O primeiro run.sh imprimiu SUCCESS. Um reverse shell. Teatro. O oráculo é o token de laboratório capturado na 6.0.0 e o erro de TLS autoassinado na 6.1.0.
cd lab
./run.sh
Aponte apenas para https://127.0.0.1:18210 (container 8443). O run.sh instala o gist 6.0.0 e 6.1.0 a partir do RubyGems, serve o stub dentro do container e, em seguida, desmonta a stack. Certificado autoassinado. Sem GitHub real.
Atualize a gem gist para 6.1.0 ou superior.
lib/gist.rb v6.0.0 L466-L468