guest@websec ~ % man 14-deserialization-and-xxe
14 · Deserialization and XXE
Some data formats can rebuild any object, read files, or balloon to gigabytes. Parse them from strangers and the input decides what your server does.
14.1 Insecure deserialization
JSON only rebuilds plain data. Ruby's Marshal and YAML with object tags can rebuild any class.
So the attacker picks which objects get built. Chain a few ordinary classes together and you get code execution from one request.
Rails got hit by this in 2013: one POST could take over any Rails app on the internet.
YAML.unsafe_load
YAML.load (Psych 4+, Ruby 3.1+)
JSON.parse
Defenses:
- Use JSON for anything from outside.
- Need YAML from users?
YAML.safe_load. - Never
Marshal.loaduntrusted bytes.
Modern Rails is safe by default: JSON cookies, no XML params, safe YAML. Check older apps for a
:marshal cookie serializer and any Marshal.load.# safe by default on Ruby 3.1+ (Psych 4) YAML.load(user_yaml) # plain types only YAML.safe_load(user_yaml, permitted_classes: [Date, Symbol]) JSON.parse(user_json) YAML.unsafe_load(user_yaml) # arbitrary objects Marshal.load(Base64.decode64(params[:state])) # RCE # config/initializers/cookies_serializer.rb (older apps: check this!) Rails.application.config.action_dispatch.cookies_serializer = :json
// JS: JSON.parse is data-only. Danger comes from libraries that revive objects JSON.parse(body); // plain data require("node-serialize").unserialize(body); // has executed functions (CVE-2017-5941) yaml.load(text) // js-yaml 3.x: can build functions (4.x is safe)
14.2 XML External Entities (XXE)
XML can point to external files. A careless parser will read /etc/passwd and hand it back, or expand a 1 KB file into gigabytes.
XML hides in SAML, RSS, SVG and Office files.
Nokogiri is safe by default. Just never pass
noent or dtdload.doc = Nokogiri::XML(upload.read) # safe defaults doc = Nokogiri::XML(upload.read) { |c| c.strict.nonet } Nokogiri::XML(xml) { |c| c.noent.dtdload } # enables XXE Nokogiri::XML(xml, nil, nil, Nokogiri::XML::ParseOptions::NOENT)