Marshal Madness: A Decade-Long Cycle of Patches and Bypasses |
---|
Documenting the Evolution of Exploitation Techniques
The story of deserialization exploits in Ruby's Marshal module serves as a crucial case study in understanding systemic patterns that resist conventional fixes. By tracing the evolution of this phenomenon, we can better comprehend why fundamental changes to the Ruby ecosystem are necessary rather than continued reliance on patch-and-hope approaches.
Introduction
Trail of Bits has been documenting Ruby deserialization bugs since at least 2015, while Hal Brodigan, a former Trail of Bits employee from 2012 to 2015, documented even earlier Ruby examples. Additionally, Java and PHP have CVEs going back to 2011 and 2007, respectively, regarding deserialization of untrusted data.
The Beginning: A Bug Tracker Issue
On January 31, 2013, Charlie Somerville (now Hailey) created a Ruby bug tracker issue discussing the dangers of Marshal.load in Ruby version 2.0.0. This marked the beginning of the Marshal deserialization exploitation lineage.
The Early Years: Phrack and Beyond
On May 6, 2016, the concept of Marshal deserialization exploitation found its way into a subsection of a section of a Phile of a Phrack Issue. The author, joernchen, credited Hailey Somerville and stated that the technique is patched in Rails 4.1 unless you modify the default behavior.
The Modern Era: Industrialized Exploit Development
The modern era of Ruby deserialization exploitation began with Alex Leahu's blog post on March 13, 2024, titled "Discovering Deserialization Gadget Chains in Rubyland." He referenced earlier works and used grep to search for exploit gadgets. However, shortly after, another post took everything to another level, publishing a research paper by Peter Stöckli and GitHub Security Lab on June 20, 2024.
The Never-Ending Cycle: Lessons Learned
Despite the persistence of these issues in a security-conscious codebase like RubyGems.org, we can make recommendations to improve the situation. We recommend slowly deprecating and eventually removing the Marshal module in stages, as it is too dangerous to use in 2025.
Conclusion
The evolution of deserialization exploits in Ruby's Marshal module serves as a crucial case study in understanding systemic patterns that resist conventional fixes. By tracing this phenomenon, we can better comprehend why fundamental changes to the Ruby ecosystem are necessary rather than continued reliance on patch-and-hope approaches.
For more information about our work and recommendations for improving the situation, please visit Trail of Bits' Ruby Security Page