Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/spec/lib/msf/base/serializer/readable_text_spec.rb
Views: 11765
# -*- coding:binary -*-12require 'spec_helper'3require 'rex/text'45RSpec.describe Msf::Serializer::ReadableText do6# The described_class API takes a mix of strings and whitespace character counts7let(:indent_string) { '' }8let(:indent_length) { indent_string.length }910let(:default_module_options) do11[12Msf::Opt::RHOSTS,13Msf::Opt::RPORT(3000),14Msf::OptString.new(15'foo',16[true, 'Foo option', 'bar']17),18Msf::OptString.new(19'fizz',20[true, 'fizz option', 'buzz']21),22Msf::OptString.new(23'baz',24[true, 'baz option', 'qux']25),26Msf::OptString.new(27'OptionWithModuleDefault',28[true, 'option with module default', true]29),30Msf::OptFloat.new('FloatValue', [false, 'A FloatValue ', 3.5]),31Msf::OptString.new(32'NewOptionName',33[true, 'An option with a new name. Aliases ensure the old and new names are synchronized', 'default_value'],34aliases: ['OLD_OPTION_NAME']35),36Msf::OptString.new(37'SMBUser',38[true, 'The SMB username'],39fallbacks: ['username']40),41Msf::OptString.new(42'SMBDomain',43[true, 'The SMB username', 'WORKGROUP'],44aliases: ['WindowsDomain'],45fallbacks: ['domain']46)47]48end4950let(:default_advanced_module_options) do51[52Msf::OptEnum.new('DigestAlgorithm', [ true, 'The digest algorithm to use', 'SHA256', %w[SHA1 SHA256] ])53]54end5556let(:default_evasion_module_options) do57[58Msf::OptInt.new('EVASION_TEST_OPTION', [ true, 'The evasion test option'])59]60end6162let(:module_options) { default_module_options }63let(:advanced_module_options) { default_advanced_module_options }64let(:evasion_module_options) { default_evasion_module_options }6566# (see Msf::Exploit::Remote::Kerberos::ServiceAuthenticator::Options#kerberos_auth_options)67def kerberos_auth_options(protocol:, auth_methods:)68mixin = Class.new.extend(Msf::Exploit::Remote::Kerberos::ServiceAuthenticator::Options)69mixin.kerberos_auth_options(protocol: protocol, auth_methods: auth_methods)70end7172let(:aux_mod) do73mod_klass = Class.new(Msf::Auxiliary) do74def initialize75super(76'Name' => 'mock module',77'Description' => 'mock module',78'Author' => ['Unknown'],79'License' => MSF_LICENSE,80'DefaultOptions' => {81'OptionWithModuleDefault' => false,82'foo' => 'foo_from_module',83'baz' => 'baz_from_module'84},85)86end87end8889mod = mod_klass.new90mod.send(:register_options, module_options)91mod.send(:register_advanced_options, advanced_module_options)92mod.send(:register_evasion_options, evasion_module_options)93mock_framework = instance_double(::Msf::Framework, datastore: Msf::DataStore.new)94allow(mod).to receive(:framework).and_return(mock_framework)95mod96end9798let(:aux_mod_with_set_options) do99mod = aux_mod.replicant100mod.framework.datastore['RHOSTS'] = '192.0.2.2'101mod.framework.datastore['FloatValue'] = 5102mod.framework.datastore['foo'] = 'foo_from_framework'103mod.datastore['foo'] = 'new_value'104mod.datastore.unset('foo')105mod.datastore['OLD_OPTION_NAME'] = nil106mod.datastore['username'] = 'username'107mod.datastore['fizz'] = 'new_fizz'108mod109end110111before(:each) do112allow(Rex::Text::Table).to receive(:wrapped_tables?).and_return(true)113end114115describe '.dump_datastore' do116context 'when the datastore is empty' do117it 'returns the datastore as a table' do118expect(described_class.dump_datastore('Table name', Msf::DataStore.new, indent_length)).to match_table <<~TABLE119Table name120==========121122No entries in data store.123TABLE124end125end126127context 'when the datastore has values' do128it 'returns the datastore as a table' do129expect(described_class.dump_datastore('Table name', aux_mod_with_set_options.datastore, indent_length)).to match_table <<~TABLE130Table name131==========132133Name Value134---- -----135DigestAlgorithm SHA256136EVASION_TEST_OPTION137FloatValue 5138NewOptionName139OptionWithModuleDefault false140RHOSTS 192.0.2.2141RPORT 3000142SMBDomain WORKGROUP143SMBUser username144VERBOSE false145WORKSPACE146baz baz_from_module147fizz new_fizz148foo foo_from_framework149username username150TABLE151end152end153end154155describe '.dump_options' do156context 'when missing is false' do157it 'returns the options as a table' do158expect(described_class.dump_options(aux_mod_with_set_options, indent_string, false)).to match_table <<~TABLE159Name Current Setting Required Description160---- --------------- -------- -----------161FloatValue 5 no A FloatValue162NewOptionName yes An option with a new name. Aliases ensure the old and new names are synchronized163OptionWithModuleDefault false yes option with module default164RHOSTS 192.0.2.2 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html165RPORT 3000 yes The target port166SMBDomain WORKGROUP yes The SMB username167SMBUser username yes The SMB username168baz baz_from_module yes baz option169fizz new_fizz yes fizz option170foo foo_from_framework yes Foo option171TABLE172end173end174175context 'when missing is true' do176it 'returns the options as a table' do177expect(described_class.dump_options(aux_mod_with_set_options, indent_string, true)).to match_table <<~TABLE178Name Current Setting Required Description179---- --------------- -------- -----------180NewOptionName yes An option with a new name. Aliases ensure the old and new names are synchronized181TABLE182end183end184185context 'when some options are grouped' do186let(:group_name) { 'group_name' }187let(:group_description) { 'Used for example reasons' }188let(:option_names) { %w[DigestAlgorithm RHOSTS SMBUser SMBDomain] }189let(:group) { Msf::OptionGroup.new(name: group_name, description: group_description, option_names: option_names) }190let(:aux_mod_with_grouped_options) do191mod = aux_mod_with_set_options.replicant192mod.options.add_group(group)193mod194end195196it 'should return the grouped options separate to the rest of the options' do197expect(described_class.dump_options(aux_mod_with_grouped_options, indent_string, false)).to match_table <<~TABLE198Name Current Setting Required Description199---- --------------- -------- -----------200FloatValue 5 no A FloatValue201NewOptionName yes An option with a new name. Aliases ensure the old and new names are synchronized202OptionWithModuleDefault false yes option with module default203RPORT 3000 yes The target port204baz baz_from_module yes baz option205fizz new_fizz yes fizz option206foo foo_from_framework yes Foo option207208209#{group_description}:210211Name Current Setting Required Description212---- --------------- -------- -----------213RHOSTS 192.0.2.2 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html214SMBDomain WORKGROUP yes The SMB username215SMBUser username yes The SMB username216TABLE217end218end219220context 'when there are multiple options groups' do221let(:group_name_1) { 'group_name_1' }222let(:group_description_1) { 'Used for example reasons_1' }223let(:option_names_1) {['RHOSTS']}224let(:group_name_2) { 'group_name_2' }225let(:group_description_2) { 'Used for example reasons_2' }226let(:option_names_2) { %w[SMBUser SMBDomain] }227228let(:group_1) { Msf::OptionGroup.new(name: group_name_1, description: group_description_1, option_names: option_names_1) }229let(:group_2) { Msf::OptionGroup.new(name: group_name_2, description: group_description_2, option_names: option_names_2) }230231let(:aux_mod_with_grouped_options) do232mod = aux_mod_with_set_options.replicant233mod.options.add_group(group_1)234mod.options.add_group(group_2)235mod236end237238it 'should return the grouped options separate to the rest of the options' do239expect(described_class.dump_options(aux_mod_with_grouped_options, indent_string, false)).to match_table <<~TABLE240Name Current Setting Required Description241---- --------------- -------- -----------242FloatValue 5 no A FloatValue243NewOptionName yes An option with a new name. Aliases ensure the old and new names are synchronized244OptionWithModuleDefault false yes option with module default245RPORT 3000 yes The target port246baz baz_from_module yes baz option247fizz new_fizz yes fizz option248foo foo_from_framework yes Foo option249250251#{group_description_1}:252253Name Current Setting Required Description254---- --------------- -------- -----------255RHOSTS 192.0.2.2 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html256257258#{group_description_2}:259260Name Current Setting Required Description261---- --------------- -------- -----------262SMBDomain WORKGROUP yes The SMB username263SMBUser username yes The SMB username264TABLE265end266end267end268269describe '.dump_advanced_options' do270context 'when kerberos options are present' do271let(:advanced_module_options) do272[273*default_advanced_module_options,274*kerberos_auth_options(protocol: 'Winrm', auth_methods: Msf::Exploit::Remote::AuthOption::WINRM_OPTIONS),275]276end277278it 'returns the options as a table' do279expect(described_class.dump_advanced_options(aux_mod_with_set_options, indent_string)).to match_table <<~TABLE280Name Current Setting Required Description281---- --------------- -------- -----------282DigestAlgorithm SHA256 yes The digest algorithm to use (Accepted: SHA1, SHA256)283VERBOSE false no Enable detailed status messages284WORKSPACE no Specify the workspace for this module285Winrm::Auth auto yes The Authentication mechanism to use (Accepted: auto, ntlm, kerberos, plaintext)286287288When Winrm::Auth is kerberos:289290Name Current Setting Required Description291---- --------------- -------- -----------292DomainControllerRhost no The resolvable rhost for the Domain Controller293Winrm::Krb5Ccname no The ccache file to use for kerberos authentication294Winrm::KrbOfferedEncryptionTypes AES256,AES128,RC4-HMAC,DES-CBC-MD5,DES3-CBC-SHA1 yes Kerberos encryption types to offer295Winrm::Rhostname no The rhostname which is required for kerberos - the SPN296TABLE297end298end299300context 'when some options are grouped' do301let(:group_name) { 'group_name' }302let(:group_description) { 'Used for example reasons' }303let(:option_names) { %w[DigestAlgorithm RHOSTS SMBUser SMBDomain] }304let(:group) { Msf::OptionGroup.new(name: group_name, description: group_description, option_names: option_names) }305let(:aux_mod_with_grouped_options) do306mod = aux_mod_with_set_options.replicant307mod.options.add_group(group)308mod309end310311it 'should return the grouped options separate to the rest of the options' do312expect(described_class.dump_advanced_options(aux_mod_with_grouped_options, indent_string)).to match_table <<~TABLE313Name Current Setting Required Description314---- --------------- -------- -----------315VERBOSE false no Enable detailed status messages316WORKSPACE no Specify the workspace for this module317318319#{group_description}:320321Name Current Setting Required Description322---- --------------- -------- -----------323DigestAlgorithm SHA256 yes The digest algorithm to use (Accepted: SHA1, SHA256)324325TABLE326end327end328end329330describe '.dump_evasion_options' do331context 'when kerberos options are present' do332let(:evasion_module_options) do333[334*default_evasion_module_options,335*kerberos_auth_options(protocol: 'Winrm', auth_methods: Msf::Exploit::Remote::AuthOption::WINRM_OPTIONS),336]337end338339it 'returns the options as a table' do340expect(described_class.dump_evasion_options(aux_mod_with_set_options, indent_string)).to match_table <<~TABLE341Name Current Setting Required Description342---- --------------- -------- -----------343EVASION_TEST_OPTION yes The evasion test option344Winrm::Auth auto yes The Authentication mechanism to use (Accepted: auto, ntlm, kerberos, plaintext)345346347When Winrm::Auth is kerberos:348349Name Current Setting Required Description350---- --------------- -------- -----------351DomainControllerRhost no The resolvable rhost for the Domain Controller352Winrm::Krb5Ccname no The ccache file to use for kerberos authentication353Winrm::KrbOfferedEncryptionTypes AES256,AES128,RC4-HMAC,DES-CBC-MD5,DES3-CBC-SHA1 yes Kerberos encryption types to offer354Winrm::Rhostname no The rhostname which is required for kerberos - the SPN355TABLE356end357end358end359360describe '.dump_description' do361context 'when the module description is nil' do362it 'dumps the module description' do363mod = instance_double(364Msf::Module,365description: nil366)367368result = described_class.dump_description(mod, ' ')369expect(result).to match_table <<~TABLE370Description:371372TABLE373end374end375376context 'when the module description has no whitespace' do377it 'dumps the module description' do378mod = instance_double(379Msf::Module,380description: 'this is a module description'381)382383result = described_class.dump_description(mod, ' ')384expect(result).to match_table <<~TABLE385Description:386this is a module description387TABLE388end389end390391context 'when the module description is a single line' do392it 'dumps the module description' do393mod = instance_double(394Msf::Module,395description: %q{ This is a description; with module details etc. }396)397398result = described_class.dump_description(mod, ' ')399expect(result).to match_table <<~TABLE400Description:401This is a description; with module details etc.402403TABLE404end405end406407context 'when the first line has less preceding whitespace than the subsequent lines' do408it 'dumps the module description' do409mod = instance_double(410Msf::Module,411description: 'Listen for a connection. First, the port will need to be knocked from412the IP defined in KHOST. This IP will work as an authentication method413(you can spoof it with tools like hping). After that you could get your414shellcode from any IP. The socket will appear as "closed," thus helping to415hide the shellcode',416)417418result = described_class.dump_description(mod, ' ')419expect(result).to match_table <<~TABLE420Description:421Listen for a connection. First, the port will need to be knocked from422the IP defined in KHOST. This IP will work as an authentication method423(you can spoof it with tools like hping). After that you could get your424shellcode from any IP. The socket will appear as "closed," thus helping to425hide the shellcode426TABLE427end428end429430context 'when the first line has more whitespace than the subsequent lines' do431it 'dumps the module description' do432mod = instance_double(433Msf::Module,434description: %q{435Login credentials to the Motorola WR850G router with436firmware v4.03 can be obtained via a simple GET request437if issued while the administrator is logged in. A lot438more information is available through this request, but439you can get it all and more after logging in.440},441)442443result = described_class.dump_description(mod, ' ')444expect(result).to match_table <<~TABLE445Description:446Login credentials to the Motorola WR850G router with447firmware v4.03 can be obtained via a simple GET request448if issued while the administrator is logged in. A lot449more information is available through this request, but450you can get it all and more after logging in.451TABLE452end453end454455context 'when there are two blank lines in a row' do456it 'dumps the module description' do457mod = instance_double(458Msf::Module,459description: "Run a meterpreter server in Android.\n\nTunnel communication over HTTP"460)461462result = described_class.dump_description(mod, ' ')463expect(result).to match_table <<~TABLE464Description:465Run a meterpreter server in Android.466467Tunnel communication over HTTP468TABLE469end470end471472context 'when the module description spans multiple lines' do473it 'dumps the module description' do474mod = instance_double(475Msf::Module,476description: %q{477This is a description; with module details etc.478479Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer quis mattis lacus. Nam nisi diam, commodo id eu.480481This is a list of important items to consider:482- Item A483- Item B484- Item C485486}487)488489result = described_class.dump_description(mod, ' ')490expect(result).to match_table <<~TABLE491Description:492This is a description; with module details etc.493494Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer quis mattis lacus. Nam nisi diam, commodo id eu.495496This is a list of important items to consider:497- Item A498- Item B499- Item C500501TABLE502end503end504end505end506507508