Skip to content

Files

Latest commit

f948266 · Apr 18, 2025

History

History
512 lines (359 loc) · 20 KB

ssh-and-scp.md

File metadata and controls

512 lines (359 loc) · 20 KB

SSH & SCP

{% hint style="success" %} Hack Responsibly.

Always ensure you have explicit permission to access any computer system before using any of the techniques contained in these documents. You accept full responsibility for your actions by applying any knowledge gained here. {% endhint %}

SSH

sshd

SSH should already be installed on most Linux-based computers, but you may need to start the SSH daemon (sshd) if the computer has never accepted incoming SSH connections before.

sudo systemctl start sshd

To have the SSH daemon start each time you reboot your computer, use this command:

sudo systemctl enable sshd

SSH Config

The $HOME/.ssh/config file allows for custom configurations and aliases to be specified for SSH connection profiles. The example below sets up TCPKeepAlive and ServerAliveInterval for all hosts, and sets up aliases for a few servers.

Host *
    ServerAliveInterval 60
    TCPKeepAlive no

Host jumpBox-1
    HostName jumpbox-1.com
    User jumper
    IdentityFile /home/kali/.ssh/to_jumpbox-1.key

Host jumpBox-2
    HostName sup.er.long.complex.aws.dns.name.com
    User jumpboxAdmin
    IdentityFile /home/kali/.ssh/to_jumpbox-2.key
    ProxyJump jumpBox-1

Host target-1
    HostName 192.168.221.32
    User piUser
    IdentityFile /home/kali/.ssh/to_target-1.key
    ProxyJump jumpBox-2

In the case of the SSH server side, replace ServerAliveInterval with ClientAliveInterval and put it in the file /etc/ssh/sshd_config. This is especially useful for reverse tunnels.

The above configuration shows an example of allowing a user to use a simplified command such asssh jumpbox-1 in place of having to type out user@hostName -i /path/to/keyfile and supplies the relevant information automatically. This reduces the need for remembering usernames, IPs, or long and complex DNS names.

ProxyJump

By having SSH keys for each of our jump boxes and the target device on our local machine, we can simplify the process of logging in through each machine quite a bit. The ProxyJump directive signifies which machine you need to jump through to get to the next machine in the proxy chain.

This simple change allows a user to simply give the command ssh target-1, wait a bit for all of the connections to be made, and pop a shell on the target-1 device.

Keep Alive

If you want to set the keep alive for the server, add this to /etc/ssh/sshd_config:

ClientAliveInterval 60
ClientAliveCountMax 2

ClientAliveInterval: Sets a timeout interval in seconds after which if no data has been received from the client, sshd(8) will send a message through the encrypted channel to request a response from the client.

ClientAliveCountMax: Sets the number of client alive messages (see below) which may be sent without sshd(8) receiving any messages back from the client. If this threshold is reached while client alive messages are being sent, sshd will disconnect the client, terminating the session.

  • ... look in "man sshd_config" for the server portion running the ssh daemon, not the client config. – Jeff Davenport Jul 29 '16 at 22:35
  • Should I use ClientAliveInterval to let the server check for client alive, or should I let the client "ping" the server with ServerAliveInterval repeatedly? Both seems not to make sense – qrtLs Jun 2 '17 at 14:08
  • Only set the ClientAliveInterval on the server if you want the server to disconnect on dead connections that do not respond, and you can customize how often and when that happens. – Jeff Davenport Jul 25 '17 at 20:22

SSH Keys

SSH keys are a secure way to authenticate to remote systems, either as a second authentication factor or as a replacement for passwords. Below is a guide to generating, using, and managing SSH keys effectively.

Generating SSH Keys

To generate a new SSH key for remote access, use the ssh-keygen command with the desired algorithm and key size:

# Generate an RSA key with 4096 bits
ssh-keygen -t rsa -b 4096

# Generate an ECDSA key with 521 bits
ssh-keygen -t ecdsa -b 521

# Generate an Ed25519 key (recommended for modern use)
ssh-keygen -t ed25519

Key Algorithms Comparison

Algorithm Key Size (bits) Strength Pros Cons
RSA 2048/4096 Strong (4096 recommended) Widely supported, secure Larger key size, slower
DSA 1024 Weak Legacy support Deprecated, insecure
ECDSA 256/384/521 Strong Smaller keys, faster Requires good randomness
Ed25519 Fixed (256) Very Strong Fast, secure, small key size Limited client compatibility

Using SSH Keys

  1. Generate a Key Pair: Use ssh-keygen as shown above.
  2. Copy Public Key to Remote Host:
    ssh-copy-id -i $key_file $user@$remote_host
  3. Connect Using the Key:
    ssh -i $key_file $user@$remote_host

Key File Details

To inspect the details of a key file:

  • Public key:
    openssl rsa -in $priv_key -pubout -out $pub_key_name
  • Private key:
    openssl rsa -noout -text -in key.private

Notes on Key Usage

  • Permissions: Ensure private keys have proper permissions:
    chmod 600 $key_file
  • AWS Compatibility: AWS requires keys without -----BEGIN PUBLIC KEY----- and -----END PUBLIC KEY----- headers.
    ssh-keygen -f PublicKey.pub -i -mPKCS8

Extracting Public Key from Private Key

To extract the public key from a private key:

openssl rsa -in $priv_key -pubout -out $pub_key_name

Generating Public Key from Private Key

To generate a public key from a private key:

ssh-keygen -y -f ~/.ssh/id_rsa > ~/.ssh/id_rsa.pub

Note: The comment of the public key is lost during this process. You may need to manually append a comment to the first line of the public key file (ex: ~/.ssh/id_rsa.pub). Append a comment to the first line with a space between the comment and key data. An example public key is shown truncated below.

Example:

ssh-rsa <key_data AAAA..snipped../VqDjtS5> user@hostname

Summary: SSH/SCP into target using a keyfile

  1. From the attacker_machine, generate a keypair: ssh-keygen -t ed25519
  2. Copy the contents from the public key $keyfile.pub into the .ssh/authorized_keys file of the target_machine
  3. Connect with the argument -i $keyfile

Remote Command Execution

Run a command on remote system without a shell through SSH by appending it to the end of the line, or, run multiple commands at once with a "Herefile". HERE can be anything, but it must begin and end with the same word.

Single Command:

ssh $user@$hostname $command_to_run

Multiple Commands:

ssh $user@$hostname << HERE
 $command1
 $command2
HERE

SCP

There are three main uses of SCP: to pull files from a remote host, to push files to a remote host, and to copy files between two remote hosts.

Copy from remote host to local file:

scp $username@ip:$remote_file $local_directory

Copy local file to remote host:

$ scp $local_file $username@$ip:$directory

Copy local directory to remote directory:

scp -r $local_directory $username@$ip:$remote_directory

Copy a file from one remote host to another:

scp $username@$host1:$directory/$file $username@$host2:$directory2

Improve scp performance (using blowfish algorithm):

scp -c blowfish $local_file $username@$ip:$directory

Use keyfile to login to remote host

(-i must be the first parameter)

scp -i $keyfile [other parameters]

Local Forward Tunnels

Local forward tunnels allow you to forward a port from your local machine to a remote server. This is useful for accessing services on a remote server that are not directly accessible from your local machine.

Setting Up a Local Forward Tunnel

To set up a local forward tunnel, use the -L option with the ssh command. The syntax is as follows:

ssh -L [local_port]:[remote_host]:[remote_port] [user]@[remote_server]
  • local_port: The port on your local machine that you want to forward.
  • remote_host: The host on the remote server to which you want to forward traffic.
  • remote_port: The port on the remote host to which you want to forward traffic.
  • user: The username for the remote server.
  • remote_server: The address of the remote server.

Example

Suppose you want to access a web application running on port 8080 of a target_machine through an intermediate SSH server (intermediate_server). You can set up a local forward tunnel as follows:

