From c4aed0ec8908695aee58b979009cbbdd110cbd84 Mon Sep 17 00:00:00 2001 From: ethicalhack3r Date: Fri, 14 Aug 2015 00:19:22 +0200 Subject: [PATCH] Initial attempt at implementing apiv2 #853 --- .rspec | 2 +- lib/common/collections/wp_items.rb | 1 + lib/common/collections/wp_items/detectable.rb | 28 ++++++------- .../collections/wp_plugins/detectable.rb | 8 +--- .../collections/wp_themes/detectable.rb | 8 +--- lib/common/common_helper.rb | 23 +++++------ lib/common/db_updater.rb | 3 +- lib/common/models/vulnerability.rb | 11 +++--- lib/common/models/vulnerability/output.rb | 8 ++-- lib/common/models/wp_item/output.rb | 2 + lib/common/models/wp_item/vulnerable.rb | 7 ++-- lib/common/models/wp_plugin/vulnerable.rb | 2 +- lib/common/models/wp_theme/vulnerable.rb | 2 +- lib/common/models/wp_version/vulnerable.rb | 2 +- wpscan.rb | 39 ++++++++++++++++--- 15 files changed, 81 insertions(+), 65 deletions(-) diff --git a/.rspec b/.rspec index ba44b749..9c3c126f 100644 --- a/.rspec +++ b/.rspec @@ -1,2 +1,2 @@ --color ---fail-fast +#--fail-fast diff --git a/lib/common/collections/wp_items.rb b/lib/common/collections/wp_items.rb index 5fdb17ec..0ac3adb4 100755 --- a/lib/common/collections/wp_items.rb +++ b/lib/common/collections/wp_items.rb @@ -67,6 +67,7 @@ class WpItems < Array end protected + # @return [ Class ] def item_class Object.const_get(self.class.to_s.gsub(/.$/, '')) diff --git a/lib/common/collections/wp_items/detectable.rb b/lib/common/collections/wp_items/detectable.rb index d27925df..96ca5057 100755 --- a/lib/common/collections/wp_items/detectable.rb +++ b/lib/common/collections/wp_items/detectable.rb @@ -155,15 +155,7 @@ class WpItems < Array item_class = self.item_class vulns_file = self.vulns_file - targets = vulnerable_targets_items(wp_target, item_class, vulns_file) - - unless options[:only_vulnerable] - unless options[:file] - raise 'A file must be supplied' - end - - targets += targets_items_from_file(options[:file], wp_target, item_class, vulns_file) - end + targets = target_items(wp_target, item_class, vulns_file, options[:type]) targets.uniq! { |t| t.name } targets.sort_by { rand } @@ -174,14 +166,25 @@ class WpItems < Array # @param [ String ] vulns_file # # @return [ Array ] - def vulnerable_targets_items(wp_target, item_class, vulns_file) + def target_items(wp_target, item_class, vulns_file, type) targets = [] json = json(vulns_file) - [*json].each do |item| + case type + when :vulnerable + item_names = json.select { |item| !item['vulnerabilities'].empty? }.map {|item| item['name'] } + when :popular + item_names = json.select { |item| item['popular'] == true }.map {|item| item['name'] } + when :all + item_names = [*json].map { |item| item['name'] } + else + raise "Known type #{type}" + end + + item_names.each do |item_name| targets << create_item( item_class, - item.keys.inject, + item_name, wp_target, vulns_file ) @@ -233,6 +236,5 @@ class WpItems < Array def item_class Object.const_get(self.to_s.gsub(/.$/, '')) end - end end diff --git a/lib/common/collections/wp_plugins/detectable.rb b/lib/common/collections/wp_plugins/detectable.rb index 3eb43c3c..30be4381 100644 --- a/lib/common/collections/wp_plugins/detectable.rb +++ b/lib/common/collections/wp_plugins/detectable.rb @@ -2,17 +2,11 @@ class WpPlugins < WpItems module Detectable - # @return [ String ] def vulns_file - PLUGINS_VULNS_FILE + PLUGINS_FILE end - # @return [ String ] - # def item_xpath - # '//plugin' - # end - # @param [ WpTarget ] wp_target # @param [ Hash ] options # diff --git a/lib/common/collections/wp_themes/detectable.rb b/lib/common/collections/wp_themes/detectable.rb index a2c3e594..7e28b8b1 100644 --- a/lib/common/collections/wp_themes/detectable.rb +++ b/lib/common/collections/wp_themes/detectable.rb @@ -5,13 +5,7 @@ class WpThemes < WpItems # @return [ String ] def vulns_file - THEMES_VULNS_FILE + THEMES_FILE end - - # @return [ String ] - # def item_xpath - # '//theme' - # end - end end diff --git a/lib/common/common_helper.rb b/lib/common/common_helper.rb index 82f40516..34604f93 100644 --- a/lib/common/common_helper.rb +++ b/lib/common/common_helper.rb @@ -18,20 +18,15 @@ COMMON_PLUGINS_DIR = File.join(COMMON_LIB_DIR, 'plugins') WPSCAN_PLUGINS_DIR = File.join(WPSCAN_LIB_DIR, 'plugins') # Not used ATM # Data files -PLUGINS_FILE = File.join(DATA_DIR, 'plugins.txt') -PLUGINS_FULL_FILE = File.join(DATA_DIR, 'plugins_full.txt') -PLUGINS_VULNS_FILE = File.join(DATA_DIR, 'plugin_vulns.json') -THEMES_FILE = File.join(DATA_DIR, 'themes.txt') -THEMES_FULL_FILE = File.join(DATA_DIR, 'themes_full.txt') -THEMES_VULNS_FILE = File.join(DATA_DIR, 'theme_vulns.json') -WP_VULNS_FILE = File.join(DATA_DIR, 'wp_vulns.json') -WP_VERSIONS_FILE = File.join(DATA_DIR, 'wp_versions.xml') -LOCAL_FILES_FILE = File.join(DATA_DIR, 'local_vulnerable_files.xml') -# VULNS_XSD = File.join(DATA_DIR, 'vuln.xsd') -WP_VERSIONS_XSD = File.join(DATA_DIR, 'wp_versions.xsd') -LOCAL_FILES_XSD = File.join(DATA_DIR, 'local_vulnerable_files.xsd') -USER_AGENTS_FILE = File.join(DATA_DIR, 'user-agents.txt') -LAST_UPDATE_FILE = File.join(DATA_DIR, '.last_update') +WORDPRESSES_FILE = File.join(DATA_DIR, 'wordpresses.json') +PLUGINS_FILE = File.join(DATA_DIR, 'plugins.json') +THEMES_FILE = File.join(DATA_DIR, 'themes.json') +WP_VERSIONS_FILE = File.join(DATA_DIR, 'wp_versions.xml') +LOCAL_FILES_FILE = File.join(DATA_DIR, 'local_vulnerable_files.xml') +WP_VERSIONS_XSD = File.join(DATA_DIR, 'wp_versions.xsd') +LOCAL_FILES_XSD = File.join(DATA_DIR, 'local_vulnerable_files.xsd') +USER_AGENTS_FILE = File.join(DATA_DIR, 'user-agents.txt') +LAST_UPDATE_FILE = File.join(DATA_DIR, '.last_update') WPSCAN_VERSION = '2.8' diff --git a/lib/common/db_updater.rb b/lib/common/db_updater.rb index 0204a9df..55a37095 100644 --- a/lib/common/db_updater.rb +++ b/lib/common/db_updater.rb @@ -4,9 +4,8 @@ class DbUpdater FILES = %w( local_vulnerable_files.xml local_vulnerable_files.xsd - plugins_full.txt plugins.txt themes_full.txt themes.txt timthumbs.txt user-agents.txt wp_versions.xml wp_versions.xsd - plugin_vulns.json theme_vulns.json wp_vulns.json LICENSE + wordpresses.json plugins.json themes.json LICENSE ) attr_reader :repo_directory diff --git a/lib/common/models/vulnerability.rb b/lib/common/models/vulnerability.rb index 1e6dccc7..c1a94992 100755 --- a/lib/common/models/vulnerability.rb +++ b/lib/common/models/vulnerability.rb @@ -42,11 +42,12 @@ class Vulnerability # @return [ Vulnerability ] def self.load_from_json_item(json_item) references = {} + references['id'] = [json_item['id']] - %w(id url cve secunia osvdb metasploit exploitdb).each do |key| - if json_item[key] - json_item[key] = [json_item[key]] if json_item[key].class != Array - references[key] = json_item[key] + %w(url cve secunia osvdb metasploit exploitdb).each do |key| + if json_item['references'][key] + json_item['references'][key] = [json_item['references'][key]] if json_item['references'][key].class != Array + references[key] = json_item['references'][key] end end @@ -54,7 +55,7 @@ class Vulnerability json_item['title'], json_item['type'], references, - json_item['fixed_in'], + json_item['fixed_in'] ) end diff --git a/lib/common/models/vulnerability/output.rb b/lib/common/models/vulnerability/output.rb index e6170338..06e81798 100644 --- a/lib/common/models/vulnerability/output.rb +++ b/lib/common/models/vulnerability/output.rb @@ -2,22 +2,22 @@ class Vulnerability module Output - # output the vulnerability def output(verbose = false) puts puts critical("Title: #{title}") + references.each do |key, urls| methodname = "url_#{key}" + urls.each do |u| next unless respond_to?(methodname) url = send(methodname, u) puts " Reference: #{url}" if url end end - unless fixed_in.nil? - puts notice("Fixed in: #{fixed_in}") - end + + puts notice("Fixed in: #{fixed_in}") if fixed_in end end end diff --git a/lib/common/models/wp_item/output.rb b/lib/common/models/wp_item/output.rb index 889883e1..17e8f219 100644 --- a/lib/common/models/wp_item/output.rb +++ b/lib/common/models/wp_item/output.rb @@ -7,6 +7,8 @@ class WpItem def output(verbose = false) puts puts info("Name: #{self}") #this will also output the version number if detected + puts " | Latest version:" + puts " | Last updated:" puts " | Location: #{url}" #puts " | WordPress: #{wordpress_url}" if wordpress_org_item? puts " | Readme: #{readme_url}" if has_readme? diff --git a/lib/common/models/wp_item/vulnerable.rb b/lib/common/models/wp_item/vulnerable.rb index 3b7619cf..99b9a189 100755 --- a/lib/common/models/wp_item/vulnerable.rb +++ b/lib/common/models/wp_item/vulnerable.rb @@ -9,15 +9,16 @@ class WpItem # # @return [ Vulnerabilities ] def vulnerabilities - json = json(vulns_file) + json = json(vulns_file).select { |item| !item['vulnerabilities'].empty? } vulnerabilities = Vulnerabilities.new json.each do |item| - asset = item[identifier] + asset = item['version'][identifier] if item['version'] + asset = item['name'][identifier] if item['name'] next unless asset - asset['vulnerabilities'].each do |vulnerability| + item['vulnerabilities'].each do |vulnerability| vulnerability = Vulnerability.load_from_json_item(vulnerability) vulnerabilities << vulnerability if vulnerable_to?(vulnerability) end diff --git a/lib/common/models/wp_plugin/vulnerable.rb b/lib/common/models/wp_plugin/vulnerable.rb index 1d994d62..c19e6c07 100644 --- a/lib/common/models/wp_plugin/vulnerable.rb +++ b/lib/common/models/wp_plugin/vulnerable.rb @@ -6,7 +6,7 @@ class WpPlugin < WpItem # @return [ String ] The path to the file containing vulnerabilities def vulns_file unless @vulns_file - @vulns_file = PLUGINS_VULNS_FILE + @vulns_file = PLUGINS_FILE end @vulns_file end diff --git a/lib/common/models/wp_theme/vulnerable.rb b/lib/common/models/wp_theme/vulnerable.rb index 756f547a..60e5560c 100644 --- a/lib/common/models/wp_theme/vulnerable.rb +++ b/lib/common/models/wp_theme/vulnerable.rb @@ -6,7 +6,7 @@ class WpTheme < WpItem # @return [ String ] The path to the file containing vulnerabilities def vulns_file unless @vulns_file - @vulns_file = THEMES_VULNS_FILE + @vulns_file = THEMES_FILE end @vulns_file end diff --git a/lib/common/models/wp_version/vulnerable.rb b/lib/common/models/wp_version/vulnerable.rb index ad846a26..da23790b 100644 --- a/lib/common/models/wp_version/vulnerable.rb +++ b/lib/common/models/wp_version/vulnerable.rb @@ -6,7 +6,7 @@ class WpVersion < WpItem # @return [ String ] The path to the file containing vulnerabilities def vulns_file unless @vulns_file - @vulns_file = WP_VULNS_FILE + @vulns_file = WORDPRESSES_FILE end @vulns_file end diff --git a/wpscan.rb b/wpscan.rb index a95033f8..5cd6afd3 100755 --- a/wpscan.rb +++ b/wpscan.rb @@ -273,15 +273,29 @@ def main # Enumerate the installed plugins if wpscan_options.enumerate_plugins or wpscan_options.enumerate_only_vulnerable_plugins or wpscan_options.enumerate_all_plugins puts - puts info("Enumerating installed plugins #{'(only vulnerable ones)' if wpscan_options.enumerate_only_vulnerable_plugins} ...") + if wpscan_options.enumerate_only_vulnerable_plugins + puts info('Enumerating installed plugins (only ones with known vulnerabilities) ...') + plugin_enumeration_type = :vulnerable + end + + if wpscan_options.enumerate_plugins + puts info('Enumerating installed plugins (only ones marked as popular) ...') + plugin_enumeration_type = :popular + end + + if wpscan_options.enumerate_all_plugins + puts info('Enumerating all plugins (may take a while and use a lot of system resources) ...') + plugin_enumeration_type = :all + end puts wp_plugins = WpPlugins.aggressive_detection(wp_target, enum_options.merge( - file: wpscan_options.enumerate_all_plugins ? PLUGINS_FULL_FILE : PLUGINS_FILE, - only_vulnerable: wpscan_options.enumerate_only_vulnerable_plugins || false + file: PLUGINS_FILE, + type: plugin_enumeration_type ) ) + puts if !wp_plugins.empty? puts info("We found #{wp_plugins.size} plugins:") @@ -295,13 +309,26 @@ def main # Enumerate installed themes if wpscan_options.enumerate_themes or wpscan_options.enumerate_only_vulnerable_themes or wpscan_options.enumerate_all_themes puts - puts info("Enumerating installed themes #{'(only vulnerable ones)' if wpscan_options.enumerate_only_vulnerable_themes} ...") + if wpscan_options.enumerate_only_vulnerable_themes + puts info('Enumerating installed themes (only ones with known vulnerabilities) ...') + theme_enumeration_type = :vulnerable + end + + if wpscan_options.enumerate_themes + puts info('Enumerating installed themes (only ones marked as popular) ...') + theme_enumeration_type = :popular + end + + if wpscan_options.enumerate_all_themes + puts info('Enumerating all themes (may take a while and use a lot of system resources) ...') + theme_enumeration_type = :all + end puts wp_themes = WpThemes.aggressive_detection(wp_target, enum_options.merge( - file: wpscan_options.enumerate_all_themes ? THEMES_FULL_FILE : THEMES_FILE, - only_vulnerable: wpscan_options.enumerate_only_vulnerable_themes || false + file: THEMES_FILE, + type: theme_enumeration_type ) ) puts