Yet another vulnerability Ruby on Rails vulnerability has been patched today.
Official(ish) notification here: Google Groups: Ruby on Rails Security
This time, instead of XML being used to pass raw POST data as an argument to the backend, the problem lies in the JSON (which was originally considered the work around for CVE 2013-0156) parser which transforms JSON into YAML, which is in turn passed through a YAML parser. This leads to a very similar attack, abusing !ruby/hash:ActionController::Routing::RouteSet::NamedRouteCollection, that was previously thought patched in ROR 2.3.x and 3.0.x.
Here's a look at the problem (activesupport/lib/active_support/json/backends/yaml.rb)
The bold part is important. This is what further encodes arbitrary user input into a format that supports serialization and deserialization of arbitrary data types by the Yaml parser. Once again, this includes reserved Symbols and arbitrary objects.However, instead of a combination of XML and Yaml, JSON converted into Yaml is the culprit.
The fix replaces the Yaml backend (activesupport/lib/active_support/json/backends/yaml.rb), which allowed single quoted ('foo') strings, with OkJson (activesupport/lib/active_support/json/backends/okjson.rb). The fixed versions are identified as: 3.0.20 and 2.3.16. Due to the similarity to the previous vulnerabilities earlier this month, this is likely to quickly be utilized in the wild. Expect probes soon.
Update 1: POC here: https://gist.github.com/4660248
Update 2: Sample of Metasploit Module Code, based on the previous XML/YAML Vuln
Official(ish) notification here: Google Groups: Ruby on Rails Security
This time, instead of XML being used to pass raw POST data as an argument to the backend, the problem lies in the JSON (which was originally considered the work around for CVE 2013-0156) parser which transforms JSON into YAML, which is in turn passed through a YAML parser. This leads to a very similar attack, abusing !ruby/hash:ActionController::Routing::RouteSet::NamedRouteCollection, that was previously thought patched in ROR 2.3.x and 3.0.x.
Here's a look at the problem (activesupport/lib/active_support/json/backends/yaml.rb)
# Parses a JSON string or IO and converts it into an object
def decode(json) if json.respond_to?(:read) json = json.read end YAML.load(convert_json_to_yaml(json)) rescue *EXCEPTIONS => e
raise ParseError, "Invalid JSON string: '%s'" % json
The bold part is important. This is what further encodes arbitrary user input into a format that supports serialization and deserialization of arbitrary data types by the Yaml parser. Once again, this includes reserved Symbols and arbitrary objects.However, instead of a combination of XML and Yaml, JSON converted into Yaml is the culprit.
The fix replaces the Yaml backend (activesupport/lib/active_support/json/backends/yaml.rb), which allowed single quoted ('foo') strings, with OkJson (activesupport/lib/active_support/json/backends/okjson.rb). The fixed versions are identified as: 3.0.20 and 2.3.16. Due to the similarity to the previous vulnerabilities earlier this month, this is likely to quickly be utilized in the wild. Expect probes soon.
Update 1: POC here: https://gist.github.com/4660248
encoded_yaml = yaml.gsub(':','\u003a')[Clever!]
Update 2: Sample of Metasploit Module Code, based on the previous XML/YAML Vuln
!ruby/hash\:ActionDispatch\:\:Routing\:\:RouteSet\:\:NamedRouteCollection\n" + "'#{Rex::Text.rand_text_alpha(rand(8)+1)}; " + "eval(%[#{code}].unpack(%[m0])[0]);' " + "\: !ruby/object:OpenStruct\n table\:\n \:defaults\: {}\n" yaml.gsub(':','\u003a')