Rails 3.0.x security vulnerability (via Mail 2.2.14)

Got rather a nasty surprise this morning when I woke up and read this:

There is a vulnerability in the sendmail delivery agent of the Mail gem that could allow an attacker to pass arbitrary commands to the system.

Arbitrary commands; not nice.

Looking at the patch got me even more worried, particularly this bit:

diff --git a/lib/mail/network/delivery_methods/sendmail.rb b/lib/mail/network/delivery_methods/sendmail.rb
index 6ae419a..29f1876 100644
--- a/lib/mail/network/delivery_methods/sendmail.rb
+++ b/lib/mail/network/delivery_methods/sendmail.rb
@@ -45,11 +45,11 @@ module Mail

     def deliver!(mail)
       envelope_from = mail.return_path || mail.sender || mail.from_addrs.first
-      return_path = "-f \"#{envelope_from}\"" if envelope_from
+      return_path = "-f \"#{envelope_from.to_s.shellescape}\"" if envelope_from

       arguments = [settings[:arguments], return_path].compact.join(" ")

-      Sendmail.call(settings[:location], arguments, mail.destinations.join(" "), mail)
+      Sendmail.call(settings[:location], arguments, mail.destinations.collect(&:shellescape).join(" "), mail)
     end

     def Sendmail.call(path, arguments, destinations, mail)

So you can see there how the envelope_from address is passed through directly to the shell. You can imagine scenarios in which a return path of ; rm -rf / would yield a shell command like sendmail -f ; rm -rf /.

If you are running your app as a non-privileged user, and you should be, this obviously won’t wipe out your entire system, but it can still do an annoying amount of damage. There are plenty of other malicious uses to which this kind of security hole can be put, some of them which can lead to total server compromise.

At least in my Rails app the envelope_from is not really a concern, as it is controlled by me, and always the same. But notice that the other arguments, specifically the destinations, are also passed through without escaping.

Luckily, most applications will have some validation in place that ensures that only email address of the form user@example.com get into the database, and prevents email addresses with malicious substrings like "; rm -rf /" from getting into the system. In general here a more restrictive validation will provide more protection, at the expense of rejecting some addresses that are technically valid according to RFC 2822.

So I think my app wasn’t vulnerable, despite the scary possibility of arbitrary shell command execution, but I immediately deployed a quick update using the new Mail 2.2.15 gem, just in case.