VulnAPI Implementation
This commit is contained in:
@@ -1,24 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
describe WPScan::Controller::ApiToken do
|
||||
subject(:controller) { described_class.new }
|
||||
let(:target_url) { 'http://ex.lo/' }
|
||||
let(:cli_args) { "--url #{target_url}" }
|
||||
|
||||
before do
|
||||
WPScan::ParsedCli.options = rspec_parsed_options(cli_args)
|
||||
end
|
||||
|
||||
describe '#cli_options' do
|
||||
its(:cli_options) { should_not be_empty }
|
||||
its(:cli_options) { should be_a Array }
|
||||
|
||||
it 'contains to correct options' do
|
||||
expect(controller.cli_options.map(&:to_sym)).to eq %i[api_token]
|
||||
end
|
||||
end
|
||||
|
||||
describe '#before_scan' do
|
||||
xit
|
||||
end
|
||||
end
|
||||
93
spec/app/controllers/vuln_api_spec.rb
Normal file
93
spec/app/controllers/vuln_api_spec.rb
Normal file
@@ -0,0 +1,93 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
describe WPScan::Controller::VulnApi do
|
||||
subject(:controller) { described_class.new }
|
||||
let(:target_url) { 'http://ex.lo/' }
|
||||
let(:cli_args) { "--url #{target_url}" }
|
||||
|
||||
before do
|
||||
WPScan::ParsedCli.options = rspec_parsed_options(cli_args)
|
||||
end
|
||||
|
||||
describe '#cli_options' do
|
||||
its(:cli_options) { should_not be_empty }
|
||||
its(:cli_options) { should be_a Array }
|
||||
|
||||
it 'contains to correct options' do
|
||||
expect(controller.cli_options.map(&:to_sym)).to eq %i[api_token]
|
||||
end
|
||||
end
|
||||
|
||||
describe '#before_scan' do
|
||||
context 'when no --api-token provided' do
|
||||
its(:before_scan) { should be nil }
|
||||
end
|
||||
|
||||
context 'when --api-token given' do
|
||||
let(:cli_args) { "#{super()} --api-token token" }
|
||||
|
||||
context 'when the token is invalid' do
|
||||
before { expect(WPScan::DB::VulnApi).to receive(:status).and_return('error' => 'HTTP Token: Access denied.') }
|
||||
|
||||
it 'raise an InvalidApiToken error' do
|
||||
expect { controller.before_scan }.to raise_error(WPScan::Error::InvalidApiToken)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the token is valid' do
|
||||
context 'when the limit has been reached' do
|
||||
before do
|
||||
expect(WPScan::DB::VulnApi)
|
||||
.to receive(:status)
|
||||
.and_return('success' => true, 'plan' => 'free', 'requests_remaining' => 0)
|
||||
end
|
||||
|
||||
it 'raises an ApiLimitReached error' do
|
||||
expect { controller.before_scan }.to raise_error(WPScan::Error::ApiLimitReached)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a HTTP error, like a timeout' do
|
||||
before do
|
||||
expect(WPScan::DB::VulnApi)
|
||||
.to receive(:status)
|
||||
.and_return(
|
||||
'http_error' => WPScan::Error::HTTP.new(
|
||||
Typhoeus::Response.new(effective_url: 'mock-url', return_code: 28)
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
it 'raises an HTTP error' do
|
||||
expect { controller.before_scan }
|
||||
.to raise_error(WPScan::Error::HTTP, 'HTTP Error: mock-url (Timeout was reached)')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the token is valid and no HTTP error' do
|
||||
before do
|
||||
expect(WPScan::DB::VulnApi)
|
||||
.to receive(:status)
|
||||
.and_return('success' => true, 'plan' => 'free', 'requests_remaining' => requests)
|
||||
end
|
||||
|
||||
context 'when limited requests' do
|
||||
let(:requests) { 100 }
|
||||
|
||||
it 'does not raise an error' do
|
||||
expect { controller.before_scan }.to_not raise_error
|
||||
end
|
||||
|
||||
context 'when unlimited requests' do
|
||||
let(:requests) { 'Unlimited' }
|
||||
|
||||
it 'does not raise an error' do
|
||||
expect { controller.before_scan }.to_not raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -81,24 +81,39 @@ describe WPScan::Model::Plugin do
|
||||
end
|
||||
|
||||
describe '#latest_version, #last_updated, #popular' do
|
||||
context 'when none' do
|
||||
let(:slug) { 'vulnerable-not-popular' }
|
||||
before { allow(plugin).to receive(:db_data).and_return(db_data) }
|
||||
|
||||
context 'when no db_data and no metadata' do
|
||||
let(:slug) { 'not-known' }
|
||||
let(:db_data) { {} }
|
||||
|
||||
its(:latest_version) { should be_nil }
|
||||
its(:last_updated) { should be_nil }
|
||||
its(:popular?) { should be false }
|
||||
end
|
||||
|
||||
context 'when values' do
|
||||
context 'when no db_data but metadata' do
|
||||
let(:slug) { 'no-vulns-popular' }
|
||||
let(:db_data) { {} }
|
||||
|
||||
its(:latest_version) { should eql WPScan::Model::Version.new('2.0') }
|
||||
its(:last_updated) { should eql '2015-05-16T00:00:00.000Z' }
|
||||
its(:popular?) { should be true }
|
||||
end
|
||||
|
||||
context 'when db_data' do
|
||||
let(:slug) { 'no-vulns-popular' }
|
||||
let(:db_data) { vuln_api_data_for('plugins/no-vulns-popular') }
|
||||
|
||||
its(:latest_version) { should eql WPScan::Model::Version.new('2.1') }
|
||||
its(:last_updated) { should eql '2015-05-16T00:00:00.000Z-via-api' }
|
||||
its(:popular?) { should be true }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#outdated?' do
|
||||
before { allow(plugin).to receive(:db_data).and_return({}) }
|
||||
|
||||
context 'when last_version' do
|
||||
let(:slug) { 'no-vulns-popular' }
|
||||
|
||||
@@ -116,13 +131,13 @@ describe WPScan::Model::Plugin do
|
||||
.and_return(WPScan::Model::Version.new(version_number))
|
||||
end
|
||||
|
||||
context 'when version < last_version' do
|
||||
context 'when version < latest_version' do
|
||||
let(:version_number) { '1.2' }
|
||||
|
||||
its(:outdated?) { should eql true }
|
||||
end
|
||||
|
||||
context 'when version >= last_version' do
|
||||
context 'when version >= latest_version' do
|
||||
let(:version_number) { '3.0' }
|
||||
|
||||
its(:outdated?) { should eql false }
|
||||
@@ -130,7 +145,7 @@ describe WPScan::Model::Plugin do
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no last_version' do
|
||||
context 'when no latest_version' do
|
||||
let(:slug) { 'vulnerable-not-popular' }
|
||||
|
||||
context 'when no version' do
|
||||
@@ -153,13 +168,16 @@ describe WPScan::Model::Plugin do
|
||||
end
|
||||
|
||||
describe '#vulnerabilities' do
|
||||
before { allow(plugin).to receive(:db_data).and_return(db_data) }
|
||||
|
||||
after do
|
||||
expect(plugin.vulnerabilities).to eq @expected
|
||||
expect(plugin.vulnerable?).to eql @expected.empty? ? false : true
|
||||
end
|
||||
|
||||
context 'when plugin not in the DB' do
|
||||
let(:slug) { 'not-in-db' }
|
||||
let(:slug) { 'not-in-db' }
|
||||
let(:db_data) { {} }
|
||||
|
||||
it 'returns an empty array' do
|
||||
@expected = []
|
||||
@@ -168,7 +186,8 @@ describe WPScan::Model::Plugin do
|
||||
|
||||
context 'when in the DB' do
|
||||
context 'when no vulnerabilities' do
|
||||
let(:slug) { 'no-vulns-popular' }
|
||||
let(:slug) { 'no-vulns-popular' }
|
||||
let(:db_data) { vuln_api_data_for('plugins/no-vulns-popular') }
|
||||
|
||||
it 'returns an empty array' do
|
||||
@expected = []
|
||||
@@ -176,11 +195,13 @@ describe WPScan::Model::Plugin do
|
||||
end
|
||||
|
||||
context 'when vulnerabilities' do
|
||||
let(:slug) { 'vulnerable-not-popular' }
|
||||
let(:slug) { 'vulnerable-not-popular' }
|
||||
let(:db_data) { vuln_api_data_for('plugins/vulnerable-not-popular') }
|
||||
|
||||
let(:all_vulns) do
|
||||
[
|
||||
WPScan::Vulnerability.new(
|
||||
'First Vuln',
|
||||
'First Vuln <= 6.3.10 - LFI',
|
||||
{ wpvulndb: '1' },
|
||||
'LFI',
|
||||
'6.3.10'
|
||||
|
||||
@@ -86,8 +86,179 @@ describe WPScan::Model::Theme do
|
||||
end
|
||||
end
|
||||
|
||||
describe '#latest_version, #last_updated, #popular' do
|
||||
before do
|
||||
stub_request(:get, /.*\.css\z/)
|
||||
allow(theme).to receive(:db_data).and_return(db_data)
|
||||
end
|
||||
|
||||
context 'when no db_data and no metadata' do
|
||||
let(:slug) { 'not-known' }
|
||||
let(:db_data) { {} }
|
||||
|
||||
its(:latest_version) { should be_nil }
|
||||
its(:last_updated) { should be_nil }
|
||||
its(:popular?) { should be false }
|
||||
end
|
||||
|
||||
context 'when no db_data but metadata' do
|
||||
let(:slug) { 'no-vulns-popular' }
|
||||
let(:db_data) { {} }
|
||||
|
||||
its(:latest_version) { should eql WPScan::Model::Version.new('2.0') }
|
||||
its(:last_updated) { should eql '2015-05-16T00:00:00.000Z' }
|
||||
its(:popular?) { should be true }
|
||||
end
|
||||
|
||||
context 'when db_data' do
|
||||
let(:slug) { 'no-vulns-popular' }
|
||||
let(:db_data) { vuln_api_data_for('themes/no-vulns-popular') }
|
||||
|
||||
its(:latest_version) { should eql WPScan::Model::Version.new('2.2') }
|
||||
its(:last_updated) { should eql '2015-05-16T00:00:00.000Z-via-api' }
|
||||
its(:popular?) { should be true }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#outdated?' do
|
||||
before do
|
||||
stub_request(:get, /.*\.css\z/)
|
||||
allow(theme).to receive(:db_data).and_return({})
|
||||
end
|
||||
|
||||
context 'when last_version' do
|
||||
let(:slug) { 'no-vulns-popular' }
|
||||
|
||||
context 'when no version' do
|
||||
before { expect(theme).to receive(:version).at_least(1).and_return(nil) }
|
||||
|
||||
its(:outdated?) { should eql false }
|
||||
end
|
||||
|
||||
context 'when version' do
|
||||
before do
|
||||
expect(theme)
|
||||
.to receive(:version)
|
||||
.at_least(1)
|
||||
.and_return(WPScan::Model::Version.new(version_number))
|
||||
end
|
||||
|
||||
context 'when version < latest_version' do
|
||||
let(:version_number) { '1.2' }
|
||||
|
||||
its(:outdated?) { should eql true }
|
||||
end
|
||||
|
||||
context 'when version >= latest_version' do
|
||||
let(:version_number) { '3.0' }
|
||||
|
||||
its(:outdated?) { should eql false }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no latest_version' do
|
||||
let(:slug) { 'vulnerable-not-popular' }
|
||||
|
||||
context 'when no version' do
|
||||
before { expect(theme).to receive(:version).at_least(1).and_return(nil) }
|
||||
|
||||
its(:outdated?) { should eql false }
|
||||
end
|
||||
|
||||
context 'when version' do
|
||||
before do
|
||||
expect(theme)
|
||||
.to receive(:version)
|
||||
.at_least(1)
|
||||
.and_return(WPScan::Model::Version.new('1.0'))
|
||||
end
|
||||
|
||||
its(:outdated?) { should eql false }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#vulnerabilities' do
|
||||
xit
|
||||
before do
|
||||
stub_request(:get, /.*\.css\z/)
|
||||
allow(theme).to receive(:db_data).and_return(db_data)
|
||||
end
|
||||
|
||||
after do
|
||||
expect(theme.vulnerabilities).to eq @expected
|
||||
expect(theme.vulnerable?).to eql @expected.empty? ? false : true
|
||||
end
|
||||
|
||||
context 'when theme not in the DB' do
|
||||
let(:slug) { 'not-in-db' }
|
||||
let(:db_data) { {} }
|
||||
|
||||
it 'returns an empty array' do
|
||||
@expected = []
|
||||
end
|
||||
end
|
||||
|
||||
context 'when in the DB' do
|
||||
context 'when no vulnerabilities' do
|
||||
let(:slug) { 'no-vulns-popular' }
|
||||
let(:db_data) { vuln_api_data_for('themes/no-vulns-popular') }
|
||||
|
||||
it 'returns an empty array' do
|
||||
@expected = []
|
||||
end
|
||||
end
|
||||
|
||||
context 'when vulnerabilities' do
|
||||
let(:slug) { 'vulnerable-not-popular' }
|
||||
let(:db_data) { vuln_api_data_for('themes/vulnerable-not-popular') }
|
||||
|
||||
let(:all_vulns) do
|
||||
[
|
||||
WPScan::Vulnerability.new(
|
||||
'First Vuln',
|
||||
{ wpvulndb: '1' },
|
||||
'LFI',
|
||||
'6.3.10'
|
||||
),
|
||||
WPScan::Vulnerability.new('No Fixed In', wpvulndb: '2')
|
||||
]
|
||||
end
|
||||
|
||||
context 'when no theme version' do
|
||||
before { expect(theme).to receive(:version).at_least(1).and_return(false) }
|
||||
|
||||
it 'returns all the vulnerabilities' do
|
||||
@expected = all_vulns
|
||||
end
|
||||
end
|
||||
|
||||
context 'when theme version' do
|
||||
before do
|
||||
expect(theme)
|
||||
.to receive(:version)
|
||||
.at_least(1)
|
||||
.and_return(WPScan::Model::Version.new(number))
|
||||
end
|
||||
|
||||
context 'when < to a fixed_in' do
|
||||
let(:number) { '5.0' }
|
||||
|
||||
it 'returns it' do
|
||||
@expected = all_vulns
|
||||
end
|
||||
end
|
||||
|
||||
context 'when >= to a fixed_in' do
|
||||
let(:number) { '6.3.10' }
|
||||
|
||||
it 'does not return it ' do
|
||||
@expected = [all_vulns.last]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#parent_theme' do
|
||||
|
||||
@@ -40,11 +40,13 @@ describe WPScan::Model::WpVersion do
|
||||
|
||||
describe '#vulnerabilities' do
|
||||
subject(:version) { described_class.new(number) }
|
||||
before { allow(version).to receive(:db_data).and_return(db_data) }
|
||||
|
||||
context 'when no vulns' do
|
||||
let(:number) { '4.4' }
|
||||
let(:db_data) { { 'vulnerabilities' => [] } }
|
||||
|
||||
its(:vulnerabilities) { should eql([]) }
|
||||
its(:vulnerabilities) { should be_empty }
|
||||
end
|
||||
|
||||
context 'when vulnerable' do
|
||||
@@ -53,8 +55,25 @@ describe WPScan::Model::WpVersion do
|
||||
expect(version).to be_vulnerable
|
||||
end
|
||||
|
||||
let(:all_vulns) do
|
||||
[
|
||||
WPScan::Vulnerability.new(
|
||||
'WP 3.8.1 - Vuln 1',
|
||||
{ wpvulndb: '1' },
|
||||
'SQLI'
|
||||
),
|
||||
WPScan::Vulnerability.new(
|
||||
'WP 3.8.1 - Vuln 2',
|
||||
{ url: %w[url-2 url-3], osvdb: %w[10], cve: %w[2014-0166], wpvulndb: '2' },
|
||||
nil,
|
||||
'3.8.2'
|
||||
)
|
||||
]
|
||||
end
|
||||
|
||||
context 'when a signle vuln' do
|
||||
let(:number) { '3.8' }
|
||||
let(:number) { '3.8.1' }
|
||||
let(:db_data) { vuln_api_data_for('wordpresses/38') }
|
||||
|
||||
it 'returns the expected result' do
|
||||
@expected = [WPScan::Vulnerability.new(
|
||||
@@ -67,6 +86,7 @@ describe WPScan::Model::WpVersion do
|
||||
|
||||
context 'when multiple vulns' do
|
||||
let(:number) { '3.8.1' }
|
||||
let(:db_data) { vuln_api_data_for('wordpresses/381') }
|
||||
|
||||
it 'returns the expected results' do
|
||||
@expected = [
|
||||
@@ -87,27 +107,30 @@ describe WPScan::Model::WpVersion do
|
||||
end
|
||||
end
|
||||
|
||||
describe '#release_date' do
|
||||
describe '#metadata, #release_date, #status' do
|
||||
subject(:version) { described_class.new('3.8.1') }
|
||||
|
||||
its(:release_date) { should eql '2014-01-23' }
|
||||
before { allow(version).to receive(:db_data).and_return(db_data) }
|
||||
|
||||
context 'when the version is not in the DB' do
|
||||
subject(:version) { described_class.new('3.8.2') }
|
||||
context 'when no db_data' do
|
||||
let(:db_data) { {} }
|
||||
|
||||
its(:release_date) { should eql 'Unknown' }
|
||||
its(:release_date) { should eql '2014-01-23' }
|
||||
its(:status) { should eql 'outdated' }
|
||||
|
||||
context 'when the version is not in the metadata' do
|
||||
subject(:version) { described_class.new('3.8.2') }
|
||||
|
||||
its(:release_date) { should eql 'Unknown' }
|
||||
its(:status) { should eql 'Unknown' }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#status' do
|
||||
subject(:version) { described_class.new('3.8.1') }
|
||||
context 'when db_data' do
|
||||
let(:db_data) { vuln_api_data_for('wordpresses/381') }
|
||||
|
||||
its(:status) { should eql 'outdated' }
|
||||
|
||||
context 'when the version is not in the DB' do
|
||||
subject(:version) { described_class.new('3.8.2') }
|
||||
|
||||
its(:release_date) { should eql 'Unknown' }
|
||||
its(:release_date) { should eql '2014-01-23-via-api' }
|
||||
its(:status) { should eql 'outdated-via-api' }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,6 +9,7 @@ describe 'App::Views' do
|
||||
# in the expected output.
|
||||
%i[JSON CliNoColour].each do |formatter|
|
||||
context "when #{formatter}" do
|
||||
it_behaves_like 'App::Views::VulnApi'
|
||||
it_behaves_like 'App::Views::WpVersion'
|
||||
it_behaves_like 'App::Views::MainTheme'
|
||||
it_behaves_like 'App::Views::Enumeration'
|
||||
|
||||
6
spec/fixtures/db/metadata.json
vendored
6
spec/fixtures/db/metadata.json
vendored
@@ -34,6 +34,12 @@
|
||||
"last_updated": "2015-05-16T00:00:00.000Z",
|
||||
"vulnerabilities": false
|
||||
},
|
||||
"vulnerable-not-popular": {
|
||||
"latest_version": null,
|
||||
"last_updated": null,
|
||||
"popular": false,
|
||||
"vulnerabilities": true
|
||||
},
|
||||
"dignitas-themes": {
|
||||
"popular": true,
|
||||
"latest_version": null,
|
||||
|
||||
25
spec/fixtures/db/plugins.json
vendored
25
spec/fixtures/db/plugins.json
vendored
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"no-vulns-popular": {
|
||||
"vulnerabilities": [],
|
||||
"popular": true,
|
||||
"latest_version": "2.0",
|
||||
"last_updated": "2015-05-16T00:00:00.000Z"
|
||||
},
|
||||
"vulnerable-not-popular": {
|
||||
"latest_version": null,
|
||||
"last_updated": null,
|
||||
"popular": false,
|
||||
"vulnerabilities" : [
|
||||
{
|
||||
"title" : "First Vuln",
|
||||
"fixed_in" : "6.3.10",
|
||||
"id" : 1,
|
||||
"vuln_type": "LFI"
|
||||
},
|
||||
{
|
||||
"title": "No Fixed In",
|
||||
"id": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
48
spec/fixtures/db/themes.json
vendored
48
spec/fixtures/db/themes.json
vendored
@@ -1,48 +0,0 @@
|
||||
{
|
||||
"no-vulns-popular": {
|
||||
"popular": true,
|
||||
"latest_version": "2.0",
|
||||
"last_updated": "2015-05-16T00:00:00.000Z",
|
||||
"vulnerabilities": []
|
||||
},
|
||||
"dignitas-themes": {
|
||||
"popular": true,
|
||||
"latest_version": null,
|
||||
"last_updated": null,
|
||||
"vulnerabilities" : [
|
||||
{
|
||||
"created_at" : "2015-03-05T19:25:59.000Z",
|
||||
"updated_at" : "2015-03-05T19:37:47.000Z",
|
||||
"references": {
|
||||
"url" : [
|
||||
"http://research.evex.pw/?vuln=6",
|
||||
"http://packetstormsecurity.com/files/130652/"
|
||||
]
|
||||
},
|
||||
"title" : "Dignitas 1.1.9 - Privilage Escalation",
|
||||
"id" : 7825,
|
||||
"vuln_type" : "AUTHBYPASS"
|
||||
}
|
||||
]
|
||||
},
|
||||
"yaaburnee-themes": {
|
||||
"popular": false,
|
||||
"latest_version": null,
|
||||
"last_updated": null,
|
||||
"vulnerabilities" : [
|
||||
{
|
||||
"created_at" : "2015-03-05T19:25:44.000Z",
|
||||
"updated_at" : "2015-03-05T19:41:14.000Z",
|
||||
"references": {
|
||||
"url" : [
|
||||
"http://research.evex.pw/?vuln=6",
|
||||
"http://packetstormsecurity.com/files/130652/"
|
||||
]
|
||||
},
|
||||
"title" : "Ya'aburnee 1.0.7 - Privilage Escalation",
|
||||
"id" : 7824,
|
||||
"vuln_type" : "AUTHBYPASS"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
6
spec/fixtures/db/vuln_api/plugins/no-vulns-popular.json
vendored
Normal file
6
spec/fixtures/db/vuln_api/plugins/no-vulns-popular.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"vulnerabilities": [],
|
||||
"popular": true,
|
||||
"latest_version": "2.1",
|
||||
"last_updated": "2015-05-16T00:00:00.000Z-via-api"
|
||||
}
|
||||
17
spec/fixtures/db/vuln_api/plugins/vulnerable-not-popular.json
vendored
Normal file
17
spec/fixtures/db/vuln_api/plugins/vulnerable-not-popular.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"latest_version": null,
|
||||
"last_updated": null,
|
||||
"popular": false,
|
||||
"vulnerabilities" : [
|
||||
{
|
||||
"title" : "First Vuln \u003c= 6.3.10 - LFI",
|
||||
"fixed_in" : "6.3.10",
|
||||
"id" : 1,
|
||||
"vuln_type": "LFI"
|
||||
},
|
||||
{
|
||||
"title": "No Fixed In",
|
||||
"id": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
20
spec/fixtures/db/vuln_api/themes/dignitas-themes.json
vendored
Normal file
20
spec/fixtures/db/vuln_api/themes/dignitas-themes.json
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"popular": true,
|
||||
"latest_version": null,
|
||||
"last_updated": null,
|
||||
"vulnerabilities" : [
|
||||
{
|
||||
"created_at" : "2015-03-05T19:25:59.000Z",
|
||||
"updated_at" : "2015-03-05T19:37:47.000Z",
|
||||
"references": {
|
||||
"url" : [
|
||||
"http://research.evex.pw/?vuln=6",
|
||||
"http://packetstormsecurity.com/files/130652/"
|
||||
]
|
||||
},
|
||||
"title" : "Dignitas 1.1.9 - Privilage Escalation",
|
||||
"id" : 7825,
|
||||
"vuln_type" : "AUTHBYPASS"
|
||||
}
|
||||
]
|
||||
}
|
||||
6
spec/fixtures/db/vuln_api/themes/no-vulns-popular.json
vendored
Normal file
6
spec/fixtures/db/vuln_api/themes/no-vulns-popular.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"popular": true,
|
||||
"latest_version": "2.2",
|
||||
"last_updated": "2015-05-16T00:00:00.000Z-via-api",
|
||||
"vulnerabilities": []
|
||||
}
|
||||
17
spec/fixtures/db/vuln_api/themes/vulnerable-not-popular.json
vendored
Normal file
17
spec/fixtures/db/vuln_api/themes/vulnerable-not-popular.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"latest_version": null,
|
||||
"last_updated": null,
|
||||
"popular": false,
|
||||
"vulnerabilities" : [
|
||||
{
|
||||
"title" : "First Vuln",
|
||||
"fixed_in" : "6.3.10",
|
||||
"id" : 1,
|
||||
"vuln_type": "LFI"
|
||||
},
|
||||
{
|
||||
"title": "No Fixed In",
|
||||
"id": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
20
spec/fixtures/db/vuln_api/themes/yaaburnee-themes.json
vendored
Normal file
20
spec/fixtures/db/vuln_api/themes/yaaburnee-themes.json
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"popular": false,
|
||||
"latest_version": null,
|
||||
"last_updated": null,
|
||||
"vulnerabilities" : [
|
||||
{
|
||||
"created_at" : "2015-03-05T19:25:44.000Z",
|
||||
"updated_at" : "2015-03-05T19:41:14.000Z",
|
||||
"references": {
|
||||
"url" : [
|
||||
"http://research.evex.pw/?vuln=6",
|
||||
"http://packetstormsecurity.com/files/130652/"
|
||||
]
|
||||
},
|
||||
"title" : "Ya'aburnee 1.0.7 - Privilage Escalation",
|
||||
"id" : 7824,
|
||||
"vuln_type" : "AUTHBYPASS"
|
||||
}
|
||||
]
|
||||
}
|
||||
17
spec/fixtures/db/vuln_api/wordpresses/38.json
vendored
Normal file
17
spec/fixtures/db/vuln_api/wordpresses/38.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"release_date" : "2013-12-12",
|
||||
"status": "insecure",
|
||||
"vulnerabilities" : [
|
||||
{
|
||||
"references": {
|
||||
"url" : ["url-4"],
|
||||
"osvdb" : ["11"]
|
||||
},
|
||||
"created_at" : "2014-08-01T10:58:19.000Z",
|
||||
"updated_at" : "2014-09-16T15:45:26.000Z",
|
||||
"title" : "WP 3.8 - Vuln 1",
|
||||
"id" : 3,
|
||||
"vuln_type" : "AUTHBYPASS"
|
||||
}
|
||||
]
|
||||
}
|
||||
27
spec/fixtures/db/vuln_api/wordpresses/381.json
vendored
Normal file
27
spec/fixtures/db/vuln_api/wordpresses/381.json
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"release_date" : "2014-01-23-via-api",
|
||||
"status": "outdated-via-api",
|
||||
"vulnerabilities" : [
|
||||
{
|
||||
"created_at" : "2014-08-01T10:58:19.000Z",
|
||||
"updated_at" : "2014-09-16T13:52:17.000Z",
|
||||
"title" : "WP 3.8.1 - Vuln 1",
|
||||
"id" : 1,
|
||||
"vuln_type" : "SQLI",
|
||||
"published_date" : null,
|
||||
"fixed_in" : null
|
||||
},
|
||||
{
|
||||
"references" : {
|
||||
"cve" : ["2014-0166"],
|
||||
"osvdb" : ["10"],
|
||||
"url" : ["url-2","url-3"]
|
||||
},
|
||||
"fixed_in" : "3.8.2",
|
||||
"created_at" : "2014-08-01T10:58:19.000Z",
|
||||
"updated_at" : "2014-09-16T13:53:11.000Z",
|
||||
"id" : 2,
|
||||
"title" : "WP 3.8.1 - Vuln 2"
|
||||
}
|
||||
]
|
||||
}
|
||||
4
spec/fixtures/db/vuln_api/wordpresses/40.json
vendored
Normal file
4
spec/fixtures/db/vuln_api/wordpresses/40.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"release_date" : "2014-09-04",
|
||||
"status": "latest"
|
||||
}
|
||||
50
spec/fixtures/db/wordpresses.json
vendored
50
spec/fixtures/db/wordpresses.json
vendored
@@ -1,50 +0,0 @@
|
||||
{
|
||||
"4.0": {
|
||||
"release_date" : "2014-09-04",
|
||||
"status": "latest"
|
||||
},
|
||||
"3.8.1": {
|
||||
"release_date" : "2014-01-23",
|
||||
"status": "outdated",
|
||||
"vulnerabilities" : [
|
||||
{
|
||||
"created_at" : "2014-08-01T10:58:19.000Z",
|
||||
"updated_at" : "2014-09-16T13:52:17.000Z",
|
||||
"title" : "WP 3.8.1 - Vuln 1",
|
||||
"id" : 1,
|
||||
"vuln_type" : "SQLI",
|
||||
"published_date" : null,
|
||||
"fixed_in" : null
|
||||
},
|
||||
{
|
||||
"references" : {
|
||||
"cve" : ["2014-0166"],
|
||||
"osvdb" : ["10"],
|
||||
"url" : ["url-2","url-3"]
|
||||
},
|
||||
"fixed_in" : "3.8.2",
|
||||
"created_at" : "2014-08-01T10:58:19.000Z",
|
||||
"updated_at" : "2014-09-16T13:53:11.000Z",
|
||||
"id" : 2,
|
||||
"title" : "WP 3.8.1 - Vuln 2"
|
||||
}
|
||||
]
|
||||
},
|
||||
"3.8": {
|
||||
"release_date" : "2013-12-12",
|
||||
"status": "insecure",
|
||||
"vulnerabilities" : [
|
||||
{
|
||||
"references": {
|
||||
"url" : ["url-4"],
|
||||
"osvdb" : ["11"]
|
||||
},
|
||||
"created_at" : "2014-08-01T10:58:19.000Z",
|
||||
"updated_at" : "2014-09-16T15:45:26.000Z",
|
||||
"title" : "WP 3.8 - Vuln 1",
|
||||
"id" : 3,
|
||||
"vuln_type" : "AUTHBYPASS"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ describe WPScan::DB::Themes do
|
||||
subject(:themes) { described_class }
|
||||
|
||||
describe '#all_slugs' do
|
||||
its(:all_slugs) { should eql %w[no-vulns-popular dignitas-themes yaaburnee-themes] }
|
||||
its(:all_slugs) { should eql %w[no-vulns-popular vulnerable-not-popular dignitas-themes yaaburnee-themes] }
|
||||
end
|
||||
|
||||
describe '#popular_slugs' do
|
||||
@@ -12,6 +12,6 @@ describe WPScan::DB::Themes do
|
||||
end
|
||||
|
||||
describe '#vulnerable_slugs' do
|
||||
its(:vulnerable_slugs) { should eql %w[dignitas-themes yaaburnee-themes] }
|
||||
its(:vulnerable_slugs) { should eql %w[vulnerable-not-popular dignitas-themes yaaburnee-themes] }
|
||||
end
|
||||
end
|
||||
|
||||
281
spec/lib/db/vuln_api_spec.rb
Normal file
281
spec/lib/db/vuln_api_spec.rb
Normal file
@@ -0,0 +1,281 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
describe WPScan::DB::VulnApi do
|
||||
subject(:api) { described_class }
|
||||
|
||||
describe '#uri' do
|
||||
its(:uri) { should be_a Addressable::URI }
|
||||
end
|
||||
|
||||
describe '#token, @token=' do
|
||||
context 'when no token set' do
|
||||
before { api.token = nil } # In case it was set by a previous spec
|
||||
|
||||
its(:token) { should be nil }
|
||||
end
|
||||
|
||||
context 'when token set' do
|
||||
it 'returns it' do
|
||||
api.token = 's3cRet'
|
||||
|
||||
expect(api.token).to eql 's3cRet'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#get' do
|
||||
context 'when no token' do
|
||||
before { api.token = nil }
|
||||
|
||||
it 'returns an empty hash' do
|
||||
expect(api.get('test')).to eql({})
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a token' do
|
||||
before { api.token = 's3cRet' }
|
||||
|
||||
context 'when no timeouts' do
|
||||
before do
|
||||
stub_request(:get, api.uri.join('path'))
|
||||
.with(headers: { 'Host' => api.uri.host, 'Expect' => nil, 'Referer' => nil,
|
||||
'User-Agent' => WPScan::Browser.instance.default_user_agent,
|
||||
'Authorization' => 'Token token=s3cRet' })
|
||||
.to_return(status: code, body: body)
|
||||
end
|
||||
|
||||
context 'when 200' do
|
||||
let(:code) { 200 }
|
||||
let(:body) { { data: 'something' }.to_json }
|
||||
|
||||
it 'returns the expected hash' do
|
||||
result = api.get('path')
|
||||
|
||||
expect(result).to eql('data' => 'something')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when 401' do
|
||||
let(:code) { 401 }
|
||||
let(:body) { { error: 'HTTP Token: Access denied.' }.to_json }
|
||||
|
||||
it 'returns the expected hash' do
|
||||
result = api.get('path')
|
||||
|
||||
expect(result).to eql('error' => 'HTTP Token: Access denied.')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when 404' do
|
||||
let(:code) { 404 }
|
||||
let(:body) { { error: 'Not found' }.to_json }
|
||||
|
||||
it 'returns an empty hash' do
|
||||
result = api.get('path')
|
||||
|
||||
expect(result).to eql('error' => 'Not found')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when timeouts' do
|
||||
context 'when all requests timeout' do
|
||||
before do
|
||||
stub_request(:get, api.uri.join('path'))
|
||||
.with(headers: { 'Host' => api.uri.host, 'Expect' => nil, 'Referer' => nil,
|
||||
'User-Agent' => WPScan::Browser.instance.default_user_agent,
|
||||
'Authorization' => 'Token token=s3cRet' })
|
||||
.to_return(status: 0)
|
||||
end
|
||||
|
||||
it 'tries 3 times and returns the hash with the error' do
|
||||
expect(api).to receive(:sleep).with(1).exactly(3).times
|
||||
|
||||
result = api.get('path')
|
||||
|
||||
expect(result['http_error']).to be_a WPScan::Error::HTTP
|
||||
end
|
||||
end
|
||||
|
||||
context 'when only the first request timeout' do
|
||||
before do
|
||||
stub_request(:get, api.uri.join('path'))
|
||||
.with(headers: { 'Host' => api.uri.host, 'Expect' => nil, 'Referer' => nil,
|
||||
'User-Agent' => WPScan::Browser.instance.default_user_agent,
|
||||
'Authorization' => 'Token token=s3cRet' })
|
||||
.to_return(status: 0).then
|
||||
.to_return(status: 200, body: { data: 'test' }.to_json)
|
||||
end
|
||||
|
||||
it 'tries 1 time and returns expected data' do
|
||||
expect(api).to receive(:sleep).with(1).exactly(1).times
|
||||
|
||||
result = api.get('path')
|
||||
|
||||
expect(result).to eql('data' => 'test')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#plugin_data' do
|
||||
before { api.token = api_token }
|
||||
|
||||
context 'when no --api-token' do
|
||||
let(:api_token) { nil }
|
||||
|
||||
it 'returns an empty hash' do
|
||||
expect(api.plugin_data('slug')).to eql({})
|
||||
end
|
||||
end
|
||||
|
||||
context 'when valid --api-token' do
|
||||
let(:api_token) { 's3cRet' }
|
||||
|
||||
context 'when the slug exist' do
|
||||
it 'calls the correct URL' do
|
||||
stub_request(:get, api.uri.join('plugins/slug'))
|
||||
.to_return(status: 200, body: { slug: { p: 'aa' } }.to_json)
|
||||
|
||||
expect(api.plugin_data('slug')).to eql('p' => 'aa')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the slug does not exist' do
|
||||
it 'returns an empty hash' do
|
||||
stub_request(:get, api.uri.join('plugins/slug-404')).to_return(status: 404, body: '{}')
|
||||
|
||||
expect(api.plugin_data('slug-404')).to eql({})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#theme_data' do
|
||||
before { api.token = api_token }
|
||||
|
||||
context 'when no --api-token' do
|
||||
let(:api_token) { nil }
|
||||
|
||||
it 'returns an empty hash' do
|
||||
expect(api.theme_data('slug')).to eql({})
|
||||
end
|
||||
end
|
||||
|
||||
context 'when valid --api-token' do
|
||||
let(:api_token) { 's3cRet' }
|
||||
|
||||
context 'when the slug exist' do
|
||||
it 'calls the correct URL' do
|
||||
stub_request(:get, api.uri.join('themes/slug'))
|
||||
.to_return(status: 200, body: { slug: { t: 'aa' } }.to_json)
|
||||
|
||||
expect(api.theme_data('slug')).to eql('t' => 'aa')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the slug does not exist' do
|
||||
it 'returns an empty hash' do
|
||||
stub_request(:get, api.uri.join('themes/slug-404')).to_return(status: 404, body: '{}')
|
||||
|
||||
expect(api.theme_data('slug-404')).to eql({})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#wordpress_data' do
|
||||
before { api.token = api_token }
|
||||
|
||||
context 'when no --api-token' do
|
||||
let(:api_token) { nil }
|
||||
|
||||
it 'returns an empty hash' do
|
||||
expect(api.wordpress_data('1.2')).to eql({})
|
||||
end
|
||||
end
|
||||
|
||||
context 'when valid --api-token' do
|
||||
let(:api_token) { 's3cRet' }
|
||||
|
||||
context 'when the version exist' do
|
||||
it 'calls the correct URL' do
|
||||
stub_request(:get, api.uri.join('wordpresses/522'))
|
||||
.to_return(status: 200, body: { '5.2.2' => { w: 'aa' } }.to_json)
|
||||
|
||||
expect(api.wordpress_data('5.2.2')).to eql('w' => 'aa')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the version does not exist' do
|
||||
it 'returns an empty hash' do
|
||||
stub_request(:get, api.uri.join('wordpresses/11')).to_return(status: 404, body: '{}')
|
||||
|
||||
expect(api.wordpress_data('1.1')).to eql({})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#status' do
|
||||
before do
|
||||
api.token = 's3cRet'
|
||||
|
||||
stub_request(:get, api.uri.join('status'))
|
||||
.with(query: { version: WPScan::VERSION },
|
||||
headers: { 'Host' => api.uri.host, 'Expect' => nil, 'Referer' => nil,
|
||||
'User-Agent' => WPScan::Browser.instance.default_user_agent,
|
||||
'Authorization' => 'Token token=s3cRet' })
|
||||
.to_return(status: code, body: return_body.to_json)
|
||||
end
|
||||
|
||||
let(:code) { 200 }
|
||||
let(:return_body) { {} }
|
||||
|
||||
context 'when 200' do
|
||||
let(:return_body) { { success: true, plan: 'free', requests_remaining: 100 } }
|
||||
|
||||
it 'returns the expected hash' do
|
||||
status = api.status
|
||||
|
||||
expect(status['success']).to be true
|
||||
expect(status['plan']).to eql 'free'
|
||||
expect(status['requests_remaining']).to eql 100
|
||||
end
|
||||
|
||||
context 'when unlimited requests' do
|
||||
let(:return_body) { super().merge(plan: 'enterprise', requests_remaining: -1) }
|
||||
|
||||
it 'returns the expected hash, witht he correct requests_remaining' do
|
||||
status = api.status
|
||||
|
||||
expect(status['success']).to be true
|
||||
expect(status['plan']).to eql 'enterprise'
|
||||
expect(status['requests_remaining']).to eql 'Unlimited'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when 401' do
|
||||
let(:code) { 401 }
|
||||
let(:return_body) { { error: 'HTTP Token: Access denied.' } }
|
||||
|
||||
it 'returns the expected hash' do
|
||||
status = api.status
|
||||
|
||||
expect(status['error']).to eql 'HTTP Token: Access denied.'
|
||||
end
|
||||
end
|
||||
|
||||
context 'otherwise' do
|
||||
let(:code) { 0 }
|
||||
|
||||
it 'returns the expected hash with the response' do
|
||||
status = api.status
|
||||
|
||||
expect(status['http_error']).to be_a WPScan::Error::HTTP
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -83,14 +83,22 @@ describe WPScan::Target do
|
||||
end
|
||||
|
||||
context 'when wp_version found' do
|
||||
before do
|
||||
expect(wp_version)
|
||||
.to receive(:db_data)
|
||||
.and_return(vuln_api_data_for("wordpresses/#{wp_version.number.tr('.', '')}"))
|
||||
|
||||
target.instance_variable_set(:@wp_version, wp_version)
|
||||
end
|
||||
|
||||
context 'when not vulnerable' do
|
||||
before { target.instance_variable_set(:@wp_version, WPScan::Model::WpVersion.new('4.4')) }
|
||||
let(:wp_version) { WPScan::Model::WpVersion.new('4.0') }
|
||||
|
||||
it { should_not be_vulnerable }
|
||||
end
|
||||
|
||||
context 'when vulnerable' do
|
||||
before { target.instance_variable_set(:@wp_version, WPScan::Model::WpVersion.new('3.8.1')) }
|
||||
let(:wp_version) { WPScan::Model::WpVersion.new('3.8.1') }
|
||||
|
||||
it { should be_vulnerable }
|
||||
end
|
||||
|
||||
4
spec/output/vuln_api/all_ok.cli_no_colour
Normal file
4
spec/output/vuln_api/all_ok.cli_no_colour
Normal file
@@ -0,0 +1,4 @@
|
||||
[+] WPVulnDB API OK
|
||||
| Plan: paid
|
||||
| Requests Done (during the scan): 3
|
||||
| Requests Remaining: 120
|
||||
7
spec/output/vuln_api/all_ok.json
Normal file
7
spec/output/vuln_api/all_ok.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"vuln_api": {
|
||||
"plan": "paid",
|
||||
"requests_done_during_scan": 3,
|
||||
"requests_remaining": 120
|
||||
}
|
||||
}
|
||||
1
spec/output/vuln_api/http_error.cli_no_colour
Normal file
1
spec/output/vuln_api/http_error.cli_no_colour
Normal file
@@ -0,0 +1 @@
|
||||
[!] WPVulnDB API, HTTP Error: url (Timeout was reached)
|
||||
5
spec/output/vuln_api/http_error.json
Normal file
5
spec/output/vuln_api/http_error.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"vuln_api": {
|
||||
"http_error": "HTTP Error: url (Timeout was reached)"
|
||||
}
|
||||
}
|
||||
4
spec/output/vuln_api/no_more_requests.cli_no_colour
Normal file
4
spec/output/vuln_api/no_more_requests.cli_no_colour
Normal file
@@ -0,0 +1,4 @@
|
||||
[+] WPVulnDB API OK
|
||||
| Plan: free
|
||||
| Requests Done (during the scan): 3
|
||||
| Requests Remaining: 0
|
||||
7
spec/output/vuln_api/no_more_requests.json
Normal file
7
spec/output/vuln_api/no_more_requests.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"vuln_api": {
|
||||
"plan": "free",
|
||||
"requests_done_during_scan": 3,
|
||||
"requests_remaining": 0
|
||||
}
|
||||
}
|
||||
2
spec/output/vuln_api/no_token.cli_no_colour
Normal file
2
spec/output/vuln_api/no_token.cli_no_colour
Normal file
@@ -0,0 +1,2 @@
|
||||
[!] No WPVulnDB API Token given, as a result vulnerability data has not been output.
|
||||
[!] You can get a free API token with 50 daily requests by registering at https://wpvulndb.com/register.
|
||||
5
spec/output/vuln_api/no_token.json
Normal file
5
spec/output/vuln_api/no_token.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"vuln_api": {
|
||||
"error": "No WPVulnDB API Token given, as a result vulnerability data has not been output.\nYou can get a free API token with 50 daily requests by registering at https://wpvulndb.com/register."
|
||||
}
|
||||
}
|
||||
4
spec/output/vuln_api/unlimited_requests.cli_no_colour
Normal file
4
spec/output/vuln_api/unlimited_requests.cli_no_colour
Normal file
@@ -0,0 +1,4 @@
|
||||
[+] WPVulnDB API OK
|
||||
| Plan: enterprise
|
||||
| Requests Done (during the scan): 3
|
||||
| Requests Remaining: Unlimited
|
||||
7
spec/output/vuln_api/unlimited_requests.json
Normal file
7
spec/output/vuln_api/unlimited_requests.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"vuln_api": {
|
||||
"plan": "enterprise",
|
||||
"requests_done_during_scan": 3,
|
||||
"requests_remaining": "Unlimited"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
[+] WordPress version 3.8.1 identified (Outdated, released on 2014-01-23).
|
||||
[+] WordPress version 3.8.1 identified (Outdated-via-api, released on 2014-01-23-via-api).
|
||||
| Detected By: rspec
|
||||
|
|
||||
| [!] 2 vulnerabilities identified:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"version": {
|
||||
"number": "3.8.1",
|
||||
"release_date": "2014-01-23",
|
||||
"status": "outdated",
|
||||
"release_date": "2014-01-23-via-api",
|
||||
"status": "outdated-via-api",
|
||||
"found_by": "rspec",
|
||||
"confidence": 0,
|
||||
"interesting_entries": [
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'shared_examples/views/vuln_api'
|
||||
require 'shared_examples/views/wp_version'
|
||||
require 'shared_examples/views/main_theme'
|
||||
require 'shared_examples/views/enumeration'
|
||||
|
||||
@@ -60,6 +60,8 @@ shared_examples 'App::Views::MainTheme' do
|
||||
|
||||
it 'outputs the expected string' do
|
||||
expect(theme).to receive(:version).at_least(1)
|
||||
allow(theme).to receive(:db_data).and_return(vuln_api_data_for('themes/dignitas-themes'))
|
||||
|
||||
@tpl_vars = tpl_vars.merge(theme: theme, verbose: true)
|
||||
end
|
||||
end
|
||||
|
||||
63
spec/shared_examples/views/vuln_api.rb
Normal file
63
spec/shared_examples/views/vuln_api.rb
Normal file
@@ -0,0 +1,63 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
shared_examples 'App::Views::VulnApi' do
|
||||
let(:controller) { WPScan::Controller::VulnApi.new }
|
||||
let(:tpl_vars) { { url: target_url } }
|
||||
|
||||
describe 'status' do
|
||||
let(:view) { 'status' }
|
||||
|
||||
context 'when no api token is given' do
|
||||
let(:expected_view) { 'no_token' }
|
||||
|
||||
it 'outputs the expected string' do
|
||||
@tpl_vars = tpl_vars.merge(status: {})
|
||||
end
|
||||
end
|
||||
|
||||
context 'when http error' do
|
||||
let(:expected_view) { 'http_error' }
|
||||
|
||||
it 'outputs the expected string' do
|
||||
@tpl_vars = tpl_vars.merge(
|
||||
status: {
|
||||
'http_error' => WPScan::Error::HTTP.new(Typhoeus::Response.new(effective_url: 'url', return_code: 28))
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no more remaining requests' do
|
||||
let(:expected_view) { 'no_more_requests' }
|
||||
|
||||
it 'outputs the expected string' do
|
||||
@tpl_vars = tpl_vars.merge(
|
||||
status: { 'success': true, 'plan' => 'free', 'requests_remaining' => 0 },
|
||||
api_requests: 3
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when everything is fine' do
|
||||
let(:expected_view) { 'all_ok' }
|
||||
|
||||
it 'outputs the expected string' do
|
||||
@tpl_vars = tpl_vars.merge(
|
||||
status: { 'success': true, 'plan' => 'paid', 'requests_remaining' => 120 },
|
||||
api_requests: 3
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when unlimited requests' do
|
||||
let(:expected_view) { 'unlimited_requests' }
|
||||
|
||||
it 'outputs the expected string' do
|
||||
@tpl_vars = tpl_vars.merge(
|
||||
status: { 'success': true, 'plan' => 'enterprise', 'requests_remaining' => 'Unlimited' },
|
||||
api_requests: 3
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -17,6 +17,7 @@ shared_examples 'App::Views::WpVersion' do
|
||||
|
||||
context 'when the version is not nil' do
|
||||
let(:version) { WPScan::Model::WpVersion.new('4.0', found_by: 'rspec') }
|
||||
before { allow(version).to receive(:db_data).and_return(vuln_api_data_for('wordpresses/40')) }
|
||||
|
||||
context 'when confirmed_by is empty' do
|
||||
context 'when no interesting_entries' do
|
||||
@@ -77,9 +78,12 @@ shared_examples 'App::Views::WpVersion' do
|
||||
|
||||
context 'when the version is vulnerable' do
|
||||
let(:expected_view) { 'with_vulns' }
|
||||
let(:version) { WPScan::Model::WpVersion.new('3.8.1', found_by: 'rspec') }
|
||||
|
||||
before { allow(version).to receive(:db_data).and_return(vuln_api_data_for('wordpresses/381')) }
|
||||
|
||||
it 'outputs the expected string' do
|
||||
@tpl_vars = tpl_vars.merge(version: WPScan::Model::WpVersion.new('3.8.1', found_by: 'rspec'))
|
||||
@tpl_vars = tpl_vars.merge(version: version)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -44,6 +44,10 @@ def df_stubbed_response(fixture, finder_super_class)
|
||||
end
|
||||
end
|
||||
|
||||
def vuln_api_data_for(path)
|
||||
JSON.parse(File.read(FIXTURES.join('db', 'vuln_api', "#{path}.json")))
|
||||
end
|
||||
|
||||
require 'wpscan'
|
||||
require 'shared_examples'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user