Path: blob/master/app/finders/plugin_version/readme.rb
485 views
# frozen_string_literal: true12module WPScan3module Finders4module PluginVersion5# Plugin Version Finder from the readme.txt file6class Readme < CMSScanner::Finders::Finder7# @return [ Version ]8def aggressive(_opts = {})9found_by_msg = 'Readme - %s (Aggressive Detection)'1011# The target(plugin)#readme_url can't be used directly here12# as if the --detection-mode is passive, it will always return nil13target.potential_readme_filenames.each do |file|14res = target.head_and_get(file)1516next unless res.code == 200 && !(numbers = version_numbers(res.body)).empty?1718return numbers.reduce([]) do |a, e|19a << Model::Version.new(20e[0],21found_by: format(found_by_msg, e[1]),22confidence: e[2],23interesting_entries: [res.effective_url]24)25end26end2728nil29end3031# @return [ Array<String, String, Integer> ] number, found_by, confidence32def version_numbers(body)33numbers = []3435if (number = from_stable_tag(body))36numbers << [number, 'Stable Tag', 80]37end3839if (number = from_changelog_section(body))40numbers << [number, 'ChangeLog Section', 50]41end4243numbers44end4546# @param [ String ] body47#48# @return [ String, nil ] The version number detected from the stable tag49def from_stable_tag(body)50return unless body =~ /\b(?:stable tag|version):\s*(?!trunk)([0-9a-z.-]+)/i5152number = Regexp.last_match[1]5354number if /[0-9]+/.match?(number)55end5657# @param [ String ] body58#59# @return [ String, nil ] The best version number detected from the changelog section60def from_changelog_section(body)61extracted_versions = body.scan(/^=+\s+(?:v(?:ersion)?\s*)?([0-9.-]+)[^=]*=+$/i)6263return if extracted_versions.nil? || extracted_versions.empty?6465extracted_versions.flatten!66# must contain at least one number67extracted_versions = extracted_versions.grep(/[0-9]+/)6869sorted = extracted_versions.sort do |x, y|70Gem::Version.new(x) <=> Gem::Version.new(y)71rescue StandardError72073end7475sorted.last76end77end78end79end80end818283