forked from rapid7/metasploit-framework
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improves UX for scanner/login modules
- Loading branch information
1 parent
6301d84
commit 0853965
Showing
5 changed files
with
149 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
# -*- coding: binary -*- | ||
|
||
## | ||
# This file is part of the Metasploit Framework and may be subject to | ||
# redistribution and commercial restrictions. Please see the Metasploit | ||
# Framework web site for more information on licensing and terms of use. | ||
# https://metasploit.com/framework/ | ||
## | ||
|
||
module Msf | ||
class Auxiliary | ||
### | ||
# | ||
# This module provides a means to report module summaries | ||
# | ||
### | ||
module ReportSummary | ||
def initialize(info = {}) | ||
super(info) | ||
|
||
if framework.features.enabled?(Msf::FeatureManager::SHOW_SUCCESSFUL_LOGINS) | ||
register_options( | ||
[ | ||
OptBool.new('ShowSuccessfulLogins', [false, 'Outputs a table of successful logins', true]), | ||
] | ||
) | ||
end | ||
end | ||
|
||
def run | ||
@report = {} | ||
@report.extend(::Rex::Ref) | ||
rhost_walker = Msf::RhostsWalker.new(datastore['RHOSTS'], datastore).to_enum | ||
conditional_verbose_output(rhost_walker.count) | ||
super | ||
return unless framework.features.enabled?(Msf::FeatureManager::SHOW_SUCCESSFUL_LOGINS) | ||
return unless datastore['ShowSuccessfulLogins'] == true | ||
|
||
print_report_summary | ||
end | ||
|
||
def create_credential_login(credential_data) | ||
return unless framework.features.enabled?(Msf::FeatureManager::SHOW_SUCCESSFUL_LOGINS) | ||
return unless datastore['ShowSuccessfulLogins'] == true | ||
|
||
credential = credential_data[:core].to_credential | ||
@report[rhost] = { successful_logins: [] } | ||
@report[rhost][:successful_logins] << credential | ||
super | ||
end | ||
|
||
# I think this will work for our new modules, but I don't know if it'll work | ||
# for other modules that might not use 'session_setup' convention; | ||
# i.e. you might need to hijack start_session, or create_session, or some other | ||
# lower level building block that you'll have access to | ||
def start_session(obj, info, ds_merge, crlf = false, sock = nil, sess = nil) | ||
return unless framework.features.enabled?(Msf::FeatureManager::SHOW_SUCCESSFUL_LOGINS) | ||
return unless datastore['ShowSuccessfulLogins'] == true | ||
|
||
result = super | ||
@report[rhost].merge!({ successful_sessions: [] }) | ||
@report[rhost][:successful_sessions] << result | ||
result | ||
end | ||
|
||
private | ||
|
||
def print_report_summary | ||
report = @report | ||
|
||
logins = report.flat_map { |_k, v| v[:successful_logins] }.compact | ||
sessions = report.flat_map { |_k, v| v[:successful_sessions] }.compact | ||
|
||
# TODO: - This was previously within the run command that was initially added as a workaround | ||
# return results unless framework.features.enabled?(Msf::FeatureManager::MSSQL_SESSION_TYPE) | ||
|
||
print_status("Bruteforce completed, #{logins.size} #{logins.size == 1 ? 'credential was' : 'credentials were'} successful.") | ||
if datastore['CreateSession'] | ||
print_status("#{sessions.size} #{sessions.size == 1 ? 'session was' : 'sessions were'} opened successfully.") | ||
else | ||
print_status('You can open a session with these credentials and %grnCreateSession%clr set to true') | ||
end | ||
|
||
show_successful_logins(report) | ||
report | ||
end | ||
|
||
# Logic to detect if the ShowSuccessLogins datastore option has been set | ||
# | ||
# @param [Hash] report Host mapped to successful logins and sessions | ||
# @return [String] Rex::Text::Table containing successful logins | ||
def show_successful_logins(report) | ||
if datastore['ShowSuccessfulLogins'] == true && !report.empty? | ||
successful_logins_to_table(report) | ||
end | ||
end | ||
|
||
# The idea here is to add a hybrid approach for scanner modules | ||
# If only one host is scanned a more verbose output is useful to the user | ||
# If scanning multiple hosts we would want more lightweight information | ||
# | ||
# @param [Object] host_count The number of hosts | ||
def conditional_verbose_output(host_count) | ||
if host_count == 1 | ||
datastore['Verbose'] = true | ||
end | ||
end | ||
|
||
# Takes the login/session results and converts them into a Rex::Text::Table format | ||
# | ||
# @param report [Hash{String => [Metasploit::Framework::LoginScanner::Result, Msf::Sessions]}] | ||
# @return [String] Rex::Text::Table containing successful logins | ||
def successful_logins_to_table(report) | ||
field_headers = %w[Host Public Private] | ||
|
||
markdown_fields = report.flat_map do |host, result| | ||
if result[:successful_logins].nil? | ||
next | ||
end | ||
|
||
result[:successful_logins].map do |credential| | ||
[host, credential.public, credential.private] | ||
end | ||
end | ||
|
||
table = ::Rex::Text::Table.new( | ||
'Header' => 'Successful logins', | ||
'Indent' => 4, | ||
'Columns' => field_headers, | ||
'Rows' => markdown_fields.compact | ||
) | ||
|
||
print_line("\n" + table.to_s + "\n") | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters