Skip to content

Conversation

@dwelch-r7
Copy link
Contributor

@dwelch-r7 dwelch-r7 commented Nov 18, 2025

Resolves #14902

Combines the ssh_login and ssh_login_pubkey modules for an improved user experience

There will be an accompanying Pro PR so I will draft this until we're sure Pro works with these changes

my setup for testing can be found here #20546

Verification Steps

  • Run the ssh_login module and gain a session with username/password
  • Run the module again and gain a session with a non-password protected private key (via KEY_PATH and PRIVATE_KEY)
  • Run the module again and gain a session with a password protected private key (via KEY_PATH and PRIVATE_KEY)


scanner.verbosity = :debug if datastore['SSH_DEBUG']

scanner.scan! do |result|
Copy link
Contributor Author

Choose a reason for hiding this comment

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

realising this section is very similar between the two login methods bar the slight different in printing, I can probably DRY this up too

@dwelch-r7 dwelch-r7 force-pushed the combine-ssh-login-modules branch from 2eb18cc to b29aba1 Compare November 18, 2025 16:16
@smcintyre-r7 smcintyre-r7 self-assigned this Nov 18, 2025
@dwelch-r7 dwelch-r7 force-pushed the combine-ssh-login-modules branch from b29aba1 to 95e62cf Compare November 19, 2025 11:59
@dwelch-r7 dwelch-r7 force-pushed the combine-ssh-login-modules branch from 95e62cf to c461a1b Compare November 27, 2025 12:54
@dwelch-r7 dwelch-r7 marked this pull request as ready for review November 27, 2025 12:54
@ip = ip
print_brute :ip => ip, :msg => 'Starting bruteforce'

if datastore['USER_FILE'].blank? && datastore['USERNAME'].blank? && datastore['USERPASS_FILE'].blank?

Choose a reason for hiding this comment

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

If you want to avoid chaining && maybe something like?

Suggested change
if datastore['USER_FILE'].blank? && datastore['USERNAME'].blank? && datastore['USERPASS_FILE'].blank?
if datastore.values_at('USER_FILE', 'USERNAME', 'USERPASS_FILE').all?(&:blank?)

@cpomfret-r7
Copy link
Contributor

cpomfret-r7 commented Dec 2, 2025

My testing

Created a keypair for testing: ssh-keygen -t ed25519 -C "email@example.com"

Username & Password

Setup SSH server

docker run -e PASSWORD_ACCESS=true -e USER_PASSWORD=password -e USER_NAME=username -e LOG_STDOUT=true -p 2222:2222 lscr.io/linuxserver/openssh-server:latest

Confirmed session created with:

run RHOSTS=127.0.0.1 RPORT=2222 USERNAME=username PASSWORD=password

or put username/password in files:

run RHOSTS=127.0.0.1 RPORT=2222 USER_FILE=./userfile PASS_FILE=./passfile

or put username/password in file on same line, separated by space:

run RHOSTS=127.0.0.1 RPORT=2222 USERPASS_FILE=./userpass

Key based access

Setup SSH server. For some reason I could not get PUBLIC_KEY_FILE to work, so I quoted the public key directly:

 docker run -e PASSWORD_ACCESS=false -e USER_NAME=username -e PUBLIC_KEY='ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMSd0qRXKH6o3lgqEanN6cvr5URCubmo7uL4ahFHfw0e email@example.com'  -e LOG_STDOUT=true -p 2222:2222 lscr.io/linuxserver/openssh-server:latest

Confirmed session created with KEY_PATH:

run RHOSTS=127.0.0.1 RPORT=2222 USERNAME=username KEY_PATH=~/.ssh/id_ed25519

Confirmed session created with KEY_PATH + password protected keypair (recreate a keypair and set a passphrase:

run RHOSTS=127.0.0.1 RPORT=2222 USERNAME=username KEY_PATH=~/.ssh/id_ed25519 KEY_PASS=passphrase

Also confirmed key and password auth works via PRO

@cpomfret-r7
Copy link
Contributor

Questions

  • Is createsession=true the default? I didn't specify this and sessions were created
  • I couldn't work out how to set the PRIVATE_KEY option

'PASSWORD' => result.credential.private
'USERNAME' => result.credential.public
}
if used_key
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd extract the merge from the conditional because we're doing it in both branches e.g.

auth_type_options = if used_key
  {
    'PASSWORD' => nil
  }
else
  {
    'PASSWORD' => result.credential.private,
    'PRIVATE_KEY' => nil,
    'KEY_FILE' => nil
  }
end

base_options = {
  'USERPASS_FILE' => nil,
  'USER_FILE' => nil,
  'PASS_FILE' => nil,
  'USERNAME' => result.credential.public
}.merge(auth_type_options)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Consolidate ssh_login_pubkey and ssh_login modules

4 participants