HIGH xml external entitiesrails

Xml External Entities in Rails

How Xml External Entities Manifests in Rails

Xml External Entities (XXE) vulnerabilities in Rails applications typically arise when XML parsing is enabled without proper configuration. Rails, by default, uses Nokogiri for XML parsing, which can be vulnerable to XXE attacks if not properly configured.

The most common attack pattern involves an attacker submitting malicious XML payloads that contain external entity definitions. For example:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
  <!ELEMENT foo ANY >
  <!ENTITY xxe SYSTEM "file:///etc/passwd" >
]>
<foo>&xxe;</foo>

When a Rails application parses this XML without proper safeguards, it may read the contents of /etc/passwd and return it in the response, effectively leaking sensitive system information.

Rails applications are particularly vulnerable when using XML-based formats like RSS feeds, SOAP APIs, or when accepting XML data in API endpoints. The vulnerability manifests in several ways:

  • File disclosure: Reading arbitrary files from the server filesystem
  • SSRF: Making internal network requests to internal services
  • Denial of Service: Causing XML entity expansion to consume excessive memory
  • Port scanning: Using external entities to probe internal network services

A typical Rails controller vulnerable to XXE might look like this:

class Api::V1::FeedController < ApplicationController
  def create
    feed = Feedjira::Feed.parse(params[:xml])
    render json: { title: feed.title, entries: feed.entries }
  end
end

The issue here is that Feedjira (and many other XML libraries) will parse external entities by default unless explicitly configured not to. An attacker could craft a malicious RSS feed that includes external entities, and when your application parses it, the entities would be resolved.

Another common scenario is when Rails applications use XML for configuration files or import/export functionality. For instance, a Rails app that allows users to upload XML configuration files for import might be vulnerable if it doesn't properly sanitize the XML before parsing.

Rails-Specific Detection

Detecting XXE vulnerabilities in Rails applications requires examining both the code and the runtime behavior. Here are Rails-specific detection methods:

Code Analysis: Search your Rails codebase for XML parsing operations. Look for patterns like:

grep -r "Nokogiri::XML" app/

Or search for common XML processing gems:

grep -r "Feedjira\|LibXML\|REXML" app/

When you find XML parsing code, examine whether it's using safe parsing options. Vulnerable patterns include:

# VULNERABLE - no entity processing disabled
Nokogiri::XML(xml_string)

Safe patterns should look like:

# SECURE
options = Nokogiri::XML::ParseOptions::NONET
Nokogiri::XML(xml_string, nil, nil, options)

Gemfile Analysis: Check your Gemfile for XML processing gems that might be vulnerable. Common problematic gems include:

gem 'nokogiri'
gem 'feedjira'
gem 'libxml-ruby'

middleBrick Scanning: The middleBrick API security scanner can detect XXE vulnerabilities in Rails applications by submitting crafted XML payloads to your endpoints and analyzing the responses. It tests for:

  • XML entity expansion
  • External entity resolution
  • SSRF via XML external entities
  • Denial of service through entity expansion

To scan a Rails API with middleBrick:

# Using the CLI
middlebrick scan https://yourapp.com/api/v1/feed

# Or via GitHub Action
- uses: middlebrick/middlebrick-action@v1
  with:
    url: 'https://yourapp.com/api/v1/feed'
    fail-on-severity: high

Runtime Testing: You can manually test for XXE by crafting payloads and submitting them to your Rails endpoints. A simple test payload:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test [
  <!ENTITY xxe SYSTEM "http://ifconfig.me" >
]>
<test>&xxe;</test>

If your Rails application returns the external content, it's vulnerable to XXE.

Rails-Specific Remediation

Remediating XXE vulnerabilities in Rails applications involves configuring XML parsers properly and implementing safe parsing practices. Here are Rails-specific solutions:

Nokogiri Configuration: The most common XML parser in Rails is Nokogiri. Configure it securely:

class SecureXmlParser
  def self.parse(xml_string)
    options = Nokogiri::XML::ParseOptions::NONET |
             Nokogiri::XML::ParseOptions::NOENT |
             Nokogiri::XML::ParseOptions::DTDLOAD
    
    doc = Nokogiri::XML(xml_string, nil, nil, options)
    raise "Invalid XML" unless doc
    doc
  end
end

# Usage in your controller
class Api::V1::FeedController < ApplicationController
  def create
    xml = params.require(:xml)
    feed = SecureXmlParser.parse(xml)
    render json: { title: feed.title, entries: feed.entries }
  rescue
    render json: { error: "Invalid or malformed XML" }, status: :bad_request
  end
end

The key options here are:

  • NONET: Prevents network access during parsing
  • NOENT: Disables entity expansion
  • DTDLOAD: Prevents loading of external DTDs

Feedjira Security: If you're using Feedjira for RSS/Atom parsing, configure it securely:

Feedjira.configure do |config|
  config.on_parse_failure = :ignore
  config.on_content_failure = :ignore
end

# Use with safe parsing
feed = Feedjira::Feed.parse(xml, parser: :nokogiri, parser_options: Nokogiri::XML::ParseOptions::NONET)

ActiveSupport XML Parsing: Rails's ActiveSupport includes XML parsing utilities. Use them securely:

class SecureXmlService
  def self.parse(xml_string)
    options = { unsupported_attribute: nil, entity_expansion: false }
    ActiveSupport::XMLConverter.new(xml_string, options).convert
  end
end

Middleware Approach: Implement a Rails middleware to sanitize XML requests:

class XxeProtectionMiddleware
  def initialize(app)
    @app = app
  end

  def call(env)
    if xml_request?(env)
      xml = env['rack.input'].read
      if contains_xxe?(xml)
        return [400, { 'Content-Type' => 'application/json' }, [{ error: 'Malicious XML detected' }.to_json]]
      end
      env['rack.input'] = StringIO.new(xml)
    end
    @app.call(env)
  end

  private

  def xml_request?(env)
    env['CONTENT_TYPE'] == 'application/xml' ||
      env['PATH_INFO'] =~ %r{/api.*xml}
  end

  def contains_xxe?(xml)
    xml.include?('<!DOCTYPE') || xml.include?('

Gem Pinning: Pin your XML processing gems to versions that have XXE fixes:

gem 'nokogiri', '~> 1.13.0'
# 1.13.0 and above have improved XXE protections

Testing Your Fix: After implementing these changes, use middleBrick to verify your remediation:

middlebrick scan https://yourapp.com/api/v1/feed --test-suite=xxe

This will specifically test for XXE vulnerabilities and provide a security score for your XML processing endpoints.

Frequently Asked Questions

Does Rails have built-in protection against XXE vulnerabilities?

No, Rails does not have built-in XXE protection. The framework's XML parsing libraries (like Nokogiri) allow external entity processing by default for backward compatibility. Developers must explicitly configure secure parsing options when handling XML data in Rails applications.

Can XXE vulnerabilities in Rails lead to remote code execution?

Directly, XXE typically doesn't lead to remote code execution, but it can be a stepping stone. Through XXE, an attacker might read sensitive files, access internal services, or cause denial of service. In some configurations, XXE combined with other vulnerabilities could potentially lead to RCE, making it critical to properly secure XML parsing in Rails applications.