Skip to content

Instantly share code, notes, and snippets.

@claudijd
Created June 18, 2015 12:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save claudijd/3763faa17b83b614cb00 to your computer and use it in GitHub Desktop.
Save claudijd/3763faa17b83b614cb00 to your computer and use it in GitHub Desktop.
I way to manually update RubyGems without susceptibility to CVE-2015-3900
require 'digest'
require 'net/http'
gem_file = 'rubygems-update-2.4.8.gem'
# Reference: https://rubygems.org/gems/rubygems-update/versions/2.4.8
sha256hash = "dbed858db605923d9cc77080de1a5f1ce6ac3c68924877c78665e0d85d7b3e73"
##################################################
# Download the Gem from RubyGems.org (over HTTPS)
##################################################
puts "Downloading #{gem_file}"
if File.exists?(gem_file)
File.unlink(gem_file)
end
puts `wget https://rubygems.org/downloads/#{gem_file}`
if File.exists?(gem_file)
puts "Successfully Downloaded #{gem_file}"
else
puts "Failed to Download #{gem_file}"
puts "Aborting..."
exit
end
##################################################
# Verify the Gem against the SHA265 Hash from RubyGems.org
##################################################
puts "Verifying File against SHA256 hash"
if Digest::SHA256.hexdigest(File.read(gem_file)) == sha256hash
puts "#{gem_file} is Verified"
else
puts "#{gem_file} is Not Verified"
puts "Aborting..."
exit
end
##################################################
# Install the gem manually from downloaded file
##################################################
puts `gem install #{gem_file}`
@bf4
Copy link

bf4 commented Jun 18, 2015

looks like I need to update https://github.com/bf4/gem-checksum to use sha256. (I wrote this before rubygems.org add checksums to all the gems)

@bf4
Copy link

bf4 commented Jun 18, 2015

Is wget not subject to the same SRV attack as rubygems? If not, the checksum verification is really above and beyond, no?

@bf4
Copy link

bf4 commented Jun 18, 2015

Also, maybe add?

\curl -sSL https://gist.github.com/claudijd/3763faa17b83b614cb00/download | \
  tar xzvf - --include 'update.rb' -O | ruby

@claudijd
Copy link
Author

@bf4 I'm moving today, so I whipped this up for @HAZULA in a pinch between boxes. To your comments...

1.) RE: gem-checksum (cool, go for it)
2.) "SRV attack" is specific to DNS and RubyGems' verification of the response, wget is not susceptible to such attacks, unless you turn off SSL/TLS verification. In which case, an attacker can MiTM the HTTPS transaction. Yes, the checksum verification is above and beyond, but another verification step.
3.) wrapping it all together in a one-liners, sure, go for it. Use as you wish, merely trying to show there is a "safe" way to get the update other than the approved mechanism.

Back to moving for me! Thanks for the comments, much appreciated!

@claudijd
Copy link
Author

Ha, just realized @bf4 is also @HAZULA. Have a good day man, gotta run!

@bf4
Copy link

bf4 commented Jun 18, 2015

heh, that's me :)

@bf4
Copy link

bf4 commented Jun 18, 2015

stupiding it up with bash

#!/usr/bin/env bash

echo "\n"
which ruby &> /dev/null
if [ $? -eq 0 ]; then
  echo "Using $(ruby -e 'puts RUBY_DESCRIPTION')\n"
else
  echo "No Ruby found"
  echo "Aborting..."
  exit 1
fi

set -e
version=${VERSION:-2.4.8}
# sha256hash reference: https://rubygems.org/gems/rubygems-update/versions/2.4.8
checksum=${CHECKSUM:-dbed858db605923d9cc77080de1a5f1ce6ac3c68924877c78665e0d85d7b3e73}
gem_name="rubygems-update-${version}.gem"
# USING CDN url, redirected from https://api.rubygems.org/gems/rubygems-update-2.4.8.gem
# see \curl -sSLI https://api.rubygems.org/gems/rubygems-update-2.4.8.gem
url="https://rubygems.global.ssl.fastly.net/gems/${gem_name}"
rm -f "${gem_name}*"
\curl -sSL $url -o $gem_name

if [ $? -eq 0 ]; then
  echo "Successfully Downloaded ${gem_name}\n"
else
  echo "Failed to Download ${gem_name}"
  echo "Aborting...\n"
  exit 2
fi

sha256hash=$(cat $gem_name | openssl dgst -sha256)
if [ "$checksum" = "$sha256hash" ]; then
  echo "${gem_name} is Verified\n"
else
  echo "${gem_name} is Not Verified"
  echo "Aborting...\n"
  exit 3
fi

echo "installing..\n"
gem install ${gem_name}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment