[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

mcollective cve-2016-2788



Details of this bug seem to be very scarce. I can't find any information
on how to reproduce, and I can't find git source. I can't even tell if
wheezy is vulnerable or not.

Furthermore this package is very old in all distributions including
unstable.

About the best I can find is this bug is present in 2.8.8 but fixed in
2.8.9. So I did a diff, and only included *.rb files (this filters out a
lot of changes to the documentation files).

My suspicion is that the changes to /lib/mcollective/matcher/scanner.rb might be relevant.

The changes to /lib/mcollective/matcher.rb might also be significant.

diff -ruN mcollective-2.8.8/install.rb mcollective-2.8.9/install.rb
--- mcollective-2.8.8/install.rb	2016-03-12 09:56:24.000000000 +1100
+++ mcollective-2.8.9/install.rb	2016-07-21 03:53:53.000000000 +1000
@@ -110,7 +110,7 @@
 #
 def prepare_installation
   InstallOptions.configs = true
-
+  InstallOptions.batch_files = true
   # Only try to do docs if we're sure they have rdoc
   if $haverdoc
     InstallOptions.rdoc = true
@@ -149,6 +149,9 @@
     opts.on('--plugindir[=OPTIONAL]', 'Installation directory for plugins', 'Default /usr/libexec/mcollective') do |plugindir|
       InstallOptions.plugindir = plugindir
     end
+    opts.on('--no-batch-files', 'Prevents installation of batch files for windows', 'Default off') do |batch_files|
+      InstallOptions.batch_files = false
+    end
     opts.on('--quick', 'Performs a quick installation. Only the', 'installation is done.') do |quick|
       InstallOptions.rdoc    = false
       InstallOptions.ri      = false
@@ -293,6 +296,7 @@
 
 # Change directory into the mcollective root so we don't get the wrong files for install.
 cd File.dirname(__FILE__) do
+  prepare_installation
   # Set these values to what you want installed.
   configs = glob(%w{etc/*.dist})
   erbs = glob(%w{etc/*.erb})
@@ -301,7 +305,8 @@
   rdoc = glob(%w{bin/* lib/**/*.rb README* })
   libs = glob(%w{lib/**/*})
   plugins = glob(%w{plugins/**/*})
-  if WINDOWS
+
+  if WINDOWS && InstallOptions.batch_files
     if InstallOptions.service_files
        windows_bins = glob(%w{ext/windows/*.bat ext/windows/*.rb})
     else
@@ -310,14 +315,12 @@
   end
 
   check_prereqs
-  prepare_installation
-
   build_rdoc(rdoc) if InstallOptions.rdoc
   do_configs(configs, InstallOptions.configdir, 'etc/|\.dist') if InstallOptions.configs
   do_configs(erbs, InstallOptions.configdir) if InstallOptions.configs
   do_bins(bins, InstallOptions.bindir)
   do_bins(sbins, InstallOptions.sbindir)
-  do_bins(windows_bins, InstallOptions.bindir, 'ext/windows/') if WINDOWS
+  do_bins(windows_bins, InstallOptions.bindir, 'ext/windows/') if WINDOWS && InstallOptions.batch_files
   do_libs(libs, InstallOptions.sitelibdir)
   do_libs(plugins, InstallOptions.plugindir, 'plugins/')
 end
diff -ruN mcollective-2.8.8/lib/mcollective/matcher/scanner.rb mcollective-2.8.9/lib/mcollective/matcher/scanner.rb
--- mcollective-2.8.8/lib/mcollective/matcher/scanner.rb	2016-03-12 09:56:24.000000000 +1100
+++ mcollective-2.8.9/lib/mcollective/matcher/scanner.rb	2016-07-21 03:53:53.000000000 +1000
@@ -65,7 +65,6 @@
         current_token_value = ""
         j = @token_index
         escaped = false
-        escaped_with = ""
 
         begin
           if (@arguments[j] == "/")
@@ -117,47 +116,46 @@
                 break
               end
 
-              if @arguments[j+1] == "("
+              if @arguments[j] == "("
                 func = true
-                be_greedy = true
-              end
-
-              if @arguments[j+1] == '"' || @arguments[j+1] == "'"
-                func = false
-                be_greedy = true
-                escaped = true
-                escaped_with = @arguments[j+1]
-              end
 
-              current_token_value << @arguments[j]
+                current_token_value << @arguments[j]
+                j += 1
 
-              if be_greedy
-                if func
-                  while !(j+1 >= @arguments.size) && @arguments[j] != ')'
+                while j < @arguments.size
+                  current_token_value << @arguments[j]
+                  if @arguments[j] == ')'
                     j += 1
-                    current_token_value << @arguments[j]
+                    break
                   end
-                else
-                  j += 2 # step over first "
-                  @white_spaces += 1
-                  # identified "..."
-                  while !(j+1 >= @arguments.size) && @arguments[j] != escaped_with
-                    if  @arguments[j] == '\\'
-                      # eat the escape char but don't add it to the token, or we
-                      # end up with \\\"
-                      @white_spaces += 1
-                      j += 1
-                      escaped = true
+                  j += 1
+                end
+              elsif @arguments[j] == '"' || @arguments[j] == "'"
+                escaped = true
+                escaped_with = @arguments[j]
+
+                j += 1 # step over first " or '
+                @white_spaces += 1
+                # identified "..." or '...'
+                while j < @arguments.size
+                  if  @arguments[j] == '\\'
+                    # eat the escape char but don't add it to the token, or we
+                    # end up with \\\"
+                    j += 1
+                    @white_spaces += 1
+                    unless j < @arguments.size
+                      break
                     end
-                    current_token_value << @arguments[j]
+                  elsif @arguments[j] == escaped_with
                     j += 1
+                    @white_spaces += 1
+                    break
                   end
-                  @white_spaces += 1
+                  current_token_value << @arguments[j]
+                  j += 1
                 end
-
-                j += 1
-                be_greedy = false
               else
+                current_token_value << @arguments[j]
                 j += 1
               end
 
diff -ruN mcollective-2.8.8/lib/mcollective/matcher.rb mcollective-2.8.9/lib/mcollective/matcher.rb
--- mcollective-2.8.8/lib/mcollective/matcher.rb	2016-03-12 09:56:24.000000000 +1100
+++ mcollective-2.8.9/lib/mcollective/matcher.rb	2016-07-21 03:53:53.000000000 +1000
@@ -157,11 +157,6 @@
         return false
       end
 
-      # Escape strings for evaluation
-      if (l_compare.is_a?(String)  && !(function_hash["operator"] =~ /=~|!=~/))
-        r_compare = "\"#{r_compare}\""
-      end
-
       # Do a regex comparison if right compare string is a regex
       if operator=~ /(=~|!=~)/
         # Fail if left compare value isn't a string
@@ -177,10 +172,40 @@
             return !!result
           end
         end
-        # Otherwise evaluate the logical comparison
+        # Otherwise do a normal comparison while taking the type into account
       else
-        l_compare = "\"#{l_compare}\"" if l_compare.is_a?(String)
-        result = eval("#{l_compare} #{operator} #{r_compare}")
+        if l_compare.is_a? String
+          r_compare = r_compare.to_s
+        elsif r_compare.is_a? String
+          if l_compare.is_a? Numeric
+            r_compare = r_compare.strip
+            begin
+              r_compare = Integer(r_compare)
+            rescue ArgumentError
+              begin
+                r_compare = Float(r_compare)
+              rescue ArgumentError
+                raise ArgumentError, "invalid numeric value: #{r_compare}"
+              end
+            end
+          elsif l_compare.is_a? TrueClass or l_compare.is_a? FalseClass
+            r_compare = r_compare.strip
+            if r_compare == true.to_s
+              r_compare = true
+            elsif r_compare == false.to_s
+              r_compare = false
+            else
+              raise ArgumentError, "invalid boolean value: #{r_compare}"
+            end
+          end
+        end
+        operator = operator.strip
+        if operator =~ /(?:(!=|<=|>=|<|>)|==?)/
+          operator = $1 ? $1.to_sym : :==
+        else
+          raise ArgumentError, "invalid operator: #{operator}"
+        end
+        result = l_compare.send(operator, r_compare)
         return result
       end
     end
diff -ruN mcollective-2.8.8/lib/mcollective/ssl.rb mcollective-2.8.9/lib/mcollective/ssl.rb
--- mcollective-2.8.8/lib/mcollective/ssl.rb	2016-03-12 09:56:24.000000000 +1100
+++ mcollective-2.8.9/lib/mcollective/ssl.rb	2016-07-21 03:53:53.000000000 +1000
@@ -218,7 +218,7 @@
     def self.uuid(string=nil)
       string ||= OpenSSL::Random.random_bytes(16).unpack('H*').shift
 
-      uuid_name_space_dns = "\x6b\xa7\xb8\x10\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8"
+      uuid_name_space_dns = [0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8].map {|b| b.chr}.join
 
       sha1 = Digest::SHA1.new
       sha1.update(uuid_name_space_dns)
diff -ruN mcollective-2.8.8/lib/mcollective.rb mcollective-2.8.9/lib/mcollective.rb
--- mcollective-2.8.8/lib/mcollective.rb	2016-03-12 09:56:24.000000000 +1100
+++ mcollective-2.8.9/lib/mcollective.rb	2016-07-21 03:53:53.000000000 +1000
@@ -59,7 +59,7 @@
 
   MCollective::Vendor.load_vendored
 
-  VERSION="2.8.8"
+  VERSION="2.8.9"
 
   def self.version
     VERSION

-- 
Brian May <brian@linuxpenguins.xyz>
https://linuxpenguins.xyz/brian/


Reply to: