Class: WPScan::Finders::PluginVersion::Readme

Inherits:
CMSScanner::Finders::Finder
  • Object
show all
Defined in:
app/finders/plugin_version/readme.rb

Overview

Plugin Version Finder from the readme.txt file

Instance Method Summary collapse

Instance Method Details

#aggressive(_opts = {}) ⇒ Version

Returns:

  • (Version)


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'app/finders/plugin_version/readme.rb', line 9

def aggressive(_opts = {})
  found_by_msg = 'Readme - %s (Aggressive Detection)'

  # The target(plugin)#readme_url can't be used directly here
  # as if the --detection-mode is passive, it will always return nil
  target.potential_readme_filenames.each do |file|
    res = target.head_and_get(file)

    next unless res.code == 200 && !(numbers = version_numbers(res.body)).empty?

    return numbers.reduce([]) do |a, e|
      a << Model::Version.new(
        e[0],
        found_by: format(found_by_msg, e[1]),
        confidence: e[2],
        interesting_entries: [res.effective_url]
      )
    end
  end

  nil
end

#from_changelog_section(body) ⇒ String?

Returns The best version number detected from the changelog section.

Parameters:

  • body (String)

Returns:

  • (String, nil)

    The best version number detected from the changelog section



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'app/finders/plugin_version/readme.rb', line 61

def from_changelog_section(body)
  extracted_versions = body.scan(%r{[=]+\s+(?:v(?:ersion)?\s*)?([0-9\.-]+)[ \ta-z0-9\(\)\.\-\/]*[=]+}i)

  return if extracted_versions.nil? || extracted_versions.empty?

  extracted_versions.flatten!
  # must contain at least one number
  extracted_versions = extracted_versions.select { |x| x =~ /[0-9]+/ }

  sorted = extracted_versions.sort do |x, y|
    begin
      Gem::Version.new(x) <=> Gem::Version.new(y)
    rescue StandardError
      0
    end
  end

  sorted.last
end

#from_stable_tag(body) ⇒ String?

Returns The version number detected from the stable tag.

Parameters:

  • body (String)

Returns:

  • (String, nil)

    The version number detected from the stable tag



50
51
52
53
54
55
56
# File 'app/finders/plugin_version/readme.rb', line 50

def from_stable_tag(body)
  return unless body =~ /\b(?:stable tag|version):\s*(?!trunk)([0-9a-z\.-]+)/i

  number = Regexp.last_match[1]

  number if /[0-9]+/.match?(number)
end

#version_numbers(body) ⇒ Array<String, String, Integer>

Returns number, found_by, confidence.

Returns:

  • (Array<String, String, Integer>)

    number, found_by, confidence



33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'app/finders/plugin_version/readme.rb', line 33

def version_numbers(body)
  numbers = []

  if (number = from_stable_tag(body))
    numbers << [number, 'Stable Tag', 80]
  end

  if (number = from_changelog_section(body))
    numbers << [number, 'ChangeLog Section', 50]
  end

  numbers
end