CVE-2012-2139 (published 2012-07-18T18:55Z)

Directory traversal vulnerability in lib/mail/network/delivery_methods/file_delivery.rb in the Mail gem before 2.4.4 for Ruby allows remote attackers to read arbitrary files via a .. (dot dot) in the to parameter.

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:P/I:N/A:N)

Weakness information:
cwe_id: CWE-22
cwe_name: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
description: The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
extended_description: 
            Many file operations are intended to take place within a restricted directory. By using special elements such as ".." and "/" separators, attackers can escape outside of the restricted location to access files or directories that are elsewhere on the system. One of the most common special elements is the "../" sequence, which in most modern operating systems is interpreted as the parent directory of the current location. This is referred to as relative path traversal. Path traversal also covers the use of absolute pathnames such as "/usr/local/bin" to access unexpected files. This is referred to as absolute path traversal.
         
         

Fix information:
repo_url: https://github.com/mikel/mail
commit_details: repo_url: https://github.com/mikel/mail
author: Mikel Lindsaar
author_date: 2012-03-14 22:44:27+11:00
msg: Preventing file system traversal in file_delivery method
repository: repo_url: https://github.com/mikel/mail
repo_name: mikel/mail
description: A Really Ruby Mail Library
repo_language: Ruby
owner: mikel
file_changes: filename: file_delivery.rb
change_type: ModificationType.MODIFY
diff: @@ -6,7 +6,7 @@ module Mail
   # So if you have an email going to fred@test, bob@test, joe@anothertest, and you
   # set your location path to /path/to/mails then FileDelivery will create the directory
   # if it does not exist, and put one copy of the email in three files, called
-  # "fred@test", "bob@test" and "joe@anothertest"
+  # by their message id
   # 
   # Make sure the path you specify with :location is writable by the Ruby process
   # running Mail.
@@ -32,7 +32,7 @@ module Mail
       end
 
       mail.destinations.uniq.each do |to|
-        ::File.open(::File.join(settings[:location], to), 'a') { |f| "#{f.write(mail.encoded)}\r\n\r\n" }
+        ::File.open(::File.join(settings[:location], File.basename(to.to_s)), 'a') { |f| "#{f.write(mail.encoded)}\r\n\r\n" }
       end
     end
     

programming_language: Ruby
filename: file_delivery_spec.rb
change_type: ModificationType.MODIFY
diff: @@ -74,6 +74,21 @@ describe "SMTP Delivery Method" do
       File.exists?(delivery).should be_true
     end
 
+    it "should use the base name of the file name to prevent file system traversal" do
+      Mail.defaults do
+        delivery_method :file, :location => tmpdir
+      end
+      
+      Mail.deliver do
+        from    'roger@moore.com'
+        to      '../../../../../../../../../../../tmp/pwn'
+        subject 'evil hacker'
+      end
+
+      delivery = File.join(Mail.delivery_method.settings[:location], 'pwn')
+      File.exists?(delivery).should be_true
+    end
+
   end
   
 end

programming_language: Ruby