From fffcd61cc4a674880fd0b1dfcf421b225d0df54b Mon Sep 17 00:00:00 2001 From: Christian Mehlmauer Date: Sat, 7 Dec 2013 22:04:51 +0100 Subject: [PATCH] Detect and output parent theme --- lib/common/models/wp_theme.rb | 16 ++++---- lib/common/models/wp_theme/childtheme.rb | 33 ++++++++++++++++ lib/common/models/wp_theme/info.rb | 50 ++++++++++++------------ lib/common/models/wp_theme/output.rb | 30 +++++++------- wpscan.rb | 10 +++++ 5 files changed, 92 insertions(+), 47 deletions(-) create mode 100644 lib/common/models/wp_theme/childtheme.rb diff --git a/lib/common/models/wp_theme.rb b/lib/common/models/wp_theme.rb index fe28360d..6cafa982 100755 --- a/lib/common/models/wp_theme.rb +++ b/lib/common/models/wp_theme.rb @@ -5,23 +5,25 @@ require 'wp_theme/versionable' require 'wp_theme/vulnerable' require 'wp_theme/info' require 'wp_theme/output' +require 'wp_theme/childtheme' class WpTheme < WpItem extend WpTheme::Findable include WpTheme::Versionable include WpTheme::Vulnerable - include WpTheme::Info - include WpTheme::Output + include WpTheme::Info + include WpTheme::Output + include WpTheme::Childtheme attr_writer :style_url def allowed_options; super << :style_url end - def initialize(*args) - super(*args) + def initialize(*args) + super(*args) - parse_style - end + parse_style + end # Sets the @uri # @@ -38,6 +40,6 @@ class WpTheme < WpItem @style_url = uri.merge('style.css').to_s end @style_url - end + end end diff --git a/lib/common/models/wp_theme/childtheme.rb b/lib/common/models/wp_theme/childtheme.rb new file mode 100644 index 00000000..3e0944e8 --- /dev/null +++ b/lib/common/models/wp_theme/childtheme.rb @@ -0,0 +1,33 @@ +# encoding: UTF-8 + +class WpTheme < WpItem + module Childtheme + + def is_child_theme? + return true unless @theme_template.nil? + false + end + + def get_parent_theme_style_url + if is_child_theme? + return style_url.sub("/#{name}/style.css", "/#@theme_template/style.css") + end + nil + end + + def get_parent_theme + if is_child_theme? + base_url = @uri.clone + base_url.path = base_url.path.sub(/(?.*\/)#{Regexp.escape(@wp_content_dir)}\/.+/, '\k') + return WpTheme.new(base_url, + { + name: @theme_template, + style_url: get_parent_theme_style_url, + wp_content_dir: @wp_content_dir + }) + end + nil + end + + end +end diff --git a/lib/common/models/wp_theme/info.rb b/lib/common/models/wp_theme/info.rb index 120c753c..370927da 100644 --- a/lib/common/models/wp_theme/info.rb +++ b/lib/common/models/wp_theme/info.rb @@ -1,34 +1,34 @@ # encoding: UTF-8 class WpTheme < WpItem - module Info + module Info - attr_reader :theme_name, :theme_uri, :theme_description, - :theme_author, :theme_author_uri, :theme_template, - :theme_license, :theme_license_uri, :theme_tags, - :theme_text_domain + attr_reader :theme_name, :theme_uri, :theme_description, + :theme_author, :theme_author_uri, :theme_template, + :theme_license, :theme_license_uri, :theme_tags, + :theme_text_domain - def parse_style - style = Browser.get(style_url).body - @theme_name = parse_style_tag(style, 'Theme Name') - @theme_uri = parse_style_tag(style, 'Theme URI') - @theme_description = parse_style_tag(style, 'Description') - @theme_author = parse_style_tag(style, 'Author') - @theme_author_uri = parse_style_tag(style, 'Author URI') - @theme_template = parse_style_tag(style, 'Template') - @theme_license = parse_style_tag(style, 'License') - @theme_license_uri = parse_style_tag(style, 'License URI') - @theme_tags = parse_style_tag(style, 'Tags') - @theme_text_domain = parse_style_tag(style, 'Text Domain') - end + def parse_style + style = Browser.get(style_url).body + @theme_name = parse_style_tag(style, 'Theme Name') + @theme_uri = parse_style_tag(style, 'Theme URI') + @theme_description = parse_style_tag(style, 'Description') + @theme_author = parse_style_tag(style, 'Author') + @theme_author_uri = parse_style_tag(style, 'Author URI') + @theme_template = parse_style_tag(style, 'Template') + @theme_license = parse_style_tag(style, 'License') + @theme_license_uri = parse_style_tag(style, 'License URI') + @theme_tags = parse_style_tag(style, 'Tags') + @theme_text_domain = parse_style_tag(style, 'Text Domain') + end - private + private - def parse_style_tag(style, tag) - value = style[/^\s*#{Regexp.escape(tag)}:\s*(.*)/i, 1] - return value.strip if value - nil - end + def parse_style_tag(style, tag) + value = style[/^\s*#{Regexp.escape(tag)}:\s*(.*)/i, 1] + return value.strip if value + nil + end - end + end end \ No newline at end of file diff --git a/lib/common/models/wp_theme/output.rb b/lib/common/models/wp_theme/output.rb index eecf9660..0f5937fa 100644 --- a/lib/common/models/wp_theme/output.rb +++ b/lib/common/models/wp_theme/output.rb @@ -1,21 +1,21 @@ # encoding: UTF-8 class WpTheme - module Output + module Output - # @return [ Void ] - def additional_output - puts " | Style URL: #{style_url}" - puts " | Theme Name: #@theme_name" if @theme_name - puts " | Theme URI: #@theme_uri" if @theme_uri - puts " | Description: #@theme_description" if @theme_description - puts " | Author: #@theme_author" if @theme_author - puts " | Author URI: #@theme_author_uri" if @theme_author_uri - puts " | Template: #@theme_template" if @theme_template - puts " | License: #@theme_license" if @theme_license_uri - puts " | Tags: #@theme_tags" if @theme_tags - puts " | Text Domain: #@theme_text_domain" if @theme_text_domain - end + # @return [ Void ] + def additional_output + puts " | Style URL: #{style_url}" + puts " | Theme Name: #@theme_name" if @theme_name + puts " | Theme URI: #@theme_uri" if @theme_uri + puts " | Description: #@theme_description" if @theme_description + puts " | Author: #@theme_author" if @theme_author + puts " | Author URI: #@theme_author_uri" if @theme_author_uri + puts " | Template: #@theme_template" if @theme_template + puts " | License: #@theme_license" if @theme_license_uri + puts " | Tags: #@theme_tags" if @theme_tags + puts " | Text Domain: #@theme_text_domain" if @theme_text_domain + end - end + end end diff --git a/wpscan.rb b/wpscan.rb index 5547535b..5477171c 100755 --- a/wpscan.rb +++ b/wpscan.rb @@ -194,6 +194,16 @@ def main # Theme version is handled in #to_s puts green('[+]') + " WordPress theme in use: #{wp_theme}" wp_theme.output + + # Check for parent Themes + while wp_theme.is_child_theme? + parent = wp_theme.get_parent_theme + puts + puts green('[+]') + " Detected parent theme: #{parent}" + parent.output + wp_theme = parent + end + end if wpscan_options.enumerate_plugins == nil and wpscan_options.enumerate_only_vulnerable_plugins == nil