Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wpscanteam
GitHub Repository: wpscanteam/wpscan
Path: blob/master/app/finders/plugin_version/readme.rb
485 views
1
# frozen_string_literal: true
2
3
module WPScan
4
module Finders
5
module PluginVersion
6
# Plugin Version Finder from the readme.txt file
7
class Readme < CMSScanner::Finders::Finder
8
# @return [ Version ]
9
def aggressive(_opts = {})
10
found_by_msg = 'Readme - %s (Aggressive Detection)'
11
12
# The target(plugin)#readme_url can't be used directly here
13
# as if the --detection-mode is passive, it will always return nil
14
target.potential_readme_filenames.each do |file|
15
res = target.head_and_get(file)
16
17
next unless res.code == 200 && !(numbers = version_numbers(res.body)).empty?
18
19
return numbers.reduce([]) do |a, e|
20
a << Model::Version.new(
21
e[0],
22
found_by: format(found_by_msg, e[1]),
23
confidence: e[2],
24
interesting_entries: [res.effective_url]
25
)
26
end
27
end
28
29
nil
30
end
31
32
# @return [ Array<String, String, Integer> ] number, found_by, confidence
33
def version_numbers(body)
34
numbers = []
35
36
if (number = from_stable_tag(body))
37
numbers << [number, 'Stable Tag', 80]
38
end
39
40
if (number = from_changelog_section(body))
41
numbers << [number, 'ChangeLog Section', 50]
42
end
43
44
numbers
45
end
46
47
# @param [ String ] body
48
#
49
# @return [ String, nil ] The version number detected from the stable tag
50
def from_stable_tag(body)
51
return unless body =~ /\b(?:stable tag|version):\s*(?!trunk)([0-9a-z.-]+)/i
52
53
number = Regexp.last_match[1]
54
55
number if /[0-9]+/.match?(number)
56
end
57
58
# @param [ String ] body
59
#
60
# @return [ String, nil ] The best version number detected from the changelog section
61
def from_changelog_section(body)
62
extracted_versions = body.scan(/^=+\s+(?:v(?:ersion)?\s*)?([0-9.-]+)[^=]*=+$/i)
63
64
return if extracted_versions.nil? || extracted_versions.empty?
65
66
extracted_versions.flatten!
67
# must contain at least one number
68
extracted_versions = extracted_versions.grep(/[0-9]+/)
69
70
sorted = extracted_versions.sort do |x, y|
71
Gem::Version.new(x) <=> Gem::Version.new(y)
72
rescue StandardError
73
0
74
end
75
76
sorted.last
77
end
78
end
79
end
80
end
81
end
82
83