Skip to content

Commit 038ccf1

Browse files
committed
Land rapid7#14769, Handle nil versions in preparation for rubygems 4
2 parents a1cc6aa + a6461a0 commit 038ccf1

File tree

198 files changed

+553
-500
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

198 files changed

+553
-500
lines changed

lib/metasploit/framework/api/version.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ module Version
1010
end
1111

1212
VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::PATCH}"
13-
GEM_VERSION = Gem::Version.new(VERSION)
13+
GEM_VERSION = Rex::Version.new(VERSION)
1414
end
1515
end
16-
end
16+
end

lib/metasploit/framework/core/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ module Version
1313
end
1414

1515
VERSION = Metasploit::Framework::VERSION
16-
GEM_VERSION = Gem::Version.new(Metasploit::Framework::GEM_VERSION)
16+
GEM_VERSION = Rex::Version.new(Metasploit::Framework::GEM_VERSION)
1717
end
1818
end
1919
end

lib/metasploit/framework/login_scanner/phpmyadmin.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def check_setup
1414

1515
if res && res.body.include?('phpMyAdmin')
1616
if res.body =~ /PMA_VERSION:"(\d+\.\d+\.\d+)"/
17-
version = Gem::Version.new($1)
17+
version = Rex::Version.new($1)
1818
end
1919
return version.to_s
2020
end

lib/msf/core/exploit/remote/http/drupal.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def setup
2323

