CVE-2015-9096 (published 2017-06-12T20:29Z)

Net::SMTP in Ruby before 2.4.0 is vulnerable to SMTP command injection via CRLF sequences in a RCPT TO or MAIL FROM command, as demonstrated by CRLF sequences immediately before and after a DATA substring.

Severity: MEDIUM
CVSS v2 base score: 4.3 (AV:N/AC:M/Au:N/C:N/I:P/A:N)
CVSS v3 base score: 6.1, MEDIUM (CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N)

Weakness information:
cwe_id: CWE-93
cwe_name: Improper Neutralization of CRLF Sequences ('CRLF Injection')
description: The product uses CRLF (carriage return line feeds) as a special element, e.g. to separate lines or records, but it does not neutralize or incorrectly neutralizes CRLF sequences from inputs.
extended_description: 
            
            
         
         

Fix information:
repo_url: https://github.com/ruby/ruby
commit_details: repo_url: https://github.com/ruby/ruby
author: shugo
author_date: 2016-06-08 07:06:57+00:00
msg: * lib/net/smtp.rb (getok, get_response): raise an ArgumentError when
CR or LF is included in a line, because they are not allowed in
RFC5321.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55324 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
repository: repo_url: https://github.com/ruby/ruby
repo_name: ruby/ruby
description: The Ruby Programming Language
repo_language: Ruby
owner: ruby
file_changes: filename: ChangeLog
change_type: ModificationType.MODIFY
diff: @@ -1,3 +1,9 @@
+Wed Jun  8 16:03:09 2016  Shugo Maeda  <shugo@ruby-lang.org>
+
+	* lib/net/smtp.rb (getok, get_response): raise an ArgumentError when
+	  CR or LF is included in a line, because they are not allowed in
+	  RFC5321.
+
 Tue Jun  7 21:27:25 2016  Kazuki Yamaguchi  <k@rhe.jp>
 
 	* test/rubygems/*_{cert,cert_32}.pem: Regenerate test certificates for

programming_language: Markdown
filename: smtp.rb
change_type: ModificationType.MODIFY
diff: @@ -926,7 +926,15 @@ def quit
 
     private
 
+    def validate_line(line)
+      # A bare CR or LF is not allowed in RFC5321.
+      if /[\r\n]/ =~ line
+        raise ArgumentError, "A line must not contain CR or LF"
+      end
+    end
+
     def getok(reqline)
+      validate_line reqline
       res = critical {
         @socket.writeline reqline
         recv_response()
@@ -936,6 +944,7 @@ def getok(reqline)
     end
 
     def get_response(reqline)
+      validate_line reqline
       @socket.writeline reqline
       recv_response()
     end

programming_language: Ruby
filename: test_smtp.rb
change_type: ModificationType.MODIFY
diff: @@ -6,6 +6,8 @@
 module Net
   class TestSMTP < Test::Unit::TestCase
     class FakeSocket
+      attr_reader :write_io
+
       def initialize out = "250 OK\n"
         @write_io = StringIO.new
         @read_io  = StringIO.new out
@@ -51,5 +53,50 @@ def test_rset
 
       assert smtp.rset
     end
+
+    def test_mailfrom
+      sock = FakeSocket.new
+      smtp = Net::SMTP.new 'localhost', 25
+      smtp.instance_variable_set :@socket, sock
+      assert smtp.mailfrom("foo@example.com").success?
+      assert_equal "MAIL FROM:<foo@example.com>\r\n", sock.write_io.string
+    end
+
+    def test_rcptto
+      sock = FakeSocket.new
+      smtp = Net::SMTP.new 'localhost', 25
+      smtp.instance_variable_set :@socket, sock
+      assert smtp.rcptto("foo@example.com").success?
+      assert_equal "RCPT TO:<foo@example.com>\r\n", sock.write_io.string
+    end
+
+    def test_auth_plain
+      sock = FakeSocket.new
+      smtp = Net::SMTP.new 'localhost', 25
+      smtp.instance_variable_set :@socket, sock
+      assert smtp.auth_plain("foo", "bar").success?
+      assert_equal "AUTH PLAIN AGZvbwBiYXI=\r\n", sock.write_io.string
+    end
+
+    def test_crlf_injection
+      smtp = Net::SMTP.new 'localhost', 25
+      smtp.instance_variable_set :@socket, FakeSocket.new
+
+      assert_raise(ArgumentError) do
+        smtp.mailfrom("foo\r\nbar")
+      end
+
+      assert_raise(ArgumentError) do
+        smtp.mailfrom("foo\rbar")
+      end
+
+      assert_raise(ArgumentError) do
+        smtp.mailfrom("foo\nbar")
+      end
+
+      assert_raise(ArgumentError) do
+        smtp.rcptto("foo\r\nbar")
+      end
+    end
   end
 end

programming_language: Ruby