Patch your projects vulnerable to Rails XML/YAML security hole

12 Jan 2013

update: Special thanks to Justin and Jeff for fixing up the script. And to Pepijn for reminding me to post more details.

There have been some announcements in the last few weeks about vulnerabilities in Ruby on Rails. It’s mostly just one vulnerability but it is so large and so easy to exploit that you have to patch all your applications. Important: You even need to patch applications sitting on your laptop that are not deployed anywhere.

Code Climate has a good writeup.

If you have Phusion Passenger (or any other webserver) serving a Rails application locally on your computer then a maliciously-crafted IMG tag* anyone running Metasploit can compromise your personal laptop. Yeah, it’s that bad.

*I’m no longer sure an IMG tag is an attack vector. I know GETs are susceptible as well as POSTs but it may need to be an ajax or curled HTTP request rather than a plain browser GET.

Here’s what you need to fix:

locate Gemfile.lock | xargs egrep "^  rails " | cut -d : -f 1 | xargs egrep -L 'rails \(= (2.3.15|3.0.19|3.1.10|3.2.11)\)' | xargs -n 1 dirname

Any project that shows up in the output of that command needs you to hardcode the Rails version in Gemfile to one of the following (whichever is closest to your current version):

2.3.15
3.0.19
3.1.10
3.2.11

Or, if you’re feeling gutsy:

# for the lazy:
# curl https://gist.github.com/raw/4519927/83eca75e98ec9921969a18a1b3dcaebddb44011a/patch-CVE-2013-0156.sh | sh
projects=`locate Gemfile.lock | egrep -v "(.rvm|bundler|.passenger)" | xargs egrep "  rails" | cut -d : -f 1 | uniq | xargs egrep -L 'rails \((2.3.15|3.0.19|3.1.10|3.2.11)\)' |cut -d : -f 1 | xargs -n 1 dirname`
for project in $projects; do
  echo '-----------------'
  echo '-- PATCHING' $project ' -- '
  echo '-----------------'
  cd $project
  git stash
  git checkout master
  git pull
  sed -i .bak "s/gem [\"|']rails[\"|'], [\"|']2.*[\"|']/gem 'rails', '2.3.15'/g" Gemfile
  sed -i .bak "s/gem [\"|']rails[\"|'], [\"|']3.0.*[\"|']/gem 'rails', '3.0.19'/g" Gemfile
  sed -i .bak "s/gem [\"|']rails[\"|'], [\"|']3.1.*[\"|']/gem 'rails', '3.1.10'/g" Gemfile
  sed -i .bak "s/gem [\"|']rails[\"|'], [\"|']3.2.*[\"|']/gem 'rails', '3.2.11'/g" Gemfile
  # Per VULN-75/CVE-2013-0156 Disable YAML and symbol parsing from the rails XML parser
  # incase it is used elsewhere in request processing or backend communications
  if [[ -z `egrep "rails '2.3.15'" Gemfile` ]]; then
    echo "
ActionDispatch::ParamsParser::DEFAULT_PARSERS.delete(Mime::XML)
ActiveSupport::XmlMini::PARSING.delete('symbol')
ActiveSupport::XmlMini::PARSING.delete('yaml')
" > config/initializers/CVE-2013-0156.rb
  else
    echo "
ActionController::Base.param_parsers.delete(Mime::XML)
ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING.delete('symbol')
ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING.delete('yaml')
" > config/initializers/CVE-2013-0156.rb
  fi;
  bundle
  cd -
  say 'patched' $project
done

Please if you found this post helpful or have questions.