Category Archives: FreeBSD

automated patching against SQL Injection Vulnerability in Ruby on Rails (CVE-2012-5664)

Suppose you have a server with multiple rubies, rvms, gemsets, etc…

Manually finding and patching all affected activerecord-gems would be pretty cumbersome.

The following script does the job for you:


#!/usr/bin/env ruby

SEARCH_DIR = "/" # by default search the entire filesystem
ACTIVERECORD_GEM_VERSIONS = ['2.3','3.0','3.1','3.2']
PATCHES = {
'2.3' => 'https://bugzilla.redhat.com/attachment.cgi?id=672189',
'3.0' => 'https://bugzilla.redhat.com/attachment.cgi?id=672190',
'3.1' => 'https://bugzilla.redhat.com/attachment.cgi?id=672191',
'3.2' => 'https://bugzilla.redhat.com/attachment.cgi?id=672192',
}

#1. Find all activerecord 2.3.x, 3.0.x, 3.1.x, 3.2.x gems on this machine
gem_paths = {}
puts "Searching for activerecord gems inside #{SEARCH_DIR} ... "
ACTIVERECORD_GEM_VERSIONS.each do |version|
gem_paths[version] = `find #{SEARCH_DIR} -path '*/gems/activerecord*' -name 'activerecord-#{version}.*' -type d`.split("\n")
puts "Found the following activerecord gems for version #{version}:"
puts gem_paths[version]
end

#2. Download the 4 patches here
puts "Downloading the patches ... "
ACTIVERECORD_GEM_VERSIONS.each do |version|
`wget -O patch-#{version}.patch --no-check-certificate #{PATCHES[version]}`
end
puts " ... done"

#3. Apply the patches
ACTIVERECORD_GEM_VERSIONS.each do |version|
gem_paths[version].each do |gem|
puts "--------------------------\nApplying patch for gem #{gem}"
puts `cd '#{gem}'; patch -tN -p2 < '#{File.expand_path(File.dirname(__FILE__))+"/patch-"+version+".patch"}'` end end

This script searches for affected activerecord gems, downloads the required patches and applies them individually.

You might need to run it as root, and it could take a while searching your entire filesystem...
If you know where all your gems are located change the
SEARCH_DIR = "/yougemrepository"

Tested on linux, freebsd

SSL certs from STARTSSL – for nginx

Follow all necessary stept until Startssl gives you the ssl.key

openssl rsa -in ssl.key -out ssl.key

Follow further stepts until Startssl gives you the ssl.crt
Download StartSSL’s root CA and class 1 intermediate server CA certificates:
http://www.startssl.com/certs/ca.pem
http://www.startssl.com/certs/sub.class1.server.ca.pem

Now create a unified certificate:

cat ssl.crt sub.class1.server.ca.pem ca.pem > ssl-unified.crt

Upload the files ssl.key and ssl-unified.crt to the server
Do not forget to chmod 600 ssl.key
In your nginx ssl vhost include:

ssl on;
ssl_certificate /path/to/ssl-unified.crt;
ssl_certificate_key /path/to/ssl.key;

monitor file and send alert mail on change/modify

For some reasons it can be very useful to be alerted on some specific file changes (for instance a database error log).

Using inotify-tools I wrote a script that can monitor a file sending alerts to an email address if that file is changed:


#!/bin/sh
#
# Monitor file $1 for changes
# Send an alert emai to $2 if file $1 changes
# usage: file_change_mail_alert.sh /var/log/messages your.name@domain.com
#

if [ -z "$2" ]; then
echo "Usage: file_change_mail_alert.sh "
exit 1
fi

#if a inotifywait for this file is already running
if [ $(ps aux | grep inotifywait | grep -c "$1" ) -gt '0' ]; then
echo "A process monitoring the file $1 is already running: $(ps aux | grep inotifywait | grep "$1" )";
exit 1;
fi

#if inotifywait exists
type -P inotifywait &>/dev/null || { echo "Error: This script requires inotifywait(http://wiki.github.com/rvoicilas/inotify-tools/) .... apt-get install inotify-tools ... " >&2; exit 1; }

#if the file exists
if [ -f $1 ]; then

echo "Monitoring file $1 for changes - sending alerts to $2"

while inotifywait -e modify $1; do
sleep 1
changes="$(tail -n5 $1)"
echo "The following change occured in the file $1 : $changes" | mail -s "Change in $1" $2
done
else
echo "Error: File $1 not found"
fi

This script can be started on server startup like this:
/path/to/file_change_mail_alert.sh /var/log/something.log your.email@domain.ro

Or put in in the crontab – once a day (it will exit if it detects that another instance of “itself” is already running)
0 6 * * * /path/to/file_change_mail_alert.sh /var/log/something.log your.email@domain.ro

unicorn start/stop and monitoring script

Today I wanted to write a script which could be used to start/stop/restart unicorn for a given application – without root privileges, to get a status and a special action(monitor) which can be called periodically and will restart unicorn automatically in case something went wrong

I found this very usefull blogpost on the net http://rubynyc.wordpress.com/2009/12/24/unicorn-scriptspin/ and modified the script with 2 additional “methods”: status and monitor. (I know … the code I added is pretty primitive… but it works)


#!/usr/local/bin/ruby

UNICORN_RAILS='/usr/local/bin/unicorn_rails'
APP_PATH="#{ARGV[0]}"

class Runner
class << self def start system "cd #{APP_PATH}; #{UNICORN_RAILS} -c ./config/unicorn.rb -E production -D" end def reload system "kill -s USR2 #{pid}" end def restart stop start end def graceful_stop system "kill -s QUIT #{pid}" end def stop system "kill #{pid}" end def pid File.read "#{APP_PATH}/tmp/pids/unicorn.pid" end def status begin system "ps -o user,pid,ppid,command -ax | grep #{pid}" rescue puts 'not started' end end #start if killed def monitor begin #this throws an exception in 2 cases: #1. if no unicorn-process for the current user exists #2. if the pid functions fails(throws an error) due to non-existant unicorn.pid-file throw 'processes killed manually' if (`ps -o user,pid,ppid,command -ax | grep #{pid}`).split("\n").size <= 2 rescue puts 'restarting ... ' start end end end end case ARGV[1] when "start" Runner.start when "reload" Runner.reload when "restart" Runner.restart when "stop" Runner.stop when "status" Runner.status when "monitor" Runner.monitor else STDERR.puts "usage ./unicorn_script.rb absolute_path_to_RAILS_ROOT [start|stop|restart|status|monitor]" exit(1) end

This script can be called from a cron every minute like this


* * * * * /path/to/this_script /path/to/rails_root/ monitor

It baiscally checks if the unicorn-processes exist(the master process and his spawned kids). If it does not detect at least one unicorn-process it will calls the start routine.