YAML is the new eval

               09.02.2013 @rug_b



                   @plexus
        github/arnebrasseur
You




Need to think about security
I'm a Rails developer
I'm a Rails developer

I'm not a security expert
I'm a Rails developer

I'm not a security expert
That's the point
“You Should Be At
Defcon 2 For Most
  Of February”
  http://bit.ly/you_will_be_compromised
§
“Security”
Many aspects
confidentiality, integrity,
availability, authenticity
gem “security” ?
Emergent Property
It's not a feature
Infinity Maxim
Limitless vulnerabilities, most
unknown
Trade off
No such thing as 100% secure
Ignorance is bliss
If you believe you're safe,
You can assume you're not.
Attack Surface
Your outer shell
Least Authority
Can't break what you can't reach
Constrained code
Positive security
Whitelist vs Blacklist
§
Rails Security
"secure by default"
XSS, CSRF, sql escaping, etc.
Tasty Magic
Programmer happiness
“People who use magic without knowing
what they are doing usually come to a sticky end.
     All over the entire room, sometimes.”
                ~ Terry Pratchett
§
  What
happened?
4 x Rails Vulnerability
Rubygems Hacked
Bonus : MySQL “feature”
Jan 2
CVE-2012-5664
SQL Injection Vulnerability
Post.find_by_id(id, opts = {})
Plain Old Dynamic Finder




                                                Jan 2
                                       CVE-2012-5664
                           SQL Injection Vulnerability
Post.find_by_id(:select => sql)
I Can Haz Inject SQL?




                                             Jan 2
                                    CVE-2012-5664
                        SQL Injection Vulnerability
Post.find_by_id(params[:id])
I Can Haz Inject SQL?




                                             Jan 2
                                    CVE-2012-5664
                        SQL Injection Vulnerability
HashWithIndifferentAccess



Post.find_by_id(params[:id])
I Can Haz Inject SQL?




                                             Jan 2
                                    CVE-2012-5664
                        SQL Injection Vulnerability
Exploitable?
Probably, but not trivially



                                                   Jan 2
                                          CVE-2012-5664
                              SQL Injection Vulnerability
AuthLogic
User.find_by_persistence_token(token)



                                               Jan 2
                                      CVE-2012-5664
                          SQL Injection Vulnerability
CookieStore
session[:token] = {:select => “foo; DROP TABLE… ; --”}



                                               Jan 2
                                      CVE-2012-5664
                          SQL Injection Vulnerability
config.session.key
Do you know where your session key is
at 4 o'clock in the morning?


                                                Jan 2
                                       CVE-2012-5664
                           SQL Injection Vulnerability
Jan 8
CVE-2013-0155
Unsafe Query Generation
Foo.find_by_bar( [ nil ] )




JSON or XML payload


Result



                                               Jan 8
                                       CVE-2013-0155
                             Unsafe Query Generation
Jan 8
          CVE-2013-0155
Unsafe Query Generation
Jan 14
CVE-2013-0156
XML will deserialize YAML
THE BIG ONE
Who thought YAML in XML was a good idea anyway?



                                            Jan 14
                                    CVE-2013-0156
                        XML will deserialize YAML
Never trust YAML
!ruby/hash:I::Am::In::Your::Objects
!ruby/object:Setting::Your::Ivars


                                                Jan 14
                                        CVE-2013-0156
                            XML will deserialize YAML
!ruby/hash
Calls #[]=

                                 Jan 14
                         CVE-2013-0156
             XML will deserialize YAML
!ruby/object
Calls instance_variable_set

                                     Jan 14
                             CVE-2013-0156
                 XML will deserialize YAML
ActionController::Routing::
RouteSet::NamedRouteCollection
def add(name, route)
  define_named_route_methods(name, route)
end
alias []= add


def define_url_helper(route, name, kind, options)
  @module.module_eval <<-END
      def #{name}_#{kind}(*args)
                                                               Jan 14
        options = hash_for_#{name}_#{kind}(args.extract_options!)

                                                       CVE-2013-0156
                                           XML will deserialize YAML
EVAL ALL THE THINGS
$ rails new myapp ; cd myapp ; bundle install
$ cd `rvm gemdir`/gems
$ egrep -r '(module_eval|instance_eval|class_eval)' . | wc -l
321
$ egrep -r '(module_eval|instance_eval|class_eval)' . | sed 's//.*//' | uniq -c | sort -n
   62 activesupport-3.2.11
   50 erubis-2.7.0
   38 actionpack-3.2.11
   24 activerecord-3.2.11
   19 railties-3.2.11


                                                                   Jan 14
                                                           CVE-2013-0156
                                               XML will deserialize YAML
Jan 28
CVE-2013-0333
Vulnerability in JSON Parser
in Ruby on Rails 3.0 and 2.3
Only 3.0 and 2.3

                         Jan 28
                  CVE-2013-0333
           JSON parsed as YAML
JSON is YAML
True story

                           Jan 28
                    CVE-2013-0333
             JSON parsed as YAML
Jan 30
Rubygems Hacked
Gemspecs are … YAML
Jan 14
            CVE-2013-0156
XML will deserialize YAML
Feb 7
Bonus Level
SELECT 0 = “foo”; # => true
§
Practical
Are you up-to-date?
Rails 3.2 / 3.1 get security updates
Rails 2.3 for severe security issues
Ruby 1.8 is End of Life June 2013
What now?

Sign up to the security mailing list
What now?

Read the Rails Guide on Security
GET routes don't check CSRF token
match 'user/reset/:id' => 'user#reset', :via => :put
attr_accessible
even better : strong_parameters
params.require(:person).permit(:name, :age)
params.permit(:name, { :emails => [ ] }
Careful with to_json in templates
<script>
 Accounts.reset(<%= raw @accounts.to_json %>);
</script>
Careful with to_json in templates
<script>
Accounts.reset([{name: "</script><script>alert('xss')</script>", ...}]);

</script>
Escaped by default in Rails 4
ActiveSupport::JSON::Encoding.escape_html_entities_in_json = true


There are other solutions as well
●   json_escape
●   data-* attributes
Regexp Anchors
“some@email.comn'; I AM IN YOUR SQLZ ; --” =~ /^...$/
Use A and z
$ : beginning of line
^ : end of line
A : beginning of string
z : end of string
Z : ignores final newline
SafeYAML
Will probably become part of Psych
Brakeman
Static security analysis for Rails apps
Sanitize Your Inputs
Distrust params, cookies and request
Thank you!




 Twitter : @plexus
Github : arnebrasseur

YAML is the new Eval