ssh -L 8080:target_machine:8080 user@intermediate_server

After running this command, you can access the web application by navigating to http://localhost:8080 in your web browser.

Notes

  • The local port (e.g., 8080) must not be in use on your local machine.
  • You can use -N to prevent the SSH session from executing commands, keeping the tunnel open:
ssh -L 8080:target_machine:8080 user@intermediate_server -N
  • Use -f to run the SSH session in the background:
ssh -L 8080:target_machine:8080 user@intermediate_server -N -f

Local forward tunnels are particularly useful for securely accessing internal services or databases on a remote network.

Reverse Tunnels

  • Let's assume that the target_machine's IP is 192.168.20.55 (Linux box that you want to access).
  • You want to access it from the local_machine with IP 178.27.99.99.
  • target_machine <- |NAT| <- local_machine
  • SSH from the target_machine to the local_machine (with public IP) using the command below:
ssh -R 19999:localhost:22 sourceuser@local_machine

{% hint style="info" %} * port 19999 can be any unused local port. {% endhint %}

  1. Now you can SSH from local_machine to target_machine through SSH tunneling:
ssh localhost -p 19999
  1. 3rd party servers can also access target_machine through local_machine.

target_machine <- |NAT| <- local_machine <- Target web server

3.1 From the Target web server:

ssh sourceuser@local_machine

3.2 After the successful login to local_machine:

ssh localhost -p 19999

{% hint style="info" %} * the connection between target_machine and local_machine must be alive at all times. Tip: you may run a command (e.g. watch, top) on target_machine to keep the connection active. {% endhint %}

Dynamic Tunnels

Dynamic tunnels allow you to create a SOCKS proxy on a remote machine, enabling dynamic port forwarding. This is particularly useful for accessing multiple services on a remote network without setting up individual tunnels for each service.

Setting Up a Dynamic Tunnel

To set up a dynamic reverse tunnel, use the -D option with the ssh command. The syntax is as follows:

ssh -D [local_port] [user]@[remote_server]
  • local_port: The port on your local machine that will act as the SOCKS proxy.
  • user: The username for the remote server.
  • remote_server: The address of the remote server.

Example

Suppose you want to create a SOCKS proxy on port 1080 of your local machine to access services on a remote network through an intermediate SSH server (intermediate_server). You can set up a dynamic reverse tunnel as follows:

ssh -D 1080 user@intermediate_server

After running this command, configure your applications (e.g., web browsers) to use localhost:1080 as a SOCKS proxy. This will route all traffic through the SSH tunnel to the remote network.

Notes

  • The local port (e.g., 1080) must not be in use on your local machine.
  • You can use -N to prevent the SSH session from executing commands, keeping the tunnel open:
ssh -D 1080 user@intermediate_server -N
  • Use -f to run the SSH session in the background:
ssh -D 1080 user@intermediate_server -N -f

Dynamic tunnels are particularly useful for scenarios where you need to access multiple services on a remote network without knowing the specific ports in advance.

Using Dynamic Tunnels with Proxychains and Other Applications

Dynamic tunnels can be used in conjunction with tools like proxychains or by configuring a browser's proxy settings to route traffic through the SOCKS proxy created by the tunnel. This allows you to access remote services as if they were local.

Using Proxychains

proxychains is a tool that forces any TCP connection made by a given application to go through a proxy, such as the SOCKS proxy created by a dynamic reverse tunnel.

  1. Install proxychains if it is not already installed:

    sudo apt install proxychains
  2. Edit the proxychains configuration file (usually located at /etc/proxychains.conf) to add the SOCKS proxy:

    socks5  127.0.0.1 1080
    
  3. Use proxychains to run any application through the proxy. For example, to use curl:

    proxychains curl http://example.com

Configuring a Browser

To use the SOCKS proxy with a web browser:

  1. Open your browser's network or proxy settings.
  2. Set the proxy type to SOCKS5.
  3. Enter 127.0.0.1 as the proxy address and 1080 as the port (or the port you specified when setting up the dynamic tunnel).
  4. Save the settings and browse as usual. All traffic will be routed through the SOCKS proxy.

