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: