Land #18144, update capture plugin to be more helpful, and add documentation

This commit is contained in:
adfoster-r7 2023-07-06 11:17:14 +01:00 committed by GitHub
commit 88a539a82c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 130 additions and 4 deletions

View File

@ -0,0 +1,37 @@
Capturing credentials is a critical and early phase in the playbook of many offensive security testers. Metasploit has facilitated this for years with protocol-specific modules all under the auxiliary/server/capture. Users can start and configure each of these modules individually, but now the capture plugin can streamline the process. The capture plugin can easily start 13 different services (17 including SSL enabled versions) on the same listening IP address including remote interfaces via Meterpreter. A configuration file can be used to select individual services to start and once finished, all services can easily be stopped using a single command.
To use the plugin, it must first be loaded. That will provide the captureg command (for Capture-Global) which then offers start and stop subcommands. In the following example, the plugin is loaded, and then all default services are started on the 192.168.159.128 interface.
```
msf6 > load capture
[*] Successfully loaded plugin: Credential Capture
msf6 > captureg start --ip 192.168.159.128
Logging results to /home/smcintyre/.msf4/logs/captures/capture_local_20220325104416_589275.txt
Hash results stored in /home/smcintyre/.msf4/loot/captures/capture_local_20220325104416_612808
[+] Authentication Capture: DRDA (DB2, Informix, Derby) started
[+] Authentication Capture: FTP started
[+] HTTP Client MS Credential Catcher started
[+] HTTP Client MS Credential Catcher started
[+] Authentication Capture: IMAP started
[+] Authentication Capture: MSSQL started
[+] Authentication Capture: MySQL started
[+] Authentication Capture: POP3 started
[+] Authentication Capture: PostgreSQL started
[+] Printjob Capture Service started
[+] Authentication Capture: SIP started
[+] Authentication Capture: SMB started
[+] Authentication Capture: SMTP started
[+] Authentication Capture: Telnet started
[+] Authentication Capture: VNC started
[+] Authentication Capture: FTP started
[+] Authentication Capture: IMAP started
[+] Authentication Capture: POP3 started
[+] Authentication Capture: SMTP started
[+] NetBIOS Name Service Spoofer started
[+] LLMNR Spoofer started
[+] mDNS Spoofer started
[+] Started capture jobs
msf6 >
```
This content was originally posted on the [Rapid7 Blog](https://www.rapid7.com/blog/post/2022/03/25/metasploit-weekly-wrap-up-154/).

View File

@ -623,6 +623,10 @@ NAVIGATION_CONFIG = [
path: 'How-to-use-the-Git-mixin-to-write-an-exploit-module.md',
title: 'Git Mixin'
},
{
path: 'How-To-Use-The-Capture-Plugin.md',
title: 'Capture Plugin'
},
{
title: 'HTTP',
folder: 'http',

View File

@ -13,14 +13,15 @@ module Msf
include Msf::Ui::Console::CommandDispatcher
class CaptureJobListener
def initialize(name, done_event)
def initialize(name, done_event, dispatcher)
@name = name
@done_event = done_event
@dispatcher = dispatcher
end
def waiting(_id)
self.succeeded = true
print_good("#{@name} started")
@dispatcher.print_good("#{@name} started")
@done_event.set
end
@ -29,7 +30,7 @@ module Msf
def completed(id, result, mod); end
def failed(_id, _error, _mod)
print_error("#{@name} failed to start")
@dispatcher.print_error("#{@name} failed to start")
@done_event.set
end
@ -82,6 +83,7 @@ module Msf
# short circuit the whole deal if they need help
return help if args.empty?
return help if args.length == 1 && args.first =~ HELP_REGEX
return help(args.last) if args.length == 2 && args.first =~ HELP_REGEX
begin
if args.first == 'stop'
@ -322,7 +324,7 @@ module Msf
modules_to_run.each do |svc, mod, opts|
event = Rex::Sync::Event.new(false, false)
job_listener = CaptureJobListener.new(mod.name, event)
job_listener = CaptureJobListener.new(mod.name, event, self)
result = Msf::Simple::Auxiliary.run_simple(mod, opts, job_listener: job_listener)
job_id = result[1]
@ -389,6 +391,8 @@ module Msf
print_line(@stop_opt_parser.usage)
else
print_line('Usage: captureg [start|stop] [options]')
print_line('')
print_line('Use captureg --help [start|stop] for more detailed usage help')
end
end

View File

@ -0,0 +1,81 @@
require 'spec_helper'
require Metasploit::Framework.root.join('plugins/capture.rb').to_path
RSpec.describe Msf::Plugin::Capture::ConsoleCommandDispatcher do
describe '#cmd_captureg' do
let(:driver) do
double(Object).as_null_object.tap do |dbl|
allow(dbl).to receive(:print_line) do |args|
args
end
end
end
subject { described_class.new(driver) }
context 'without args' do
it 'returns generic help text' do
expect(subject.cmd_captureg).to eql subject.help
end
end
context 'single arg matching the HELP regex' do
it 'returns generic help text' do
expect(subject.cmd_captureg('--help')).to eql subject.help
end
end
context 'two args, first one matches HELP regex' do
it 'calls `help` with second arg' do
expect(subject.cmd_captureg('--help', 'start')).to eql subject.help('start')
end
end
end
end
RSpec.describe Msf::Plugin::Capture::ConsoleCommandDispatcher::CaptureJobListener do
let(:dispatcher) do
instance_double(
Msf::Plugin::Capture::ConsoleCommandDispatcher,
print_error: nil,
print_good: nil
)
end
let(:done_event) { instance_double(Rex::Sync::Event, set: nil) }
let(:name) { 'my-little-module' }
subject { described_class.new(name, done_event, dispatcher) }
describe '#waiting' do
it 'sets the `succeeded` flag' do
subject.waiting('ignored')
expect(subject.succeeded).to eql true
end
it 'outputs a message via the dispatcher' do
expect(dispatcher).to receive(:print_good).with("#{name} started")
subject.waiting('ignored')
end
it 'sets the done event' do
expect(done_event).to receive(:set)
subject.waiting('ignored')
end
end
describe '#failed' do
it 'outputs a message via the dispatcher' do
expect(dispatcher).to receive(:print_error).with("#{name} failed to start")
subject.failed('ignored', 'ignored', 'ignored')
end
it 'sets the done event' do
expect(done_event).to receive(:set)
subject.failed('ignored', 'ignored', 'ignored')
end
end
end