Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract reusable core session commands #18516

Merged
merged 5 commits into from
Nov 15, 2023

Conversation

dwelch-r7
Copy link
Contributor

Refactoring some commands out of the Meterpreter specific command dispatcher into a new generic Sessions command dispatcher that all sessions will be able to leverage.

The common commands I pulled out were: help background sessions resource irb pry exit
I didn't see any others that made a tonne of sense to move out but if there's any you'd like to see added feel free to dorp a comment calling it out

Also added a bunch of tests that should let us make sure any new session types have correctly implemented the api that the session command dispatcher is expecting

@dwelch-r7 dwelch-r7 marked this pull request as draft November 6, 2023 16:04
Copy link
Contributor

@bcoles bcoles left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code quality issues with existing code

Comment on lines 190 to 192
end
# let's check to see if it's in the scripts/resource dir (like when tab completed)
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where's end's friend? he shares an indentation level with another end.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

huh, most of this was copied over from the meterpreter command_dispatcher, I swear I rubocopped this but there's definitely still issues, I'll get it sorted cheers

Comment on lines 193 to 198
if good_res
client.console.load_resource(good_res)
else
print_error("#{res} is not a valid resource file")
next
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if good_res
client.console.load_resource(good_res)
else
print_error("#{res} is not a valid resource file")
next
end
unless good_res
print_error("#{res} is not a valid resource file")
next
end
client.console.load_resource(good_res)

Comment on lines +207 to +208
return tab_complete_filenames(str, words)
elsif (!(words[1]) || !words[1].match(%r{^/}))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return tab_complete_filenames(str, words)
elsif (!(words[1]) || !words[1].match(%r{^/}))
return tab_complete_filenames(str, words)
end
if (!(words[1]) || !words[1].match(%r{^/}))

::File.file?(path) and ::File.readable?(path)
end
end
rescue Exception
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dwelch-r7 dwelch-r7 force-pushed the core-session-commands-tests branch from 8303d8c to 06e066b Compare November 6, 2023 16:31
spec/lib/msf/base/sessions/command_shell_spec.rb Outdated Show resolved Hide resolved

COMMANDS = %i[help background sessions resource shell download upload source irb pry]

RSpec.describe Msf::Sessions::CommandShell do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be nice to clean these up to align with some of the conventions from https://www.betterspecs.org/

this should follow the conventions of https://www.betterspecs.org/#describe

i.e.

describe '.type' do
 # ...
end

describe '.can_cleanup_files' do
  # ...
end

# ... etc ...

And ensure context blocks follow the naming convention of context 'when ...' do

https://www.betterspecs.org/#contexts

datastore
end
it 'should execute the script' do
is_expected.to receive(:execute_script).with(initial_auto_run_script)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a blocker; expect to receive is an antipattern as it doesn't follow the normal pattern of arrange/act/assert

https://automationpanda.com/2020/07/07/arrange-act-assert-a-pattern-for-writing-good-tests/

i.e. prefer adding a expect(...).to have_received(...) after the 'act', instead of expect(...). to receive(...) before your 'act'

@dwelch-r7 dwelch-r7 force-pushed the core-session-commands-tests branch from 06e066b to c7e0e09 Compare November 6, 2023 16:34
session_id = args[0].to_i
if session_id <= 0
print_status 'Invalid session id'
cmd_sessions_help
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need a return?

Copy link
Contributor

@jvoisin jvoisin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to normalise the return part in cmd_…_help: do we want a return false after it? do we want to return cmd_…_help? do we want a naked return instead?

@@ -30,7 +30,7 @@ class CommandShell
include Rex::Ui::Text::Resource

@@irb_opts = Rex::Parser::Arguments.new(
'-h' => [false, 'Help menu.' ],
['-h', '--help'] => [false, 'Help menu.' ],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
['-h', '--help'] => [false, 'Help menu.' ],
['-h', '--help'] => [false, 'Help menu.'],

# One arg, and args[1] => '-h' '-H' 'help'
return cmd_sessions_help
if args.length == 1 && (args[0] == '-h' || args[0] == '--help')
# One arg, and args[0] => '-h' '--help'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# One arg, and args[0] => '-h' '--help'

I don't think this comment is necessary.

include Rex::Ui::Text::DispatcherShell::CommandDispatcher

@@irb_opts = Rex::Parser::Arguments.new(
%w[-h --help] => [false, 'Help menu.' ],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
%w[-h --help] => [false, 'Help menu.' ],
%w[-h --help] => [false, 'Help menu.'],

Comment on lines +49 to +57
#
# Terminates the session.
#
def cmd_exit(*args)
print_status("Shutting down session: #{client.sid}")
client.exit
end

alias cmd_quit cmd_exit
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A session can be terminated, exit'ed, shut down and quit'ted. It would be nice to reduce the amount of terms for this action I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't necessarily disagree but I don't think it belongs in this PR, this is just a bit of a refactor and moving things around, the intention is not to alter the way someone would interact with a session here

end

print_status('Starting Pry shell...')
print_status("You are in the \"client\" (session) object\n")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
print_status("You are in the \"client\" (session) object\n")
print_status('You are in the "client" (session) object')
print_line

end

def cmd_sessions(*args)
if args.empty? || args[0].to_i == 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if args.empty? || args[0].to_i == 0
if args.empty? || args[0].to_i == 0 || args.include?('-h') || args.include?('--help')

@dwelch-r7 dwelch-r7 marked this pull request as ready for review November 8, 2023 11:34
if args.length != 1
# More than one argument
session_id = args[0].to_i
if session_id <= 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we check if this works the same as before when provided with negative session ids?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dwelch-r7 Is there anything actionable here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the previous implementation didn't accept negative session IDs so it's a nice to have but I don't think we should block the PR on it

@dwelch-r7 dwelch-r7 mentioned this pull request Nov 14, 2023
10 tasks
@adfoster-r7
Copy link
Contributor

adfoster-r7 commented Nov 14, 2023

Some of the remaining comments are about existing code that's just been shuffled, will treat as not a blocker for now

@adfoster-r7 adfoster-r7 merged commit e011fbe into rapid7:master Nov 15, 2023
32 checks passed
@adfoster-r7 adfoster-r7 added the rn-no-release-notes no release notes label Nov 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
rn-no-release-notes no release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants