Land #14458, Add auxiliary support to autocheck mixin

This commit is contained in:
Grant Willcox
2020-12-05 23:54:41 -06:00
3 changed files with 120 additions and 97 deletions
+20 -7
View File
@@ -16,10 +16,24 @@ module Exploit::Remote::AutoCheck
])
end
def run
with_prepended_auto_check do
super
end
end
def exploit
with_prepended_auto_check do
super
end
end
private
def with_prepended_auto_check
unless datastore['AutoCheck']
print_warning('AutoCheck is disabled, proceeding with exploitation')
return super
return yield
end
print_status('Executing automatic check (disable AutoCheck to override)')
@@ -30,14 +44,14 @@ module Exploit::Remote::AutoCheck
case (checkcode = check)
when Exploit::CheckCode::Vulnerable, Exploit::CheckCode::Appears
print_good(checkcode.message)
super
yield
when Exploit::CheckCode::Detected
print_warning(checkcode.message)
super
yield
when Exploit::CheckCode::Safe
if datastore['ForceExploit']
print_warning("#{checkcode.message} #{warning_msg}")
return super
return yield
end
fail_with(Module::Failure::NotVulnerable,
@@ -45,19 +59,18 @@ module Exploit::Remote::AutoCheck
when Exploit::CheckCode::Unsupported
if datastore['ForceExploit']
print_warning("#{checkcode.message} #{warning_msg}")
return super
return yield
end
fail_with(Module::Failure::BadConfig, "#{checkcode.message} #{error_msg}")
else
if datastore['ForceExploit']
print_warning("#{checkcode.message} #{warning_msg}")
return super
return yield
end
fail_with(Module::Failure::Unknown, "#{checkcode.message} #{error_msg}")
end
end
end
end
+2 -11
View File
@@ -6,6 +6,7 @@
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {})
super(update_info(info,
@@ -42,8 +43,7 @@ class MetasploitModule < Msf::Auxiliary
])
register_advanced_options([
OptBool.new('DefangedMode', [true, 'Run in defanged mode', true]),
OptBool.new('ForceExploit', [true, 'Override check result', false])
OptBool.new('DefangedMode', [true, 'Run in defanged mode', true])
])
end
@@ -72,15 +72,6 @@ class MetasploitModule < Msf::Auxiliary
return
end
checkcode = check
unless datastore['ForceExploit']
unless checkcode == Exploit::CheckCode::Appears
print_error("#{checkcode[1]}. Set ForceExploit to override.")
return
end
end
case action.name
when 'Cook'
print_status("Cooking on #{datastore['TEMP']} for #{datastore['TIME']}m")
@@ -9,15 +9,15 @@ RSpec.shared_examples "An AutoCheck module which can be overridden" do |opts|
context "when ForceExploit is enabled" do
before(:each) do
subject.datastore['ForceExploit'] = true
subject.exploit
subject.send(opts[:method])
end
it "calls the check method" do
expect(subject).to have_received(:check)
end
it 'calls the original exploit' do
expect(subject).to have_received(:original_exploit_call)
it "calls the original #{opts[:method ]} method" do
expect(subject).to have_received(:"original_#{opts[:method]}_call")
end
end
end
@@ -27,15 +27,94 @@ RSpec.shared_examples "An AutoCheck module which can be overridden" do |opts|
subject.datastore['ForceExploit'] = false
end
it "it doesn't call the original exploit" do
expect { subject.exploit }.to raise_error(opts[:expected_error]) do
expect(subject).to_not have_received(:original_exploit_call)
it "it doesn't call the original #{opts[:method ]} method" do
expect { subject.send(opts[:method]) }.to raise_error(opts[:expected_error]) do
expect(subject).to_not have_received(:"original_#{opts[:method]}_call")
end
end
end
end
end
RSpec.shared_examples "An AutoChecked method" do |opts|
subject { mock_module_with_prepend_autocheck.new }
before(:each) do
allow(subject).to receive(:check).and_return(check_result)
allow(subject).to receive(:"original_#{opts[:method]}_call").and_call_original
end
context 'when AutoCheck is disabled' do
let(:check_result) { ::Msf::Exploit::CheckCode::Vulnerable }
before(:each) do
subject.datastore['AutoCheck'] = false
subject.send(opts[:method])
end
it "doesn't call the check method" do
expect(subject).to_not have_received(:check)
end
it "correctly calls the #{opts[:method]} method" do
expect(subject).to have_received(:"original_#{opts[:method]}_call")
end
end
context 'when AutoCheck is enabled' do
before(:each) do
subject.datastore['AutoCheck'] = true
end
context 'when the check method returns vulnerable' do
let(:check_result) { ::Msf::Exploit::CheckCode::Vulnerable }
before(:each) do
subject.send(opts[:method])
end
it "calls the check method" do
expect(subject).to have_received(:check)
end
it "calls the original #{opts[:method]} method" do
expect(subject).to have_received(:"original_#{opts[:method]}_call")
end
end
context 'when the check method returns appears' do
let(:check_result) { ::Msf::Exploit::CheckCode::Appears }
before(:each) do
subject.send(opts[:method])
end
it "calls the check method" do
expect(subject).to have_received(:check)
end
it "calls the original #{opts[:method]} method" do
expect(subject).to have_received(:"original_#{opts[:method]}_call")
end
end
it_behaves_like "An AutoCheck module which can be overridden",
method: opts[:method],
check_code: ::Msf::Exploit::CheckCode::Safe,
expected_error: "The target is not exploitable. Enable ForceExploit to override check result."
it_behaves_like "An AutoCheck module which can be overridden",
method: opts[:method],
check_code: ::Msf::Exploit::CheckCode::Unsupported,
expected_error: "This module does not support check. Enable ForceExploit to override check result."
it_behaves_like "An AutoCheck module which can be overridden",
method: opts[:method],
check_code: ::Msf::Exploit::CheckCode::Unknown,
expected_error: "Cannot reliably check exploitability. Enable ForceExploit to override check result."
end
end
RSpec.describe Msf::Exploit::Remote::AutoCheck do
let(:mock_module_with_prepend_autocheck) do
context_described_class = described_class
@@ -46,6 +125,14 @@ RSpec.describe Msf::Exploit::Remote::AutoCheck do
# mocked
end
def run
original_run_call
end
def original_run_call
# Helper for verifying the original run function was called
end
def exploit
original_exploit_call
end
@@ -69,80 +156,12 @@ RSpec.describe Msf::Exploit::Remote::AutoCheck do
end
context 'when the mixin is prepended' do
describe '#run' do
it_behaves_like 'An AutoChecked method', method: :run
end
describe '#exploit' do
subject { mock_module_with_prepend_autocheck.new }
before(:each) do
allow(subject).to receive(:check).and_return(check_result)
allow(subject).to receive(:original_exploit_call).and_call_original
end
context 'when AutoCheck is disabled' do
let(:check_result) { ::Msf::Exploit::CheckCode::Vulnerable }
before(:each) do
subject.datastore['AutoCheck'] = false
subject.exploit
end
it "doesn't call the check method" do
expect(subject).to_not have_received(:check)
end
it "correctly calls the exploit method" do
expect(subject).to have_received(:original_exploit_call)
end
end
context 'when AutoCheck is enabled' do
before(:each) do
subject.datastore['AutoCheck'] = true
end
context 'when the check method returns vulnerable' do
let(:check_result) { ::Msf::Exploit::CheckCode::Vulnerable }
before(:each) do
subject.exploit
end
it "calls the check method" do
expect(subject).to have_received(:check)
end
it 'calls the original exploit' do
expect(subject).to have_received(:original_exploit_call)
end
end
context 'when the check method returns appears' do
let(:check_result) { ::Msf::Exploit::CheckCode::Appears }
before(:each) do
subject.exploit
end
it "calls the check method" do
expect(subject).to have_received(:check)
end
it 'calls the original exploit' do
expect(subject).to have_received(:original_exploit_call)
end
end
it_behaves_like "An AutoCheck module which can be overridden",
check_code: ::Msf::Exploit::CheckCode::Safe,
expected_error: "The target is not exploitable. Enable ForceExploit to override check result."
it_behaves_like "An AutoCheck module which can be overridden",
check_code: ::Msf::Exploit::CheckCode::Unsupported,
expected_error: "This module does not support check. Enable ForceExploit to override check result."
it_behaves_like "An AutoCheck module which can be overridden",
check_code: ::Msf::Exploit::CheckCode::Unknown,
expected_error: "Cannot reliably check exploitability. Enable ForceExploit to override check result."
end
it_behaves_like 'An AutoChecked method', method: :exploit
end
end
end