1= Ruby Security 2 3The Ruby programming language is large and complex and there are many security 4pitfalls often encountered by newcomers and experienced Rubyists alike. 5 6This document aims to discuss many of these pitfalls and provide more secure 7alternatives where applicable. 8 9Please check the full list of publicly known CVEs and how to correctly report a 10security vulnerability, at: https://www.ruby-lang.org/en/security/ 11Japanese version is here: https://www.ruby-lang.org/ja/security/ 12 13Security vulnerabilities should be reported via an email to 14mailto:security@ruby-lang.org ({the PGP public 15key}[https://www.ruby-lang.org/security.asc]), which is a private mailing list. 16Reported problems will be published after fixes. 17 18== <code>$SAFE</code> 19 20Ruby provides a mechanism to restrict what operations can be performed by Ruby 21code in the form of the <code>$SAFE</code> variable. 22 23However, <code>$SAFE</code> does not provide a secure environment for executing 24untrusted code. 25 26If you need to execute untrusted code, you should use an operating system level 27sandboxing mechanism. On Linux, ptrace or LXC can be used to sandbox 28potentially malicious code. Other similar mechanisms exist on every major 29operating system. 30 31== +Marshal.load+ 32 33Ruby's +Marshal+ module provides methods for serializing and deserializing Ruby 34object trees to and from a binary data format. 35 36Never use +Marshal.load+ to deserialize untrusted or user supplied data. 37Because +Marshal+ can deserialize to almost any Ruby object and has full 38control over instance variables, it is possible to craft a malicious payload 39that executes code shortly after deserialization. 40 41If you need to deserialize untrusted data, you should use JSON as it is only 42capable of returning 'primitive' types such as strings, arrays, hashes, numbers 43and nil. If you need to deserialize other classes, you should handle this 44manually. Never deserialize to a user specified class. 45 46== YAML 47 48YAML is a popular human readable data serialization format used by many Ruby 49programs for configuration and database persistence of Ruby object trees. 50 51Similar to +Marshal+, it is able to deserialize into arbitrary Ruby classes. 52For example, the following YAML data will create an +ERB+ object when 53deserialized: 54 55 !ruby/object:ERB 56 src: puts `uname` 57 58Because of this, many of the security considerations applying to Marshal are 59also applicable to YAML. Do not use YAML to deserialize untrusted data. 60 61== Symbols 62 63Symbols are often seen as syntax sugar for simple strings, but they play a much 64more crucial role. The MRI Ruby implementation uses Symbols internally for 65method, variable and constant names. The reason for this is that symbols are 66simply integers with names attached to them, so they are faster to look up in 67hashtables. 68 69Starting in version 2.2, most symbols can be garbage collected; these are 70called <i>mortal</i> symbols. Most symbols you create (e.g. by calling 71+to_sym+) are mortal. 72 73<i>Immortal</i> symbols on the other hand will never be garbage collected. 74They are created when modifying code: 75* defining a method (e.g. with +define_method+), 76* setting an instance variable (e.g. with +instance_variable_set+), 77* creating a variable or constant (e.g. with +const_set+) 78C extensions that have not been updated and are still calling `SYM2ID` 79will create immortal symbols. 80Bugs in 2.2.0: +send+ and +__send__+ also created immortal symbols, 81and calling methods with keyword arguments could also create some. 82 83Don't create immortal symbols from user inputs. Otherwise, this would 84allow a user to mount a denial of service attack against your application by 85flooding it with unique strings, which will cause memory to grow indefinitely 86until the Ruby process is killed or causes the system to slow to a halt. 87 88While it might not be a good idea to call these with user inputs, methods that 89used to be vulnerable such as +to_sym+, +respond_to?+, 90+method+, +instance_variable_get+, +const_get+, etc. are no longer a threat. 91 92== Regular expressions 93 94Ruby's regular expression syntax has some minor differences when compared to 95other languages. In Ruby, the <code>^</code> and <code>$</code> anchors do not 96refer to the beginning and end of the string, rather the beginning and end of a 97*line*. 98 99This means that if you're using a regular expression like 100<code>/^[a-z]+$/</code> to restrict a string to only letters, an attacker can 101bypass this check by passing a string containing a letter, then a newline, then 102any string of their choosing. 103 104If you want to match the beginning and end of the entire string in Ruby, use 105the anchors +\A+ and +\z+. 106 107== +eval+ 108 109Never pass untrusted or user controlled input to +eval+. 110 111Unless you are implementing a REPL like +irb+ or +pry+, +eval+ is almost 112certainly not what you want. Do not attempt to filter user input before passing 113it to +eval+ - this approach is fraught with danger and will most likely open 114your application up to a serious remote code execution vulnerability. 115 116== +send+ 117 118'Global functions' in Ruby (+puts+, +exit+, etc.) are actually private instance 119methods on +Object+. This means it is possible to invoke these methods with 120+send+, even if the call to +send+ has an explicit receiver. 121 122For example, the following code snippet writes "Hello world" to the terminal: 123 124 1.send(:puts, "Hello world") 125 126You should never call +send+ with user supplied input as the first parameter. 127Doing so can introduce a denial of service vulnerability: 128 129 foo.send(params[:bar]) # params[:bar] is "exit!" 130 131If an attacker can control the first two arguments to +send+, remote code 132execution is possible: 133 134 # params is { :a => "eval", :b => "...ruby code to be executed..." } 135 foo.send(params[:a], params[:b]) 136 137When dispatching a method call based on user input, carefully verify that the 138method name. If possible, check it against a whitelist of safe method names. 139 140Note that the use of +public_send+ is also dangerous, as +send+ itself is 141public: 142 143 1.public_send("send", "eval", "...ruby code to be executed...") 144 145== DRb 146 147As DRb allows remote clients to invoke arbitrary methods, it is not suitable to 148expose to untrusted clients. 149 150When using DRb, try to avoid exposing it over the network if possible. If this 151isn't possible and you need to expose DRb to the world, you *must* configure an 152appropriate security policy with <code>DRb::ACL</code>. 153