2424
# Determine Drupal version
2525
#
26-
# @return [Gem::Version] Version as Gem::Version
26+
# @return [Rex::Version] Version as Rex::Version
2727
def drupal_version
2828
res = send_request_cgi(
2929
'method' => 'GET',
@@ -49,12 +49,12 @@ def drupal_version
4949

5050
# Return CHANGELOG.txt
5151
#
52-
# @param version [Gem::Version] Gem::Version or version string
52+
# @param version [Rex::Version] Rex::Version or version string
5353
# @return [String] CHANGELOG.txt as a string
5454
def drupal_changelog(version)
55-
return unless version && Gem::Version.correct?(version)
55+
return unless version && Rex::Version.correct?(version)
5656

57-
uri = Gem::Version.new(version) < Gem::Version.new('8') ?
57+
uri = Rex::Version.new(version) < Rex::Version.new('8') ?
5858
normalize_uri(target_uri.path, 'CHANGELOG.txt') :
5959
normalize_uri(target_uri.path, 'core/CHANGELOG.txt')
6060

@@ -89,16 +89,16 @@ def drupal_patch(changelog, patch)
8989
# Match a Drupal version
9090
#
9191
# @param string [String] String to match against
92-
# @return [Gem::Version] Version as Gem::Version
92+
# @return [Rex::Version] Version as Rex::Version
9393
def version_match(string)
9494
return unless string
9595

9696
# Perl devs love me; Ruby devs hate me
9797
string =~ /^Drupal ([\d.]+)/
9898

99-
return unless $1 && Gem::Version.correct?($1)
99+
return unless $1 && Rex::Version.correct?($1)
100100

101-
Gem::Version.new($1)
101+
Rex::Version.new($1)
102102
end
103103

104104
end

lib/msf/core/exploit/remote/http/wordpress/version.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,20 +189,20 @@ def extract_and_check_version(body, type, item_type, fixed_version = nil, vuln_i
189189
if vuln_introduced_version.nil?
190190
# All versions are vulnerable
191191
return Msf::Exploit::CheckCode::Appears(details:{version: version})
192-
elsif Gem::Version.new(version) >= Gem::Version.new(vuln_introduced_version)
192+
elsif Rex::Version.new(version) >= Rex::Version.new(vuln_introduced_version)
193193
# Newer or equal to the version it was introduced
194194
return Msf::Exploit::CheckCode::Appears(details:{version: version})
195195
else
196196
return Msf::Exploit::CheckCode::Safe(details:{version: version})
197197
end
198198
else
199199
# Version older than fixed version
200-
if Gem::Version.new(version) < Gem::Version.new(fixed_version)
200+
if Rex::Version.new(version) < Rex::Version.new(fixed_version)
201201
if vuln_introduced_version.nil?
202202
# Older than fixed version, no vuln introduction date, flag as vuln
203203
return Msf::Exploit::CheckCode::Appears(details:{version: version})
204204
# vuln_introduced_version provided, check if version is newer
205-
elsif Gem::Version.new(version) >= Gem::Version.new(vuln_introduced_version)
205+
elsif Rex::Version.new(version) >= Rex::Version.new(vuln_introduced_version)
206206
return Msf::Exploit::CheckCode::Appears(details:{version: version})
207207
else
208208
# Not in range, nut vulnerable

lib/msf/core/payload/apk.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,8 @@ def backdoor_apk(apkfile, raw_payload, signature = true, manifest = true, apk_da
150150
raise RuntimeError, "apktool not found. If it's not in your PATH, please add it."
151151
end
152152

153-
apk_v = Gem::Version.new(apktool)
154-
unless apk_v >= Gem::Version.new('2.0.1')
153+
apk_v = Rex::Version.new(apktool)
154+
unless apk_v >= Rex::Version.new('2.0.1')
155155
raise RuntimeError, "apktool version #{apk_v} not supported, please download at least version 2.0.1."
156156
end
157157

lib/rex.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ module Rex
9494
require 'rex/sslscan/scanner'
9595
require 'rex/sslscan/result'
9696

97+
# Versions
98+
require 'rex/version'
99+
97100
# Overload the Kernel.sleep() function to be thread-safe
98101
Kernel.class_eval("
99102
def sleep(seconds=nil)

lib/rex/post/hwbridge/extensions/automotive/automotive.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ def send_isotp_and_wait_for_response(bus, src_id, dst_id, data, opt = {})
120120
data = [ data ] if data.is_a? Integer
121121
if data.size < 8
122122
# Padding is handled differently after 0.0.3
123-
if Gem::Version.new(client.api_version) < Gem::Version.new('0.0.4')
123+
if Rex::Version.new(client.api_version) < Rex::Version.new('0.0.4')
124124
data = padd_packet(data, opt['PADDING']) if opt.key? 'PADDING'
125125
end
126126
data = array2hex(data).join

lib/rex/version.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class Rex::Version < Gem::Version
2+
3+
def initialize(version)
4+
if version.nil?
5+
# Rubygems 4 is deprecating `nil` as a valid version number
6+
# Currently it is the equivalent of a `0` so we set that here to keep the same functionality
7+
version = 0
8+
end
9+
super version
10+
end
11+
end

modules/auxiliary/admin/http/allegro_rompager_auth_bypass.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ def check_response_fingerprint(res, fallback_status)
210210
# ensure the fingerprint at least appears vulnerable
211211
if /RomPager\/(?<version>[\d\.]+)/ =~ fp
212212
vprint_status("#{peer} is RomPager #{version}")
213-
if Gem::Version.new(version) < Gem::Version.new('4.34')
213+
if Rex::Version.new(version) < Rex::Version.new('4.34')
214214
if /realm="(?<model>.+)"/ =~ fp
215215
return model
216216
end

modules/auxiliary/admin/http/joomla_registration_privesc.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def check
5454
return Exploit::CheckCode::Safe
5555
end
5656

57-
version = Gem::Version.new(joomla_version)
57+
version = Rex::Version.new(joomla_version)
5858

5959
unless version
6060
vprint_error('Unable to detect Joomla version')
@@ -63,7 +63,7 @@ def check
6363

6464
vprint_status("Detected Joomla version #{version}")
6565

66-
if version.between?(Gem::Version.new('3.4.4'), Gem::Version.new('3.6.3'))
66+
if version.between?(Rex::Version.new('3.4.4'), Rex::Version.new('3.6.3'))
6767
return Exploit::CheckCode::Appears
6868
end
6969

modules/auxiliary/admin/http/netgear_r6700_pass_reset.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,13 @@ def retrieve_version
100100
fail_with(Failure::UnexpectedReply, 'Failed to obtain device version: no version number found in response') # Taken from https://stackoverflow.com/questions/4115115/extract-a-substring-from-a-string-in-ruby-using-a-regular-expression
101101
end
102102
raw_version_number = version[0].gsub('V', '') # If we got a result, then take the first result from the returned array, and remove the leading 'V'.
103-
Gem::Version.new(raw_version_number) # Finally lets turn it into a Gem::Version object for later use in other parts of the code.
103+
Rex::Version.new(raw_version_number) # Finally lets turn it into a Rex::Version object for later use in other parts of the code.
104104
end
105105

106106
def check
107107
target_version = retrieve_version
108108
print_status("Target is running firmware version #{target_version}")
109-
if (target_version < Gem::Version.new('1.0.4.94')) && (target_version >= Gem::Version.new('1.0.2.62'))
109+
if (target_version < Rex::Version.new('1.0.4.94')) && (target_version >= Rex::Version.new('1.0.2.62'))
110110
return Exploit::CheckCode::Appears
111111
else
112112
return Exploit::Checkcode::Safe
@@ -115,12 +115,12 @@ def check
115115

116116
def find_offset
117117
target_version = retrieve_version
118-
if target_version == Gem::Version.new('1.0.4.84')
118+
if target_version == Rex::Version.new('1.0.4.84')
119119
print_status("#{peer} - Identified Netgear R6700v3 (firmware V1.0.0.4.84_10.0.58) as the target.")
120120
# this offset is where execution will jump to
121121
# a part in the middle of the binary that resets the admin password
122122
return "\x58\x9a\x03"
123-
elsif target_version == Gem::Version.new('1.0.4.82')
123+
elsif target_version == Rex::Version.new('1.0.4.82')
124124
print_status("#{peer} - Identified Netgear R6700v3 (firmware V1.0.0.4.82_10.0.57) as the target.")
125125
return "\x48\x9a\x03"
126126
end

modules/auxiliary/admin/http/pfadmin_set_protected_alias.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ def check
6666
if res.body =~ /<div id="footer".*Postfix Admin/m
6767
version = res.body.match(/<div id="footer"[^<]*<a[^<]*Postfix\s*Admin\s*([^<]*)<\//mi)
6868
return Exploit::CheckCode::Detected unless version
69-
if Gem::Version.new("2.91") > Gem::Version.new(version[1])
69+
if Rex::Version.new("2.91") > Rex::Version.new(version[1])
7070
return Exploit::CheckCode::Detected
71-
elsif Gem::Version.new("3.0.1") < Gem::Version.new(version[1])
71+
elsif Rex::Version.new("3.0.1") < Rex::Version.new(version[1])
7272
return Exploit::CheckCode::Detected
7373
end
7474
return Exploit::CheckCode::Appears

modules/auxiliary/gather/memcached_extractor.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ def run_host(ip)
128128
connect
129129
if (version = determine_version)
130130
vprint_good("Connected to memcached version #{version}")
131-
if (Gem::Version.new(version) >= Gem::Version.new('1.5.4'))
131+
if (Rex::Version.new(version) >= Rex::Version.new('1.5.4'))
132132
command_string = "lru_crawler"
133133
else
134134
command_string = 'cachedump'

modules/auxiliary/gather/qnap_backtrace_admin_hash.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def check
6464
@target = (xml.at('//platform').text == 'TS-NASX86' ? 'x86' : 'ARM')
6565
vprint_status("QNAP #{info[0]} #{info[1..-1].join('-')} detected")
6666

67-
if Gem::Version.new(info[1]) < Gem::Version.new('4.2.3')
67+
if Rex::Version.new(info[1]) < Rex::Version.new('4.2.3')
6868
Exploit::CheckCode::Appears
6969
else
7070
Exploit::CheckCode::Detected

modules/auxiliary/scanner/couchdb/couchdb_enum.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,11 @@ def get_version
8888

8989
def check
9090
return Exploit::CheckCode::Unknown unless get_version
91-
version = Gem::Version.new(@version)
91+
version = Rex::Version.new(@version)
9292
return Exploit::CheckCode::Unknown if version.version.empty?
9393
vprint_good("#{peer} - Found CouchDB version #{version}")
9494

95-
return Exploit::CheckCode::Appears if version < Gem::Version.new('1.7.0') || version.between?(Gem::Version.new('2.0.0'), Gem::Version.new('2.1.0'))
95+
return Exploit::CheckCode::Appears if version < Rex::Version.new('1.7.0') || version.between?(Rex::Version.new('2.0.0'), Rex::Version.new('2.1.0'))
9696

9797
Exploit::CheckCode::Safe
9898
end
@@ -216,9 +216,9 @@ def run
216216

217217
if datastore['CREATEUSER']
218218
fail_with(Failure::Unknown, 'get_version failed in run') unless get_version
219-
version = Gem::Version.new(@version)
219+
version = Rex::Version.new(@version)
220220
print_good("#{peer} - Found CouchDB version #{version}")
221-
create_user if version < Gem::Version.new('1.7.0') || version.between?(Gem::Version.new('2.0.0'), Gem::Version.new('2.1.0'))
221+
create_user if version < Rex::Version.new('1.7.0') || version.between?(Rex::Version.new('2.0.0'), Rex::Version.new('2.1.0'))
222222
end
223223
auth = basic_auth(username, password) if username && password
224224
get_server_info(auth) if datastore['SERVERINFO']

modules/auxiliary/scanner/http/allegro_rompager_misfortune_cookie.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def check_response_fingerprint(res, fallback_status)
7878
fp = http_fingerprint(response: res)
7979
if /RomPager\/(?<version>[\d\.]+)/ =~ fp
8080
vprint_status("#{peer} is RomPager #{version}")
81-
if Gem::Version.new(version) < Gem::Version.new('4.34')
81+
if Rex::Version.new(version) < Rex::Version.new('4.34')
8282
return Exploit::CheckCode::Appears
8383
end
8484
end

modules/auxiliary/scanner/http/bmc_trackit_passwd_reset.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def check_host(ip)
6666
version = res.body.scan(/\bBuild=([\d\.]+)/).flatten.first
6767
if version
6868
fix_version = '11.4'
69-
if Gem::Version.new(version) < Gem::Version.new(fix_version)
69+
if Rex::Version.new(version) < Rex::Version.new(fix_version)
7070
report_vuln(
7171
host: ip,
7272
port: rport,

modules/auxiliary/scanner/http/hp_sys_mgmt_login.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def get_version(res)
5050

5151
def is_version_tested?(version)
5252
# As of Sep 4 2014, version 7.4 is the latest and that's the last one we've tested
53-
if Gem::Version.new(version) < Gem::Version.new('7.5')
53+
if Rex::Version.new(version) < Rex::Version.new('7.5')
5454
return true
5555
end
5656

modules/auxiliary/scanner/http/limesurvey_zip_traversals.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ def determine_version(cookie)
174174
/Version\s+(?<version>\d\.\d{1,2}\.\d{1,2})/ =~ res.body
175175
return nil unless version
176176

177-
Gem::Version.new(version)
177+
Rex::Version.new(version)
178178
end
179179

180180
def run_host(ip)
@@ -188,14 +188,14 @@ def run_host(ip)
188188
cve_2019_9960_pre3_15_9 cookie, ip
189189
end
190190
vprint_status "Version Detected: #{version.version}"
191-
if version.between?(Gem::Version.new('4.0'), Gem::Version.new('4.1.11'))
191+
if version.between?(Rex::Version.new('4.0'), Rex::Version.new('4.1.11'))
192192
cve_2020_11455 cookie, ip
193-
elsif version.between?(Gem::Version.new('2.50.0'), Gem::Version.new('3.15.9'))
193+
elsif version.between?(Rex::Version.new('2.50.0'), Rex::Version.new('3.15.9'))
194194
cve_2019_9960_version_3 cookie, ip
195195
# 2.50 is when LimeSurvey started doing almost daily releases. This version was
196196
# picked arbitrarily as I can't seem to find a lower bounds on when this other
197197
# method may be needed.
198-
elsif version < Gem::Version.new('2.50.0')
198+
elsif version < Rex::Version.new('2.50.0')
199199
cve_2019_9960_pre25 cookie, ip
200200
else
201201
print_bad "No exploit for version #{version.version}"

modules/auxiliary/scanner/http/wordpress_content_injection.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,14 @@ def initialize(info = {})
5050

5151
def check_host(_ip)
5252
if (version = wordpress_version)
53-
version = Gem::Version.new(version)
53+
version = Rex::Version.new(version)
5454
else
5555
return Exploit::CheckCode::Safe
5656
end
5757

5858
vprint_status("WordPress #{version}: #{full_uri}")
5959

60-
if version.between?(Gem::Version.new('4.7'), Gem::Version.new('4.7.1'))
60+
if version.between?(Rex::Version.new('4.7'), Rex::Version.new('4.7.1'))
6161
Exploit::CheckCode::Appears
6262
else
6363
Exploit::CheckCode::Detected

modules/auxiliary/scanner/http/wordpress_multicall_creds.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def check_setup
7676
elsif !wordpress_xmlrpc_enabled?
7777
print_error("#{peer}:#{rport}#{wordpress_url_xmlrpc} does not enable XMLRPC")
7878
false
79-
elsif Gem::Version.new(version) >= Gem::Version.new('4.4.1')
79+
elsif Rex::Version.new(version) >= Rex::Version.new('4.4.1')
8080
print_error("#{peer}#{wordpress_url_xmlrpc} Target's version (#{version}) is not vulnerable to this attack.")
8181
vprint_status("Dropping CHUNKSIZE from #{datastore['CHUNKSIZE']} to 1")
8282
datastore['CHUNKSIZE'] = 1

modules/auxiliary/scanner/http/wp_loginizer_log_sqli.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def run_host(ip)
5757
return
5858
end
5959

60-
if Gem::Version.new(wp_ver) < Gem::Version.new('5.4')
60+
if Rex::Version.new(wp_ver) < Rex::Version.new('5.4')
6161
vprint_error("Wordpress (core) #{wp_ver} is unexploitable. Version 5.4+ required.")
6262
return
6363
end

modules/auxiliary/scanner/smb/smb_uninit_cred.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ def get_samba_info
178178

179179
# Converts a version string into an object so we can eval it
180180
def version(v)
181-
Gem::Version.new(v)
181+
Rex::Version.new(v)
182182
end
183183

184184

modules/auxiliary/scanner/ssh/libssh_auth_bypass.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,16 @@ def initialize(info = {})
5858

5959
# Vulnerable since 0.6.0 and patched in 0.7.6 and 0.8.4
6060
def check_banner(ip, version)
61-
version =~ /libssh[_-]?([\d.]*)$/ && $1 && (v = Gem::Version.new($1))
61+
version =~ /libssh[_-]?([\d.]*)$/ && $1 && (v = Rex::Version.new($1))
6262

6363
if v.nil?
6464
vprint_error("#{ip}:#{rport} - #{version} does not appear to be libssh")
6565
Exploit::CheckCode::Unknown
6666
elsif v.to_s.empty?
6767
vprint_warning("#{ip}:#{rport} - libssh version not reported")
6868
Exploit::CheckCode::Detected
69-
elsif v.between?(Gem::Version.new('0.6.0'), Gem::Version.new('0.7.5')) ||
70-
v.between?(Gem::Version.new('0.8.0'), Gem::Version.new('0.8.3'))
69+
elsif v.between?(Rex::Version.new('0.6.0'), Rex::Version.new('0.7.5')) ||
70+
v.between?(Rex::Version.new('0.8.0'), Rex::Version.new('0.8.3'))
7171
vprint_good("#{ip}:#{rport} - #{version} appears to be unpatched")
7272
Exploit::CheckCode::Appears
7373
else

modules/auxiliary/sqli/openemr/openemr_sqli_dump.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def check
6868
version.sub! ')', ''
6969
version.strip!
7070

71-
return Exploit::CheckCode::Safe unless Gem::Version.new(version) < Gem::Version.new('5.0.1.7')
71+
return Exploit::CheckCode::Safe unless Rex::Version.new(version) < Rex::Version.new('5.0.1.7')
7272

7373
Exploit::CheckCode::Appears
7474
end

0 commit comments

Comments
 (0)