cms_scanner 0.10.0 → 0.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b99be1a5c9ca5480c3144bd7bf47158131b37d2384d0efdead0af974823e2f91
4
- data.tar.gz: ca62945912501cca054acda5c3567428f6d5952ed144f27115ecfd7ac38a8d24
3
+ metadata.gz: 943549919eeec0dc993e93789c543064401359f1673b030e7520ac49eddd8b67
4
+ data.tar.gz: db1524123914c10872586742d1b52bb50550391c5b6b2c56ceaae541b9ff27ad
5
5
  SHA512:
6
- metadata.gz: 92eefec3cc72a884f139077782486ba2bff6716f54566952f0f7d996400deeedc04131f704a2d0e63ba47d9eaaefe2ef8390cc98f411ccb231c876f3ff52c23c
7
- data.tar.gz: 559ea905b19ec7657242e6a0ea4977dcc3f34b2e0159fab086496b138c8916df5b5920723ab0ea621c7141752ce6fc96e6191607fc3cd7c082e15ea5c4a4bce2
6
+ metadata.gz: a70bd9df89f08639549c44c5611bcd1cdab4712d85e02cd2a9b2fe37cb31ab61fe5bb407464686b8abd1a68f7b3986675b17ffe287a967acbe536a6153f5a5c9
7
+ data.tar.gz: 48e01f3d443bd2b78e0ad4fd5e63c8d80ecc4c3bbc40886b5355d4d604a14d985734d90ed3707a22addf7b45fd8c8bcee8e00898bbe4caf7e3fe2cc0025f4093
@@ -2,8 +2,16 @@
2
2
 
3
3
  module CMSScanner
4
4
  module Model
5
- # FantasticoFileslist
5
+ # Fantastico is a commercial script library that automates the installation of web applications to a website.
6
+ # Fantastico scripts are executed from the administration area of a website control panel such as cPanel.
7
+ # It creates a file named fantastico_fileslist.txt that is publicly available and contains a list of all the
8
+ # files from the current directory. The contents of this file may expose sensitive information to an attacker.
6
9
  class FantasticoFileslist < InterestingFinding
10
+ # @return [ String ]
11
+ def to_s
12
+ @to_s ||= "Fantastico list found: #{url}"
13
+ end
14
+
7
15
  # @return [ Array<String> ] The interesting files/dirs detected
8
16
  def interesting_entries
9
17
  results = []
@@ -17,7 +25,9 @@ module CMSScanner
17
25
  end
18
26
 
19
27
  def references
20
- @references ||= { url: ['http://www.acunetix.com/vulnerabilities/fantastico-fileslist/'] }
28
+ @references ||= {
29
+ url: ['https://web.archive.org/web/20140518040021/http://www.acunetix.com/vulnerabilities/fantastico-fileslist/']
30
+ }
21
31
  end
22
32
  end
23
33
  end
@@ -19,7 +19,7 @@ module CMSScanner
19
19
  entries.each do |header, value|
20
20
  next if known_headers.include?(header.downcase)
21
21
 
22
- results << "#{header}: #{[*value].join(', ')}"
22
+ results << "#{header}: #{Array(value).join(', ')}"
23
23
  end
24
24
  results
25
25
  end
@@ -4,6 +4,11 @@ module CMSScanner
4
4
  module Model
5
5
  # Robots.txt
6
6
  class RobotsTxt < InterestingFinding
7
+ # @return [ String ]
8
+ def to_s
9
+ @to_s ||= "robots.txt found: #{url}"
10
+ end
11
+
7
12
  # @todo Better detection, currently everything not empty or / is returned
8
13
  #
9
14
  # @return [ Array<String> ] The interesting Allow/Disallow rules detected
@@ -4,6 +4,11 @@ module CMSScanner
4
4
  module Model
5
5
  # SearchReplaceDB2
6
6
  class SearchReplaceDB2 < InterestingFinding
7
+ # @return [ String ]
8
+ def to_s
9
+ @to_s ||= "Search Replace DB script found: #{url}"
10
+ end
11
+
7
12
  def references
8
13
  @references ||= { url: ['https://interconnectit.com/products/search-and-replace-for-wordpress-databases/'] }
9
14
  end
@@ -59,7 +59,7 @@ module CMSScanner
59
59
  #
60
60
  # @return [ String ] The expiration file path associated to the key
61
61
  def entry_expiration_path(key)
62
- entry_path(key) + '.expiration'
62
+ "#{entry_path(key)}.expiration"
63
63
  end
64
64
 
65
65
  private
@@ -21,14 +21,14 @@ module CMSScanner
21
21
 
22
22
  return symbols if mode.nil? || mode == :mixed
23
23
 
24
- symbols.include?(mode) ? [*mode] : []
24
+ symbols.include?(mode) ? Array(mode) : []
25
25
  end
26
26
 
27
27
  # @param [ CMSScanner::Finders::Finder ] finder
28
28
  # @param [ Symbol ] symbol See return values of #symbols_from_mode
29
29
  # @param [ Hash ] opts
30
30
  def run_finder(finder, symbol, opts)
31
- [*finder.send(symbol, opts.merge(found: findings))].compact.each do |found|
31
+ Array(finder.send(symbol, opts.merge(found: findings))).compact.each do |found|
32
32
  findings << found
33
33
  end
34
34
  end
@@ -57,10 +57,12 @@ module CMSScanner
57
57
  # @param [String, Class ] klass
58
58
  # @return [ String ]
59
59
  def found_by(klass = self.class)
60
+ labels = %w[aggressive passive]
61
+
60
62
  caller_locations.each do |call|
61
63
  label = call.label
62
64
 
63
- next unless %w[aggressive passive].include? label
65
+ next unless labels.include? label
64
66
 
65
67
  title = klass.to_s.demodulize.gsub(/(\d+)[a-z]+/i, '_\0').titleize(keep_id_suffix: true)
66
68
 
@@ -6,20 +6,22 @@ module CMSScanner
6
6
  # Module to provide an easy way to perform password attacks
7
7
  module BreadthFirstDictionaryAttack
8
8
  # @param [ Array<CMSScanner::Model::User> ] users
9
- # @param [ Array<String> ] passwords
9
+ # @param [ String ] wordlist_path
10
10
  # @param [ Hash ] opts
11
11
  # @option opts [ Boolean ] :show_progression
12
12
  #
13
13
  # @yield [ CMSScanner::User ] When a valid combination is found
14
14
  #
15
15
  # Due to Typhoeus threads shenanigans, in rare cases the progress-bar might
16
- # be incorrect updated, hence the 'rescue ProgressBar::InvalidProgressError'
16
+ # be incorrectly updated, hence the 'rescue ProgressBar::InvalidProgressError'
17
17
  #
18
18
  # TODO: Make rubocop happy about metrics etc
19
19
  #
20
20
  # rubocop:disable all
21
- def attack(users, passwords, opts = {})
22
- create_progress_bar(total: users.size * passwords.size, show_progression: opts[:show_progression])
21
+ def attack(users, wordlist_path, opts = {})
22
+ wordlist = File.open(wordlist_path)
23
+
24
+ create_progress_bar(total: users.size * wordlist.count, show_progression: opts[:show_progression])
23
25
 
24
26
  queue_count = 0
25
27
  # Keep the number of requests sent for each users
@@ -28,7 +30,7 @@ module CMSScanner
28
30
 
29
31
  users.each { |u| user_requests_count[u.username] = 0 }
30
32
 
31
- passwords.each do |password|
33
+ File.foreach(wordlist, chomp: true) do |password|
32
34
  remaining_users = users.select { |u| u.password.nil? }
33
35
 
34
36
  break if remaining_users.empty?
@@ -47,7 +49,7 @@ module CMSScanner
47
49
  user.password = password
48
50
 
49
51
  begin
50
- progress_bar.total -= passwords.size - user_requests_count[user.username]
52
+ progress_bar.total -= wordlist.count - user_requests_count[user.username]
51
53
  rescue ProgressBar::InvalidProgressError
52
54
  end
53
55
 
@@ -103,10 +105,12 @@ module CMSScanner
103
105
  'Request timed out.'
104
106
  elsif response.code.zero?
105
107
  "No response from remote server. WAF/IPS? (#{response.return_message})"
106
- elsif /^50/.match?(response.code.to_s)
108
+ elsif response.code.to_s.start_with?('50')
107
109
  'Server error, try reducing the number of threads.'
108
- else
110
+ elsif NS::ParsedCli.verbose?
109
111
  "Unknown response received Code: #{response.code}\nBody: #{response.body}"
112
+ else
113
+ "Unknown response received Code: #{response.code}"
110
114
  end
111
115
 
112
116
  progress_bar.log("Error: #{error}")
@@ -55,7 +55,7 @@ module CMSScanner
55
55
  # @return [ Typhoeus::Response, nil ]
56
56
  def maybe_get_full_response(head_res, opts)
57
57
  return head_res unless opts[:check_full_response] == true ||
58
- [*opts[:check_full_response]].include?(head_res.code)
58
+ Array(opts[:check_full_response]).include?(head_res.code)
59
59
 
60
60
  full_res = NS::Browser.get(head_res.effective_url, full_request_params)
61
61
 
@@ -8,6 +8,6 @@ class Numeric
8
8
  e = abs.zero? ? abs : (Math.log(abs) / Math.log(1024)).floor
9
9
  s = format('%<s>.3f', s: (abs.to_f / 1024**e))
10
10
 
11
- s.sub(/\.?0*$/, ' ' + units[e])
11
+ s.sub(/\.?0*$/, " #{units[e]}")
12
12
  end
13
13
  end
@@ -17,7 +17,7 @@ module CMSScanner
17
17
  def log(string = nil)
18
18
  return logs if string.nil?
19
19
 
20
- logs << string
20
+ logs << string unless logs.include?(string)
21
21
  end
22
22
  end
23
23
  end
@@ -21,9 +21,9 @@ module CMSScanner
21
21
  next unless refs.key?(key)
22
22
 
23
23
  @references[key] = if key == :youtube
24
- [*refs[:youtube]].map { |id| youtube_url(id) }
24
+ Array(refs[:youtube]).map { |id| youtube_url(id) }
25
25
  else
26
- [*refs[key]].map(&:to_s)
26
+ Array(refs[key]).map(&:to_s)
27
27
  end
28
28
  end
29
29
  end
@@ -18,7 +18,7 @@ module CMSScanner
18
18
  super(url, opts)
19
19
 
20
20
  scope << uri.host
21
- [*opts[:scope]].each { |s| scope << s }
21
+ Array(opts[:scope]).each { |s| scope << s }
22
22
  end
23
23
 
24
24
  # @param [ Hash ] opts
@@ -105,11 +105,11 @@ module CMSScanner
105
105
  next unless attr_value && !attr_value.empty?
106
106
 
107
107
  node_uri = begin
108
- uri.join(attr_value.strip)
109
- rescue StandardError
110
- # Skip potential malformed URLs etc.
111
- next
112
- end
108
+ uri.join(attr_value.strip)
109
+ rescue StandardError
110
+ # Skip potential malformed URLs etc.
111
+ next
112
+ end
113
113
 
114
114
  next unless node_uri.host
115
115
 
@@ -5,7 +5,7 @@ module CMSScanner
5
5
  module Platform
6
6
  # Some PHP specific implementation
7
7
  module PHP
8
- DEBUG_LOG_PATTERN = /(?:\[\d{2}\-[a-zA-Z]{3}\-\d{4}\s\d{2}\:\d{2}:\d{2}\s[A-Z]{3}\]|
8
+ DEBUG_LOG_PATTERN = /(?:\[\d{2}-[a-zA-Z]{3}-\d{4}\s\d{2}:\d{2}:\d{2}\s[A-Z]{3}\]|
9
9
  PHP\s(?:Fatal|Warning|Strict|Error|Notice):)/x.freeze
10
10
  FPD_PATTERN = /Fatal error:.+? in (.+?) on/.freeze
11
11
  ERROR_LOG_PATTERN = /PHP Fatal error/i.freeze
@@ -53,14 +53,14 @@ module CMSScanner
53
53
  domains = [uri.host + uri.path]
54
54
 
55
55
  domains += if scope.domains.empty?
56
- [*scope.invalid_domains[1..-1]]
56
+ Array(scope.invalid_domains[1..-1])
57
57
  else
58
- [*scope.domains[1..-1]].map(&:to_s) + scope.invalid_domains
58
+ Array(scope.domains[1..-1]).map(&:to_s) + scope.invalid_domains
59
59
  end
60
60
 
61
- domains.map! { |d| Regexp.escape(d.gsub(%r{/$}, '')).gsub('\*', '.*').gsub('/', '\\\\\?/') }
61
+ domains.map! { |d| Regexp.escape(d.delete_suffix('/')).gsub('\*', '.*').gsub('/', '\\\\\?/') }
62
62
 
63
- domains[0].gsub!(Regexp.escape(uri.host), Regexp.escape(uri.host) + '(?::\\d+)?') if uri.port
63
+ domains[0].gsub!(Regexp.escape(uri.host), "#{Regexp.escape(uri.host)}(?::\\d+)?") if uri.port
64
64
 
65
65
  @scope_url_pattern = %r{https?:\\?/\\?/(?:#{domains.join('|')})\\?/?}i
66
66
  end
@@ -41,7 +41,7 @@ module CMSScanner
41
41
  def directory_listing?(path = nil, params = {})
42
42
  res = NS::Browser.get(url(path), params)
43
43
 
44
- res.code == 200 && res.body =~ /<h1>Index of/ ? true : false
44
+ res.code == 200 && res.body.include?('<h1>Index of') ? true : false
45
45
  end
46
46
 
47
47
  # @param [ String ] path
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Version
4
4
  module CMSScanner
5
- VERSION = '0.10.0'
5
+ VERSION = '0.12.2'
6
6
  end
@@ -62,7 +62,7 @@ module CMSScanner
62
62
 
63
63
  # @return [ String ] The URL of an unlikely existant page
64
64
  def error_404_url
65
- @error_404_url ||= uri.join(Digest::MD5.hexdigest(rand(999_999).to_s)[0..6] + '.html').to_s
65
+ @error_404_url ||= uri.join("#{Digest::MD5.hexdigest(rand(999_999).to_s)[0..6]}.html").to_s
66
66
  end
67
67
 
68
68
  # Checks if the remote website is up.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cms_scanner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.12.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - WPScanTeam
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-16 00:00:00.000000000 Z
11
+ date: 2021-01-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: get_process_mem
@@ -30,28 +30,28 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.10.8
33
+ version: 1.11.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 1.10.8
40
+ version: 1.11.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: opt_parse_validator
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 1.9.0
47
+ version: 1.9.3
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 1.9.0
54
+ version: 1.9.3
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: public_suffix
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -70,30 +70,42 @@ dependencies:
70
70
  name: ruby-progressbar
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '1.10'
76
+ - - "<"
74
77
  - !ruby/object:Gem::Version
75
- version: 1.10.0
78
+ version: '1.12'
76
79
  type: :runtime
77
80
  prerelease: false
78
81
  version_requirements: !ruby/object:Gem::Requirement
79
82
  requirements:
80
- - - "~>"
83
+ - - ">="
81
84
  - !ruby/object:Gem::Version
82
- version: 1.10.0
85
+ version: '1.10'
86
+ - - "<"
87
+ - !ruby/object:Gem::Version
88
+ version: '1.12'
83
89
  - !ruby/object:Gem::Dependency
84
90
  name: typhoeus
85
91
  requirement: !ruby/object:Gem::Requirement
86
92
  requirements:
87
- - - "~>"
93
+ - - ">="
88
94
  - !ruby/object:Gem::Version
89
- version: 1.3.0
95
+ version: '1.3'
96
+ - - "<"
97
+ - !ruby/object:Gem::Version
98
+ version: '1.5'
90
99
  type: :runtime
91
100
  prerelease: false
92
101
  version_requirements: !ruby/object:Gem::Requirement
93
102
  requirements:
94
- - - "~>"
103
+ - - ">="
95
104
  - !ruby/object:Gem::Version
96
- version: 1.3.0
105
+ version: '1.3'
106
+ - - "<"
107
+ - !ruby/object:Gem::Version
108
+ version: '1.5'
97
109
  - !ruby/object:Gem::Dependency
98
110
  name: xmlrpc
99
111
  requirement: !ruby/object:Gem::Requirement
@@ -170,14 +182,14 @@ dependencies:
170
182
  requirements:
171
183
  - - "~>"
172
184
  - !ruby/object:Gem::Version
173
- version: 3.9.0
185
+ version: 3.10.0
174
186
  type: :development
175
187
  prerelease: false
176
188
  version_requirements: !ruby/object:Gem::Requirement
177
189
  requirements:
178
190
  - - "~>"
179
191
  - !ruby/object:Gem::Version
180
- version: 3.9.0
192
+ version: 3.10.0
181
193
  - !ruby/object:Gem::Dependency
182
194
  name: rspec-its
183
195
  requirement: !ruby/object:Gem::Requirement
@@ -198,42 +210,42 @@ dependencies:
198
210
  requirements:
199
211
  - - "~>"
200
212
  - !ruby/object:Gem::Version
201
- version: 0.81.0
213
+ version: 1.7.0
202
214
  type: :development
203
215
  prerelease: false
204
216
  version_requirements: !ruby/object:Gem::Requirement
205
217
  requirements:
206
218
  - - "~>"
207
219
  - !ruby/object:Gem::Version
208
- version: 0.81.0
220
+ version: 1.7.0
209
221
  - !ruby/object:Gem::Dependency
210
222
  name: rubocop-performance
211
223
  requirement: !ruby/object:Gem::Requirement
212
224
  requirements:
213
225
  - - "~>"
214
226
  - !ruby/object:Gem::Version
215
- version: 1.5.0
227
+ version: 1.9.0
216
228
  type: :development
217
229
  prerelease: false
218
230
  version_requirements: !ruby/object:Gem::Requirement
219
231
  requirements:
220
232
  - - "~>"
221
233
  - !ruby/object:Gem::Version
222
- version: 1.5.0
234
+ version: 1.9.0
223
235
  - !ruby/object:Gem::Dependency
224
236
  name: simplecov
225
237
  requirement: !ruby/object:Gem::Requirement
226
238
  requirements:
227
239
  - - "~>"
228
240
  - !ruby/object:Gem::Version
229
- version: 0.18.2
241
+ version: 0.21.0
230
242
  type: :development
231
243
  prerelease: false
232
244
  version_requirements: !ruby/object:Gem::Requirement
233
245
  requirements:
234
246
  - - "~>"
235
247
  - !ruby/object:Gem::Version
236
- version: 0.18.2
248
+ version: 0.21.0
237
249
  - !ruby/object:Gem::Dependency
238
250
  name: simplecov-lcov
239
251
  requirement: !ruby/object:Gem::Requirement
@@ -254,14 +266,14 @@ dependencies:
254
266
  requirements:
255
267
  - - "~>"
256
268
  - !ruby/object:Gem::Version
257
- version: 3.8.0
269
+ version: 3.11.0
258
270
  type: :development
259
271
  prerelease: false
260
272
  version_requirements: !ruby/object:Gem::Requirement
261
273
  requirements:
262
274
  - - "~>"
263
275
  - !ruby/object:Gem::Version
264
- version: 3.8.0
276
+ version: 3.11.0
265
277
  description: Framework to provide an easy way to implement CMS Scanners
266
278
  email:
267
279
  - team@wpscan.org