Using Built-in Proxy Options in Tools

Many command-line tools have built-in options to use a proxy. For example:

  • curl:

    curl --socks5 127.0.0.1:1080 http://example.com
  • wget:

    wget --execute="socks_proxy = 127.0.0.1:1080" http://example.com
  • git: Configure Git to use the SOCKS proxy:

    git config --global http.proxy socks5://127.0.0.1:1080

These configurations allow you to leverage the dynamic reverse tunnel for a wide range of applications, enhancing your ability to access remote resources securely and efficiently.

Dynamic Reverse Tunnels

A bonus feature added in OpenSSH version 7.6 (released in late 2017) is the ability to create Dynamic Reverse Tunnels. The feature works as long as the client supports it, even if the server is running an older version.

If you're performing a security audit and need to access an internal network from outside, but firewalls block inbound SSH connections, you can use a dynamic reverse tunnel to securely route traffic inside.

This allows tools like Burp Suite or Nessus to scan internal assets even when direct access isn’t possible.

Example command (-R $port without other port/ip arguments creates a dynamic reverse tunnel):

ssh user@target_machine -R 2222

Troubleshooting

Troubleshooting Connection Drops

  • If connection drops immediately after connecting:

    • Don't use bash for this session, try another shell such as dash (or /bin/sh):
      ssh 127.0.0.1 /bin/dash
    • Use bash with command options to disable processing startup files (.profile, .bashrc):
      ssh 127.0.0.1 "bash --noprofile --norc"
  • Permission Denied Errors:

    • Issue: Encountering "Permission denied" when trying to SSH or SCP.
    • Workaround: Ensure the private key file has the correct permissions:
      chmod 600 ~/.ssh/id_rsa
      Verify the username and hostname are correct, and ensure the public key is added to the ~/.ssh/authorized_keys file on the remote server.
  • Connection Timeout:

    • Issue: SSH connection times out.
    • Workaround: Check if the remote server is reachable using ping or traceroute. Ensure the SSH port (default 22) is open and not blocked by a firewall. Use the -v flag with SSH for verbose output to debug:
      ssh -v user@hostname
  • Host Key Verification Failed:

    • Issue: SSH fails due to a changed host key.
    • Workaround: This usually happens if the server's SSH key has changed. Remove the old key from the ~/.ssh/known_hosts file:
      ssh-keygen -R hostname
      Then reconnect to add the new key.
  • Too Many Authentication Failures:

    • Issue: SSH fails with "Too many authentication failures".
    • Workaround: This can occur if the SSH client tries multiple keys before the correct one. Use the -i option to specify the correct key explicitly:
      ssh -i ~/.ssh/id_rsa user@hostname
  • Broken Pipe Errors:

    • Issue: SSH session disconnects with a "broken pipe" error.
    • Workaround: Increase the ServerAliveInterval and ServerAliveCountMax settings in your SSH config to keep the connection alive:
      Host *
          ServerAliveInterval 60
          ServerAliveCountMax 5
      

Additional Common Issues and Workarounds

  • SCP File Transfer Fails:

    • Issue: SCP fails with "No such file or directory".
    • Workaround: Double-check the file paths on both the local and remote systems. Use absolute paths to avoid ambiguity.
    • Another common issue is not having the correct file/folder permissions to read and/or write the files in question.
  • SSH Hangs on Connection:

    • Issue: SSH hangs indefinitely when trying to connect.
    • Workaround: Use the -vvv flag for detailed debugging output. Check for DNS resolution issues and try connecting using the server's IP address instead of the hostname.
  • Key Mismatch Errors:

    • Issue: Public key authentication fails due to a key mismatch.
    • Workaround: Ensure the correct private key is being used and that the corresponding public key is present in the ~/.ssh/authorized_keys file on the remote server. Verify the key format and regenerate the key pair if necessary.

Resources

If you like this content and would like to see more, please consider buying me a coffee!