Plough => Ruby Journey through ruby

Timing Attack Ruby Vulnerability


layout: post title: Timing attack vulnerability in Rails date_string: 21 February 2016 —

Disclaimer

I am not a security expert and this post is my attempt to learn a bit more about web security.

Why now?

Well, I am signed up to Ruby on Rails security mailing list to make sure vulnerabilities don’t go unnoticed and all my projects are running patched versions. Usually I just read the emails and ensure to upgrade or patch the affected versions and this system has worked very smoothly, however, I have never been happy with this approach and when a timing attack vulnerabilitywas announced on 25th January 2016 (CVE-2015-7576), I decided to research and learn more about it.

What is a timing attack?

A timing attack allows an adversary to learn more about the system under attack by statistically analysing information based on different response times. Here are a few examples:

  1. The size of response for a signed in user and a signed out user will be significantlly different, thus allowing the adversary to determine user’s current state.

  2. A string comparison with no matching characters will be slightly faster than one with 2 matching characters.

There are many more examples along the same lines. One thing worth mentioning is that it takes a lot more analysis and patience for a successful timing attack, but it’s not impossible.

How can we fix the string comparision to run in constant time?

Although, there are several ways to use the timing attack but in the interest of this article the scope is limited to secure string comparison in Ruby. There are two ways to do it:

Activesupport

Activesupport provides a secure_compare method that can be used like this:

ActiveSupport::SecurityUtils.secure_compare(a, b)

Don’t use Activesupport

I took this implementation from Time Trial - Racing Towards Practical Remote Timing Attacks paper and looks similar to activesupport’s implementation.


def secure_compare(a, b)
	return false if a.empty? || b.empty? || a.bytesize != b.bytesize l = a.unpack "C#{a.bytesize}"
	res = 0
	b.each_byte { |byte| res |= byte ^ l.shift } 
	res == 0
end


Why no secure compare in Ruby?

You may ask why does Ruby not have a secure compare as part of the core API? I have no idea, but, there has been movement on that front lately and you can follow that discussion in ruby’s bug discussion area. It’s currently waiting for Matz approval.

Research

I don’t want to repeat the research that has been conducted by others, so here’s a review of things I researched and if you’re interested you should read these to gain more understanding.

Tools

Whilst researching I came across the following tools to test for a timing attack. I’ve not tried them myself but give them a go:

  • https://github.com/dmayer/time_trial
  • https://github.com/ecbftw/nanown
  • https://github.com/aj-code/TimingIntrusionTool5000

Papers/Articles

Books

  • The Tagled Web A Guide to Securing Modern Web Applications
  • The Web Application Hackers Handbook

This research is not comprehensive and I hope its given you enough to carry on this journey by yourself.

Update (17.03.2016)

Good news! Just seen update on the ruby issue and apparently OpenSSL provides a timing safe binary comparison method called CRYPTO_memcmp which is what will be used in ruby internally and exposed from it to be used by other libraries.