Class: Scryer::Rules::InsecureCookieSerializerRule

Inherits:
Scryer::Rule
  • Object
show all
Defined in:
lib/scryer/rules/insecure_cookie_serializer_rule.rb

Overview

Flags config.action_dispatch.cookies_serializer = :marshal. Rails defaults to :json since Rails 4.1 specifically because deserializing a Marshal-encoded cookie can be turned into remote code execution if the cookie's secret is ever compromised (the same class of bug UnsafeDeserializationRule flags for Marshal.load directly) — only an explicit opt back into :marshal is flagged, never the (safe) default of not setting this at all.

Instance Attribute Summary

Attributes inherited from Scryer::Rule

#file, #sexp, #source

Instance Method Summary collapse

Methods inherited from Scryer::Rule

inherited, #initialize

Constructor Details

This class inherits a constructor from Scryer::Rule

Instance Method Details

#scanObject



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/scryer/rules/insecure_cookie_serializer_rule.rb', line 16

def scan
  findings = []

  Ast.each_node(sexp) do |node|
    next unless Ast.tagged?(node, :assign)

    target = node[1]
    next unless Ast.tagged?(target, :field)
    next unless Ast.ident_text(target[3]) == "cookies_serializer"
    next unless Ast.literal_text(node[2]) == "marshal"

    line = Ast.line_of(node)
    findings << finding(
      line: line,
      message: "`cookies_serializer = :marshal` deserializes every cookie with " \
                "`Marshal.load` — if the app's `secret_key_base` is ever leaked (or brute " \
                "forced), a forged cookie deserialized this way can lead to remote code " \
                "execution, not just a spoofed session.",
      suggested_fix: "Use the default `:json` serializer instead (remove this line, or set " \
                      "`config.action_dispatch.cookies_serializer = :json` explicitly) — it " \
                      "can only produce plain data structures, never arbitrary objects."
    )
  end

  findings
end