Adds a #maybe_add_cookies to handle website requiring a specific cookie

This commit is contained in:
erwanlr
2019-04-03 19:08:52 +01:00
parent 025ce37c05
commit 352286e497
5 changed files with 146 additions and 5 deletions

View File

@@ -52,13 +52,16 @@ module WPScan
def before_scan
@last_update = local_db.last_update
maybe_output_banner_help_and_version # From CMS Scanner
maybe_output_banner_help_and_version # From CMSScanner
update_db if update_db_required?
setup_cache
check_target_availability
load_server_module
check_wordpress_state
rescue Error::NotWordPress => e
target.maybe_add_cookies
raise e unless target.wordpress?(parsed_options[:detection_mode])
end
# Raises errors if the target is hosted on wordpress.com or is not running WordPress

View File

@@ -45,6 +45,34 @@ module WPScan
false
end
COOKIE_PATTERNS = {
'vjs' => /createCookie\('vjs','(?<c_value>\d+)',\d+\);/i
}.freeze
# Sometimes there is a mechanism in place on the blog, which requires a specific
# cookie and value to be added to requests. Lets try to detect and add them
def maybe_add_cookies
COOKIE_PATTERNS.each do |cookie_key, pattern|
next unless homepage_res.body =~ pattern
browser = Browser.instance
cookie_string = "#{cookie_key}=#{Regexp.last_match[:c_value]}"
cookie_string += "; #{browser.cookie_string}" if browser.cookie_string
browser.cookie_string = cookie_string
# Force recheck of the homepage when retying wordpress?
# No need to clear the cache, as the request (which will contain the cookies)
# will be different
@homepage_res = nil
@homepage_url = nil
break
end
end
# @return [ String ]
def registration_url
multisite? ? url('wp-signup.php') : url('wp-login.php?action=register')

View File

@@ -218,7 +218,7 @@ describe WPScan::Controller::Core do
context 'when not wordpress' do
it 'raises an error' do
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(false)
expect(core.target).to receive(:wordpress?).twice.with(:mixed).and_return(false)
expect { core.before_scan }.to raise_error(WPScan::Error::NotWordPress)
end
@@ -250,12 +250,26 @@ describe WPScan::Controller::Core do
context 'when not wordpress' do
before do
expect(core).to receive(:load_server_module)
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(false)
end
context 'when no --force' do
it 'raises an error' do
expect { core.before_scan }.to raise_error(WPScan::Error::NotWordPress)
before { expect(core.target).to receive(:maybe_add_cookies) }
context 'when no cookies added or still not wordpress after being added' do
it 'raises an error' do
expect(core.target).to receive(:wordpress?).twice.with(:mixed).and_return(false)
expect { core.before_scan }.to raise_error(WPScan::Error::NotWordPress)
end
end
context 'when the added cookies solved it' do
it 'does not raise an error' do
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(false).ordered
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(true).ordered
expect { core.before_scan }.to_not raise_error
end
end
end
@@ -263,6 +277,8 @@ describe WPScan::Controller::Core do
let(:cli_args) { "#{super()} --force" }
it 'does not raise any error' do
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(false)
expect { core.before_scan }.to_not raise_error
end
end

View File

@@ -0,0 +1,24 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="robots" content="noindex">
</head>
<body>
<script>
function createCookie(name,value,days) {
if (days) {
var date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
var expires = "; expires="+date.toGMTString();
}
else var expires = "";
document.cookie = name+"="+value+expires+"; path=/";
}
createCookie('vjs','2420671338',60);
</script><form id="repost" method="post" action=""></form>
<script>
if((document.cookie.indexOf('vjs=') !== -1))
location.reload();
</script>
<h1>Access to this website is possible only using browser with JavaScript and Cookies enabled.</h1>

View File

@@ -68,6 +68,76 @@ shared_examples WPScan::Target::Platform::WordPress do
end
end
describe '#maybe_add_cookies' do
let(:fixtures) { super().join('maybe_add_cookies') }
let(:browser) { WPScan::Browser.instance }
context 'when nothing matches' do
it 'does nothing' do
stub_request(:get, target.url).to_return(body: 'nothing there')
subject.maybe_add_cookies
expect(browser.cookie_string).to eql nil
expect(subject.homepage_res.body).to eql 'nothing there'
end
end
context 'when matches' do
before do
stub_request(:get, target.url)
.to_return(
{ body: File.read(fixtures.join("#{cookie}.html")) },
body: 'Cookies Accepted!' # if we put {} there, ruobop not happy!
)
end
{
'vjs' => 'vjs=2420671338'
}.each do |key, expected_cookie_string|
context "when #{key} match" do
let(:cookie) { key }
context 'when the browser does not have a cookie_string already' do
before do
subject.maybe_add_cookies
# This one does not work, opened an issue
# https://github.com/bblimke/webmock/issues/813
# stub_request(:get, target.url)
# .with(headers: { 'Cookie' => expected_cookie_string })
# .to_return(body: 'Cookies Accepted!')
end
it 'sets the correct cookies, reset the homepage_res' do
expect(browser.cookie_string).to eql expected_cookie_string
expect(subject.homepage_res.body).to eql 'Cookies Accepted!'
end
end
context 'when the browser has cookie_string already' do
before do
browser.cookie_string = 'key=no-override'
subject.maybe_add_cookies
# This one does not work, opened an issue
# https://github.com/bblimke/webmock/issues/813
# stub_request(:get, target.url)
# .with(headers: { 'Cookie' => "#{expected_cookie_string}; key=no-override" })
# .to_return(body: 'Cookies Accepted!')
end
it 'sets the correct cookies, reset the homepage_res' do
expect(browser.cookie_string).to eql "#{expected_cookie_string}; key=no-override"
expect(subject.homepage_res.body).to eql 'Cookies Accepted!'
end
end
end
end
end
end
describe '#wordpress_hosted?' do
its(:wordpress_hosted?) { should be false }