Skip to content

Fix json_marshaller Universal Deserialisation Gadget of user-controlled data #3183

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from

Conversation

odaysec
Copy link

@odaysec odaysec commented May 17, 2025

return_value(::JSON.load(data))
rescue => e

To fix the issue, replace the unsafe JSON.load method with the safer JSON.parse method. The JSON.parse method does not allow the deserialization of arbitrary objects, making it a secure alternative for handling untrusted JSON data. Additionally, ensure that the input data is validated or sanitized before parsing.

The changes will be made in the load method of the JsonMarshaller class in lib/new_relic/agent/new_relic_service/json_marshaller.rb. Specifically:

  1. Replace JSON.load(data) with JSON.parse(data).
  2. Ensure that the data is a valid JSON string before parsing.

Deserializing untrusted data using any method that allows the construction of arbitrary objects is easily exploitable and, in many cases, allows an attacker to execute arbitrary code.

POC

The following calls the Marshal.load, JSON.load, YAML.load, Oj.load and Ox.parse_obj methods on data from an HTTP request. Since these methods are capable of deserializing to arbitrary objects, this is inherently unsafe.

require 'json'
require 'yaml'
require 'oj'

class UserController < ActionController::Base
  def marshal_example
    data = Base64.decode64 params[:data]
    object = Marshal.load data
    # ...
  end

  def json_example
    object = JSON.load params[:json]
    # ...
  end

  def yaml_example
    object = YAML.load params[:yaml]
    # ...
  end

  def oj_example
    object = Oj.load params[:json]
    # ...
  end

  def ox_example
    object = Ox.parse_obj params[:xml]
    # ...
  end
end

Using JSON.parse and YAML.safe_load instead, as in the following example, removes the vulnerability. Similarly, calling Oj.load with any mode other than :object is safe, as is calling Oj.safe_load. Note that there is no safe way to deserialize untrusted data using Marshal.

require 'json'

class UserController < ActionController::Base
  def safe_json_example
    object = JSON.parse params[:json]
    # ...
  end

  def safe_yaml_example
    object = YAML.safe_load params[:yaml]
    # ...
  end

  def safe_oj_example
    object = Oj.load params[:yaml], { mode: :strict }
    # or
    object = Oj.safe_load params[:yaml]
    # ...
  end
end

References

Overview

Describe the changes present in the pull request

Submitter Checklist:

  • Include a link to the related GitHub issue, if applicable
  • Include a security review link, if applicable

Testing

The agent includes a suite of unit and functional tests which should be used to
verify your changes don't break existing functionality. These tests will run with
GitHub Actions when a pull request is made. More details on running the tests locally can be found
here for our unit tests,
and here for our functional tests.
For most contributions it is strongly recommended to add additional tests which
exercise your changes.

Reviewer Checklist

  • Perform code review
  • Add performance label
  • Perform appropriate level of performance testing
  • Confirm all checks passed
  • Add version label prior to acceptance

@CLAassistant
Copy link

CLAassistant commented May 17, 2025

CLA assistant check
All committers have signed the CLA.

@github-actions github-actions bot added the community To tag external issues and PRs submitted by the community label May 17, 2025
@kaylareopelle
Copy link
Contributor

Hi @odaysec! Checking in on this PR. I see a few errors related to HTTPX, but I think those are unrelated. Would you mind merging dev into your branch?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
community To tag external issues and PRs submitted by the community
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants