cms_scanner 0.10.0 → 0.12.2

Sign up to get free protection for your applications and to get access to all the features.
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