Updates finders to use new methods
This commit is contained in:
@@ -8,13 +8,12 @@ module WPScan
|
||||
# @return [ InterestingFinding ]
|
||||
def aggressive(_opts = {})
|
||||
path = 'wp-content/backup-db/'
|
||||
url = target.url(path)
|
||||
res = Browser.get(url)
|
||||
res = target.head_and_get(path, [200, 403])
|
||||
|
||||
return unless [200, 403].include?(res.code) && !target.homepage_or_404?(res)
|
||||
|
||||
Model::BackupDB.new(
|
||||
url,
|
||||
target.url(path),
|
||||
confidence: 70,
|
||||
found_by: DIRECT_ACCESS,
|
||||
interesting_entries: target.directory_listing_entries(path),
|
||||
|
||||
@@ -7,13 +7,12 @@ module WPScan
|
||||
class DuplicatorInstallerLog < CMSScanner::Finders::Finder
|
||||
# @return [ InterestingFinding ]
|
||||
def aggressive(_opts = {})
|
||||
url = target.url('installer-log.txt')
|
||||
res = Browser.get(url)
|
||||
path = 'installer-log.txt'
|
||||
|
||||
return unless res.body =~ /DUPLICATOR INSTALL-LOG/
|
||||
return unless target.head_and_get(path).body =~ /DUPLICATOR INSTALL-LOG/
|
||||
|
||||
Model::DuplicatorInstallerLog.new(
|
||||
url,
|
||||
target.url(path),
|
||||
confidence: 100,
|
||||
found_by: DIRECT_ACCESS,
|
||||
references: { url: 'https://www.exploit-db.com/ghdb/3981/' }
|
||||
|
||||
@@ -7,13 +7,13 @@ module WPScan
|
||||
class EmergencyPwdResetScript < CMSScanner::Finders::Finder
|
||||
# @return [ InterestingFinding ]
|
||||
def aggressive(_opts = {})
|
||||
url = target.url('/emergency.php')
|
||||
res = Browser.get(url)
|
||||
path = 'emergency.php'
|
||||
res = target.head_and_get(path)
|
||||
|
||||
return unless res.code == 200 && !target.homepage_or_404?(res)
|
||||
|
||||
Model::EmergencyPwdResetScript.new(
|
||||
url,
|
||||
target.url(path),
|
||||
confidence: res.body =~ /password/i ? 100 : 40,
|
||||
found_by: DIRECT_ACCESS,
|
||||
references: {
|
||||
|
||||
@@ -7,14 +7,14 @@ module WPScan
|
||||
class Readme < CMSScanner::Finders::Finder
|
||||
# @return [ InterestingFinding ]
|
||||
def aggressive(_opts = {})
|
||||
potential_files.each do |file|
|
||||
url = target.url(file)
|
||||
res = Browser.get(url)
|
||||
potential_files.each do |path|
|
||||
res = target.head_and_get(path)
|
||||
|
||||
if res.code == 200 && res.body =~ /wordpress/i
|
||||
return Model::Readme.new(url, confidence: 100, found_by: DIRECT_ACCESS)
|
||||
end
|
||||
next unless res.code == 200 && res.body =~ /wordpress/i
|
||||
|
||||
return Model::Readme.new(target.url(path), confidence: 100, found_by: DIRECT_ACCESS)
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
|
||||
@@ -9,22 +9,17 @@ module WPScan
|
||||
|
||||
# @return [ InterestingFinding ]
|
||||
def aggressive(_opts = {})
|
||||
head_res = browser.forge_request(dump_url, target.head_or_get_request_params).run
|
||||
path = 'wp-content/uploads/dump.sql'
|
||||
res = target.head_and_get(path, [200], get: { headers: { 'Range' => 'bytes=0-3000' } })
|
||||
|
||||
return unless head_res.code == 200
|
||||
|
||||
return unless Browser.get(dump_url, headers: { 'Range' => 'bytes=0-3000' }).body =~ SQL_PATTERN
|
||||
return unless res.body =~ SQL_PATTERN
|
||||
|
||||
Model::UploadSQLDump.new(
|
||||
dump_url,
|
||||
target.url(path),
|
||||
confidence: 100,
|
||||
found_by: DIRECT_ACCESS
|
||||
)
|
||||
end
|
||||
|
||||
def dump_url
|
||||
@dump_url ||= target.url('wp-content/uploads/dump.sql')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,31 +8,38 @@ describe WPScan::Finders::InterestingFindings::BackupDB do
|
||||
let(:wp_content) { 'wp-content' }
|
||||
let(:dir_url) { target.url("#{wp_content}/backup-db/") }
|
||||
|
||||
before { expect(target).to receive(:content_dir).at_least(1).and_return(wp_content) }
|
||||
before do
|
||||
expect(target).to receive(:content_dir).at_least(1).and_return(wp_content)
|
||||
expect(target).to receive(:head_or_get_params).and_return(method: :head)
|
||||
end
|
||||
|
||||
describe '#aggressive' do
|
||||
before { stub_request(:get, dir_url).to_return(status: status, body: body) }
|
||||
|
||||
let(:body) { '' }
|
||||
|
||||
context 'when not a 200 or 403' do
|
||||
let(:status) { 404 }
|
||||
it 'returns nil' do
|
||||
stub_request(:head, dir_url).to_return(status: 404)
|
||||
|
||||
its(:aggressive) { should be_nil }
|
||||
expect(finder.aggressive).to eql nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when 200 and matching the homepage' do
|
||||
before { expect(target).to receive(:homepage_or_404?).and_return(true) }
|
||||
it 'returns nil' do
|
||||
stub_request(:head, dir_url)
|
||||
stub_request(:get, dir_url)
|
||||
|
||||
let(:status) { 200 }
|
||||
expect(target).to receive(:homepage_or_404?).and_return(true)
|
||||
|
||||
its(:aggressive) { should be_nil }
|
||||
expect(finder.aggressive).to eql nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when 200 or 403' do
|
||||
before { expect(target).to receive(:homepage_or_404?).and_return(false) }
|
||||
before do
|
||||
stub_request(:head, dir_url)
|
||||
stub_request(:get, dir_url).and_return(body: body)
|
||||
|
||||
let(:status) { 200 }
|
||||
expect(target).to receive(:homepage_or_404?).and_return(false)
|
||||
end
|
||||
|
||||
after do
|
||||
found = finder.aggressive
|
||||
@@ -47,6 +54,8 @@ describe WPScan::Finders::InterestingFindings::BackupDB do
|
||||
end
|
||||
|
||||
context 'when no directory listing' do
|
||||
let(:body) { '' }
|
||||
|
||||
it 'returns an empty interesting_findings attribute' do
|
||||
@expected_entries = []
|
||||
end
|
||||
|
||||
@@ -11,24 +11,39 @@ describe WPScan::Finders::InterestingFindings::DuplicatorInstallerLog do
|
||||
describe '#aggressive' do
|
||||
before do
|
||||
expect(target).to receive(:sub_dir).at_least(1).and_return(false)
|
||||
stub_request(:get, log_url).to_return(body: body)
|
||||
expect(target).to receive(:head_or_get_params).and_return(method: :head)
|
||||
end
|
||||
|
||||
context 'when the body does not match' do
|
||||
let(:body) { '' }
|
||||
context 'when not a 200' do
|
||||
it 'return nil' do
|
||||
stub_request(:head, log_url).to_return(status: 404)
|
||||
|
||||
its(:aggressive) { should be_nil }
|
||||
expect(finder.aggressive).to eql nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the body matches' do
|
||||
let(:body) { File.read(fixtures.join(filename)) }
|
||||
context 'when a 200' do
|
||||
before do
|
||||
stub_request(:head, log_url)
|
||||
stub_request(:get, log_url).to_return(body: body)
|
||||
end
|
||||
|
||||
it 'returns the InterestingFinding' do
|
||||
expect(finder.aggressive).to eql WPScan::Model::DuplicatorInstallerLog.new(
|
||||
log_url,
|
||||
confidence: 100,
|
||||
found_by: described_class::DIRECT_ACCESS
|
||||
)
|
||||
context 'when the body does not match' do
|
||||
let(:body) { '' }
|
||||
|
||||
its(:aggressive) { should be_nil }
|
||||
end
|
||||
|
||||
context 'when the body matches' do
|
||||
let(:body) { File.read(fixtures.join(filename)) }
|
||||
|
||||
it 'returns the InterestingFinding' do
|
||||
expect(finder.aggressive).to eql WPScan::Model::DuplicatorInstallerLog.new(
|
||||
log_url,
|
||||
confidence: 100,
|
||||
found_by: described_class::DIRECT_ACCESS
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,9 +4,69 @@ describe WPScan::Finders::InterestingFindings::EmergencyPwdResetScript do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:file_url) { url + 'emergency.php' }
|
||||
let(:fixtures) { FINDERS_FIXTURES.join('interesting_findings', 'emergency_pwd_reset_script') }
|
||||
|
||||
before do
|
||||
expect(target).to receive(:sub_dir).at_least(1).and_return(false)
|
||||
expect(target).to receive(:head_or_get_params).and_return(method: :head)
|
||||
end
|
||||
|
||||
describe '#aggressive' do
|
||||
xit
|
||||
context 'when not a 200' do
|
||||
it 'returns nil' do
|
||||
stub_request(:head, file_url).to_return(status: 404)
|
||||
|
||||
expect(finder.aggressive).to eql nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when 200 and matching the homepage' do
|
||||
before { stub_request(:head, file_url) }
|
||||
|
||||
context 'when matching the homepage' do
|
||||
it 'returns nil' do
|
||||
stub_request(:get, file_url)
|
||||
|
||||
expect(target).to receive(:homepage_or_404?).and_return(true)
|
||||
|
||||
expect(finder.aggressive).to eql nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when 200' do
|
||||
before do
|
||||
stub_request(:get, file_url).and_return(body: body)
|
||||
|
||||
expect(target).to receive(:homepage_or_404?).and_return(false)
|
||||
end
|
||||
|
||||
after do
|
||||
found = finder.aggressive
|
||||
|
||||
expect(found).to eql WPScan::Model::EmergencyPwdResetScript.new(
|
||||
file_url,
|
||||
confidence: @expected_confidence,
|
||||
found_by: described_class::DIRECT_ACCESS
|
||||
)
|
||||
end
|
||||
|
||||
context 'when body matches /password/' do
|
||||
let(:body) { File.read(fixtures.join('emergency.php')) }
|
||||
|
||||
it 'returns with a confidence of 100' do
|
||||
@expected_confidence = 100
|
||||
end
|
||||
end
|
||||
|
||||
context 'when body does not match /password/' do
|
||||
let(:body) { 'maybe, maybe not' }
|
||||
|
||||
it 'returns with a confidence of 40' do
|
||||
@expected_confidence = 40
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,9 +9,10 @@ describe WPScan::Finders::InterestingFindings::Readme do
|
||||
describe '#aggressive' do
|
||||
before do
|
||||
expect(target).to receive(:sub_dir).at_least(1).and_return(false)
|
||||
expect(target).to receive(:head_or_get_params).at_least(1).and_return(method: :head)
|
||||
|
||||
finder.potential_files.each do |file|
|
||||
stub_request(:get, target.url(file)).to_return(status: 404)
|
||||
stub_request(:head, target.url(file)).to_return(status: 404)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -24,7 +25,10 @@ describe WPScan::Finders::InterestingFindings::Readme do
|
||||
let(:file) { finder.potential_files.sample }
|
||||
let(:readme) { File.read(fixtures.join('readme-3.9.2.html')) }
|
||||
|
||||
before { stub_request(:get, target.url(file)).to_return(body: readme) }
|
||||
before do
|
||||
stub_request(:head, target.url(file))
|
||||
stub_request(:get, target.url(file)).to_return(body: readme)
|
||||
end
|
||||
|
||||
it 'returns the expected InterestingFinding' do
|
||||
expected = WPScan::Model::Readme.new(
|
||||
|
||||
@@ -4,20 +4,21 @@ describe WPScan::Finders::InterestingFindings::UploadSQLDump do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:dump_url) { url + 'wp-content/uploads/dump.sql' }
|
||||
let(:fixtures) { FINDERS_FIXTURES.join('interesting_findings', 'upload_sql_dump') }
|
||||
let(:wp_content) { 'wp-content' }
|
||||
|
||||
describe '#aggressive' do
|
||||
before do
|
||||
expect(target).to receive(:content_dir).at_least(1).and_return(wp_content)
|
||||
expect(target).to receive(:head_or_get_request_params).and_return(method: :head)
|
||||
expect(target).to receive(:head_or_get_params).and_return(method: :head)
|
||||
end
|
||||
|
||||
after { expect(finder.aggressive).to eql @expected }
|
||||
|
||||
context 'when not a 200' do
|
||||
it 'returns nil' do
|
||||
stub_request(:head, finder.dump_url).to_return(status: 404)
|
||||
stub_request(:head, dump_url).to_return(status: 404)
|
||||
|
||||
@expected = nil
|
||||
end
|
||||
@@ -25,9 +26,9 @@ describe WPScan::Finders::InterestingFindings::UploadSQLDump do
|
||||
|
||||
context 'when a 200' do
|
||||
before do
|
||||
stub_request(:head, finder.dump_url).to_return(status: 200)
|
||||
stub_request(:head, dump_url).to_return(status: 200)
|
||||
|
||||
stub_request(:get, finder.dump_url)
|
||||
stub_request(:get, dump_url)
|
||||
.with(headers: { 'Range' => 'bytes=0-3000' })
|
||||
.to_return(body: File.read(fixtures.join(fixture)))
|
||||
end
|
||||
@@ -45,7 +46,7 @@ describe WPScan::Finders::InterestingFindings::UploadSQLDump do
|
||||
|
||||
it 'returns the interesting findings' do
|
||||
@expected = WPScan::Model::UploadSQLDump.new(
|
||||
finder.dump_url,
|
||||
dump_url,
|
||||
confidence: 100,
|
||||
found_by: described_class::DIRECT_ACCESS
|
||||
)
|
||||
|
||||
30
spec/fixtures/finders/interesting_findings/emergency_pwd_reset_script/emergency.php
vendored
Normal file
30
spec/fixtures/finders/interesting_findings/emergency_pwd_reset_script/emergency.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>WordPress Emergency PassWord Reset</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<link rel="stylesheet" href="http://wp.lab/wp-admin/wp-admin.css?version=5.1.1" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<form method="post" action="">
|
||||
<h2>WordPress Emergency PassWord Reset</h2>
|
||||
<p><strong>Your use of this script is at your sole risk. All code is provided "as -is", without any warranty, whether express or implied, of its accuracy, completeness. Further, I shall not be liable for any damages you may sustain by using this script, whether direct, indirect, special, incidental or consequential.</strong></p>
|
||||
<p>This script is intended to be used as <strong>a last resort</strong> by WordPress administrators that are unable to access the database.
|
||||
Usage of this script requires that you know the Administrator's user name for the WordPress install. (For most installs, that is going to be "admin" without the quotes.)</p>
|
||||
<p class="submit"><input type="submit" name="update" value="Update Options" /></p>
|
||||
|
||||
<fieldset class="options">
|
||||
<legend>WordPress Administrator</legend>
|
||||
<label>Enter Username:<br />
|
||||
<input type="text" name="e-name" id="e-name" class="input" value="" size="20" tabindex="10" /></label>
|
||||
</fieldset>
|
||||
<fieldset class="options">
|
||||
<legend>Password</legend>
|
||||
<label>Enter New Password:<br />
|
||||
<input type="text" name="e-pass" id="e-pass" class="input" value="" size="25" tabindex="20" /></label>
|
||||
</fieldset>
|
||||
|
||||
<p class="submit"><input type="submit" name="update" value="Update Options" /></p>
|
||||
</form>
|
||||
</div></body></html>
|
||||
Reference in New Issue
Block a user