Skip to main content

Finding YAML Deserialization with Snyk Code

Written by
Headshot of Calum Hutton

Calum Hutton

February 23, 2023

0 mins read

I conducted some research to try and identify YAML Injection issues in open-source projects using Snyk Code. Though the vulnerability itself is not a new one, the potential impact of YAML Injection is high, which made it a good candidate for research. This research led to the discovery of several issues in open-source projects written in Python, PHP and Ruby. This article focuses on the issue found in geokit-rails version 2.3.2, a plugin for Ruby on Rails

YAML

YAML is more than a mere data interchange format such as JSON, the specification describes a number of advanced features that make it ripe for security investigation such as:

  • Custom tags (i.e. PyYAML)

  • Anchors and aliases

  • Merged attributes

  • Multiple-document streams

YAML can also be used to serialize binary data and arbitrary objects in various languages, potentially leading to deserialization vulnerabilities. These vulnerabilities are the target of this research, since successful exploitation often leads to Remote Code Execution (RCE).

YAML deserialization in Ruby

In Ruby, YAML parsing is built into the core language, so no additional libraries are needed. If an application uses the builtin Ruby YAML parser, it is vulnerable to deserialization attacks if YAML.load() or YAML.load_file() is used instead of YAML.safe_load() or YAML.safe_load_file(), respectively. An alternative, safe-by-default YAML parser is available in the SafeYAML project.

The following script and output demonstrate an unsafe way to load YAML with YAML.load().

Error rendering contentCodeBlockSnippets

The var variable holds a simple Ruby hash, with the yaml variable containing the equivalent hash, serialized in YAML form. Both putsstatements display the same hash, because the yaml variable has been deserialized back from a YAML string into a hash via YAML.load(). More complex objects can also be serialized and deserialized in this way. 

During the initial stages of this research, I came across a Universal Ruby YAML deserialization gadget that was effective on Ruby versions 2.x to 3.x. which, when deserialized, would trigger arbitrary command execution.

Error rendering contentCodeBlockSnippets

The above YAML payload will execute the id command upon deserialization if it is parsed via YAML.load() or YAML.load_file().

Case study: geokit-rails (2.3.2)

The geokit-rails gem is a plugin for Ruby on Rails that provides location services for the application. The plugin uses the unsafe YAML.load() method via the retrieve_location_from_cookie_or_service() method in geokit-rails/ip_geocode_lookup.rb:

Error rendering contentCodeBlockSnippets

The data flowing into the unsafe YAML.load() method originates from the Ruby on Rails cookies parameter, which holds the cookies sent in the request. This is good news for an attacker as the cookies can be directly controlled by crafting the appropriate HTTP request. 

Proof of concept

I set up a Rails application running the geokit-rails plugin (version 2.3.2) on Ruby 3.0.0. The following HTTP request was sent to the application to exploit the issue. It includes the URL-encoded YAML payload in the geo_location cookie.

Error rendering contentCodeBlockSnippets

Within the Rails application, the payload was deserialized and executed, running the id command to prove command execution.

Error rendering contentCodeBlockSnippets

For a system utilizing geokit-rails, an attacker exploiting this vulnerability could initiate RCE, potentially allowing for total system takeover. 

Remediation

This issue was responsibly disclosed to the maintainer of geokit-rails and was fixed in version 2.5.0 of the software by replacing the YAML containing the coordinate information with JSON. From this research, Snyk Code’s rules to detect YAML injection were improved and enhanced, meaning even more of these issues should now be detectable in user projects. 

Get started in capture the flag

Learn how to solve capture the flag challenges by watching our virtual 101 workshop on demand.