diff --git a/lib/wpscan/modules/web_site.rb b/lib/wpscan/web_site.rb
similarity index 77%
rename from lib/wpscan/modules/web_site.rb
rename to lib/wpscan/web_site.rb
index 83411c39..d7b8f2fa 100644
--- a/lib/wpscan/modules/web_site.rb
+++ b/lib/wpscan/web_site.rb
@@ -17,7 +17,21 @@
# along with this program. If not, see .
#++
-module WebSite
+class WebSite
+
+ attr_reader :uri
+
+ def initialize(site_url)
+ self.url = site_url
+ end
+
+ def url=(url)
+ @uri = URI.parse(add_trailing_slash(add_http_protocol(url)))
+ end
+
+ def url
+ @uri.to_s
+ end
# Checks if the remote website is up.
def online?
@@ -28,40 +42,6 @@ module WebSite
Browser.instance.get(@uri.to_s).code == 401
end
- # check if the remote website is
- # actually running wordpress.
- def wordpress?
- wordpress = false
-
- response = Browser.instance.get(
- @uri.to_s,
- { follow_location: true, max_redirects: 2 }
- )
- if response.body =~ /["'][^"']*\/wp-content\/[^"']*["']/i
- wordpress = true
- else
- response = Browser.instance.get(
- xml_rpc_url,
- { follow_location: true, max_redirects: 2 }
- )
-
- if response.body =~ %r{XML-RPC server accepts POST requests only}i
- wordpress = true
- else
- response = Browser.instance.get(
- login_url(),
- { follow_location: true, max_redirects: 2 }
- )
-
- if response.body =~ %r{WordPress}i
- wordpress = true
- end
- end
- end
-
- wordpress
- end
-
def has_xml_rpc?
!xml_rpc_url.nil?
end
diff --git a/lib/wpscan/wp_target.rb b/lib/wpscan/wp_target.rb
index d37f226d..45bb5ab5 100644
--- a/lib/wpscan/wp_target.rb
+++ b/lib/wpscan/wp_target.rb
@@ -17,8 +17,7 @@
# along with this program. If not, see .
#++
-class WpTarget
- include WebSite
+class WpTarget < WebSite
include WpReadme
include WpFullPathDisclosure
include WpConfigBackup
@@ -30,10 +29,11 @@ class WpTarget
include WpThemes
include BruteForce
- attr_reader :uri, :verbose
+ attr_reader :verbose
def initialize(target_url, options = {})
- @uri = URI.parse(add_trailing_slash(add_http_protocol(target_url)))
+ super(target_url)
+
@verbose = options[:verbose]
@wp_content_dir = options[:wp_content_dir]
@wp_plugins_dir = options[:wp_plugins_dir]
@@ -42,9 +42,39 @@ class WpTarget
Browser.instance(options.merge(:max_threads => options[:threads]))
end
- # Alias of @uri.to_s
- def url
- @uri.to_s
+ # check if the target website is
+ # actually running wordpress.
+ def wordpress?
+ wordpress = false
+
+ response = Browser.instance.get(
+ @uri.to_s,
+ { follow_location: true, max_redirects: 2 }
+ )
+
+ if response.body =~ /["'][^"']*\/wp-content\/[^"']*["']/i
+ wordpress = true
+ else
+ response = Browser.instance.get(
+ xml_rpc_url,
+ { follow_location: true, max_redirects: 2 }
+ )
+
+ if response.body =~ %r{XML-RPC server accepts POST requests only}i
+ wordpress = true
+ else
+ response = Browser.instance.get(
+ login_url,
+ { follow_location: true, max_redirects: 2 }
+ )
+
+ if response.body =~ %r{WordPress}i
+ wordpress = true
+ end
+ end
+ end
+
+ wordpress
end
def login_url
diff --git a/spec/lib/wpscan/modules/wp_readme_spec.rb b/spec/lib/wpscan/modules/wp_readme_spec.rb
index 6a8ce7b9..0cec1fb1 100644
--- a/spec/lib/wpscan/modules/wp_readme_spec.rb
+++ b/spec/lib/wpscan/modules/wp_readme_spec.rb
@@ -28,7 +28,7 @@ shared_examples_for 'WpReadme' do
describe '#readme_url' do
it 'should return http://example.localhost/readme.html' do
- @module.readme_url.should === "#{@module.uri}/readme.html"
+ @module.readme_url.should === "#{@module.uri}readme.html"
end
end
diff --git a/spec/lib/wpscan/modules/web_site_spec.rb b/spec/lib/wpscan/web_site_spec.rb
similarity index 64%
rename from spec/lib/wpscan/modules/web_site_spec.rb
rename to spec/lib/wpscan/web_site_spec.rb
index 0171fd6c..67df2aca 100644
--- a/spec/lib/wpscan/modules/web_site_spec.rb
+++ b/spec/lib/wpscan/web_site_spec.rb
@@ -17,9 +17,34 @@
# along with this program. If not, see .
#++
-shared_examples_for 'WebSite' do
- let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_MODULES_DIR + '/web_site' }
- subject(:web_site) { WpScanModuleSpec.new('http://example.localhost/').extend(WebSite) }
+describe 'WebSite' do
+ let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WEB_SITE_DIR }
+ subject(:web_site) { WebSite.new('http://example.localhost/') }
+
+ describe "#new" do
+ its(:url) { should === 'http://example.localhost/' }
+ end
+
+ describe '#url=' do
+ after :each do
+ web_site.url = @uri
+ web_site.url.should === @expected
+ end
+
+ context 'when protocol or trailing slash is missing' do
+ it 'should add the them' do
+ @uri = 'example.localhost'
+ @expected = 'http://example.localhost/'
+ end
+ end
+
+ context 'when there is a protocol or a trailing slash' do
+ it 'should not add them' do
+ @uri = 'http://example.localhost/'
+ @expected = @uri
+ end
+ end
+ end
describe '#online?' do
it 'should not be considered online if the status code is 0' do
@@ -74,70 +99,6 @@ shared_examples_for 'WebSite' do
end
end
- describe '#wordpress?' do
- # each url (wp-login and xmlrpc) pointed to a 404
- before :each do
- stub_request(:get, web_site.url).
- to_return(status: 200, body: '', headers: { 'X-Pingback' => web_site.uri.merge('xmlrpc.php')})
-
- [web_site.login_url, web_site.xml_rpc_url].each do |url|
- stub_request(:get, url).to_return(status: 404, body: '')
- end
- end
-
- it 'should return false if both files are not found (404)' do
- web_site.should_not be_wordpress
- end
-
- it 'should return true if the wp-login is found and is a valid wordpress one' do
- stub_request(:get, web_site.login_url).
- to_return(status: 200, body: File.new(fixtures_dir + '/wp-login.php'))
-
- web_site.should be_wordpress
- end
-
- it 'should return true if the xmlrpc is found' do
- stub_request(:get, web_site.xml_rpc_url).
- to_return(status: 200, body: File.new(fixtures_dir + '/xmlrpc.php'))
-
- web_site.should be_wordpress
- end
- end
-
- describe '#redirection' do
- it 'should return nil if no redirection detected' do
- stub_request(:get, web_site.url).to_return(status: 200, body: '')
-
- web_site.redirection.should be_nil
- end
-
- [301, 302].each do |status_code|
- it "should return http://new-location.com if the status code is #{status_code}" do
- new_location = 'http://new-location.com'
-
- stub_request(:get, web_site.url).
- to_return(status: status_code, headers: { location: new_location })
-
- stub_request(:get, new_location).to_return(status: 200)
-
- web_site.redirection.should === 'http://new-location.com'
- end
- end
-
- context 'when multiple redirections' do
- it 'should return the last redirection' do
- first_redirection = 'www.redirection.com'
- last_redirection = 'redirection.com'
-
- stub_request(:get, web_site.url).to_return(status: 301, headers: { location: first_redirection })
- stub_request(:get, first_redirection).to_return(status: 302, headers: { location: last_redirection })
- stub_request(:get, last_redirection).to_return(status: 200)
-
- web_site.redirection.should === last_redirection
- end
- end
- end
-
describe '#page_hash' do
it 'should return the MD5 hash of the page' do
url = 'http://e.localhost/somepage.php'
@@ -196,4 +157,4 @@ shared_examples_for 'WebSite' do
web_site.has_robots?.should be_false
end
end
-end
\ No newline at end of file
+end
diff --git a/spec/lib/wpscan/wp_target_spec.rb b/spec/lib/wpscan/wp_target_spec.rb
index 5f69ac9d..b8ca609d 100644
--- a/spec/lib/wpscan/wp_target_spec.rb
+++ b/spec/lib/wpscan/wp_target_spec.rb
@@ -20,6 +20,7 @@
require File.expand_path(File.dirname(__FILE__) + '/wpscan_helper')
describe WpTarget do
+ let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_TARGET_DIR }
before :each do
Browser.reset
@@ -33,7 +34,6 @@ describe WpTarget do
@wp_target = WpTarget.new('http://example.localhost/', @options)
end
- it_should_behave_like 'WebSite'
it_should_behave_like 'WpReadme'
it_should_behave_like 'WpConfigBackup'
it_should_behave_like 'WpFullPathDisclosure'
@@ -50,20 +50,6 @@ describe WpTarget do
expect { WpTarget.new(nil) }.to raise_error
expect { Wptarget.new('') }.to raise_error
end
-
- it 'should add the http protocol if missing' do
- WpTarget.new('example.localhost/', @options).url.should === 'http://example.localhost/'
- end
-
- it 'should add the trailing slash to the url if missing' do
- WpTarget.new('lamp/wordpress', @options).url.should === 'http://lamp/wordpress/'
- end
- end
-
- describe '#url' do
- it 'should return the url of the target' do
- @wp_target.url.should === @wp_target.uri.to_s
- end
end
describe '#login_url' do
@@ -85,6 +71,73 @@ describe WpTarget do
end
end
+ describe '#wordpress?' do
+ # each url (wp-login and xmlrpc) pointed to a 404
+ before :each do
+ stub_request(:get, @wp_target.url).
+ to_return(status: 200, body: '', headers: { 'X-Pingback' => @wp_target.uri.merge('xmlrpc.php')})
+
+ # Preventing redirection check from login_url()
+ @wp_target.stub(redirection: nil)
+
+ [@wp_target.login_url, @wp_target.xml_rpc_url].each do |url|
+ stub_request(:get, url).to_return(status: 404, body: '')
+ end
+ end
+
+ it 'should return false if both files are not found (404)' do
+ @wp_target.should_not be_wordpress
+ end
+
+ it 'should return true if the wp-login is found and is a valid wordpress one' do
+ stub_request(:get, @wp_target.login_url).
+ to_return(status: 200, body: File.new(fixtures_dir + '/wp-login.php'))
+
+ @wp_target.should be_wordpress
+ end
+
+ it 'should return true if the xmlrpc is found' do
+ stub_request(:get, @wp_target.xml_rpc_url).
+ to_return(status: 200, body: File.new(fixtures_dir + '/xmlrpc.php'))
+
+ @wp_target.should be_wordpress
+ end
+ end
+
+ describe '#redirection' do
+ it 'should return nil if no redirection detected' do
+ stub_request(:get, @wp_target.url).to_return(status: 200, body: '')
+
+ @wp_target.redirection.should be_nil
+ end
+
+ [301, 302].each do |status_code|
+ it "should return http://new-location.com if the status code is #{status_code}" do
+ new_location = 'http://new-location.com'
+
+ stub_request(:get, @wp_target.url).
+ to_return(status: status_code, headers: { location: new_location })
+
+ stub_request(:get, new_location).to_return(status: 200)
+
+ @wp_target.redirection.should === 'http://new-location.com'
+ end
+ end
+
+ context 'when multiple redirections' do
+ it 'should return the last redirection' do
+ first_redirection = 'www.redirection.com'
+ last_redirection = 'redirection.com'
+
+ stub_request(:get, @wp_target.url).to_return(status: 301, headers: { location: first_redirection })
+ stub_request(:get, first_redirection).to_return(status: 302, headers: { location: last_redirection })
+ stub_request(:get, last_redirection).to_return(status: 200)
+
+ @wp_target.redirection.should === last_redirection
+ end
+ end
+ end
+
describe '#wp_content_dir' do
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_TARGET_DIR + '/wp_content_dir' }
diff --git a/spec/lib/wpscan/wpscan_helper.rb b/spec/lib/wpscan/wpscan_helper.rb
index 21c526b2..c5ea8c63 100644
--- a/spec/lib/wpscan/wpscan_helper.rb
+++ b/spec/lib/wpscan/wpscan_helper.rb
@@ -23,18 +23,22 @@ require WPSCAN_LIB_DIR + '/wpscan_helper'
SPEC_FIXTURES_WPSCAN_DIR = SPEC_FIXTURES_DIR + '/wpscan'
SPEC_FIXTURES_WPSCAN_MODULES_DIR = SPEC_FIXTURES_WPSCAN_DIR + '/modules'
+SPEC_FIXTURES_WPSCAN_WEB_SITE_DIR = SPEC_FIXTURES_WPSCAN_DIR + '/web_site'
SPEC_FIXTURES_WPSCAN_WP_TARGET_DIR = SPEC_FIXTURES_WPSCAN_DIR + '/wp_target'
SPEC_FIXTURES_WPSCAN_WPSCAN_OPTIONS_DIR = SPEC_FIXTURES_WPSCAN_DIR + '/wpscan_options'
SPEC_FIXTURES_WPSCAN_WP_THEME_DIR = SPEC_FIXTURES_WPSCAN_DIR + '/wp_theme'
SPEC_FIXTURES_WPSCAN_WP_PLUGIN_DIR = SPEC_FIXTURES_WPSCAN_DIR + '/wp_plugin'
SPEC_FIXTURES_WPSCAN_WP_VERSION_DIR = SPEC_FIXTURES_WPSCAN_DIR + '/wp_version'
+# This class is a HACK to simulate the WpTarget behavior in order
+# to be able to test the modules independently
class WpScanModuleSpec
attr_reader :uri
attr_accessor :error_404_hash, :homepage_hash, :wp_content_dir, :verbose
def initialize(target_url)
- @uri = URI.parse(add_http_protocol(target_url))
+ @uri = URI.parse(add_trailing_slash(add_http_protocol(target_url)))
+
Browser.instance(
config_file: SPEC_FIXTURES_CONF_DIR + '/browser/browser.conf.json',
cache_timeout: 0
diff --git a/spec/samples/wpscan/modules/web_site/rss_url/wordpress-3.5.htm b/spec/samples/wpscan/web_site/rss_url/wordpress-3.5.htm
similarity index 100%
rename from spec/samples/wpscan/modules/web_site/rss_url/wordpress-3.5.htm
rename to spec/samples/wpscan/web_site/rss_url/wordpress-3.5.htm
diff --git a/spec/samples/wpscan/modules/web_site/wp-login.php b/spec/samples/wpscan/wp_target/wp-login.php
similarity index 100%
rename from spec/samples/wpscan/modules/web_site/wp-login.php
rename to spec/samples/wpscan/wp_target/wp-login.php
diff --git a/spec/samples/wpscan/modules/web_site/xmlrpc.php b/spec/samples/wpscan/wp_target/xmlrpc.php
similarity index 100%
rename from spec/samples/wpscan/modules/web_site/xmlrpc.php
rename to spec/samples/wpscan/wp_target/xmlrpc.php