How to Programmatically Check if SSH Server Allows Password Authentication Without Login Attempt


44 views

When auditing SSH server security configurations, we often need to verify whether password authentication is enabled without actually attempting a login. This is particularly useful for:

  • Security compliance scanning
  • Automated infrastructure testing
  • Pre-deployment configuration checks

The OpenSSH client provides several useful options for this purpose:

ssh -o PreferredAuthentications=none -o PasswordAuthentication=no user@host

This command will:

  1. Attempt connection without trying any authentication method
  2. Reveal the server's supported authentication methods
  3. Exit immediately without prompting for credentials

Here's a robust script that checks password authentication availability:

#!/bin/bash

check_ssh_password_auth() {
    local host=$1
    local output
    output=$(ssh -vvv -o BatchMode=yes -o PreferredAuthentications=none "$host" 2>&1)
    
    if [[ "$output" =~ "password" ]]; then
        echo "Password authentication is ENABLED on $host"
        return 1
    else
        echo "Password authentication is DISABLED on $host"
        return 0
    fi
}

# Usage example
if check_ssh_password_auth "example.com"; then
    echo "Server meets security requirements"
else
    echo "WARNING: Server allows insecure password authentication"
    exit 1
fi

If you have access to the server configuration, you can directly check the sshd_config file:

grep -Ei '^PasswordAuthentication (yes|no)' /etc/ssh/sshd_config

However, this requires privileged access and doesn't account for runtime overrides.

For scanning multiple servers, consider this Python approach:

import paramiko
import socket

def check_ssh_password_auth(host, port=22):
    try:
        transport = paramiko.Transport((host, port))
        transport.connect()
        auth_methods = transport.get_security_options().aslist()
        transport.close()
        
        return 'password' in auth_methods
    except (paramiko.SSHException, socket.error):
        return False

# Example usage
servers = ['host1.example.com', 'host2.example.com']
for server in servers:
    if check_ssh_password_auth(server):
        print(f"{server}: Password auth ENABLED")
    else:
        print(f"{server}: Password auth DISABLED")

When implementing these checks:

  • Be mindful of connection rate limits
  • Respect firewall and intrusion detection systems
  • Consider using dedicated monitoring accounts
  • Always obtain proper authorization before scanning

If you encounter problems:

  • Verify network connectivity and SSH port accessibility
  • Check for host key verification prompts (use -o StrictHostKeyChecking=no cautiously)
  • Ensure your testing account exists on the target system

When auditing SSH server security configurations, we often need to verify whether password authentication is enabled - a potential security risk in production environments. The challenge lies in performing this check without:

  • Triggering failed login alerts
  • Leaving authentication logs
  • Waiting for full authentication timeout

Here's a reliable method using OpenSSH client capabilities:

ssh -o PreferredAuthentications=none -o PasswordAuthentication=no user@hostname 2>&1 | \
grep -q "password" && echo "Password auth enabled" || echo "Password auth disabled"

Let's analyze the components:

  • -o PreferredAuthentications=none: Explicitly tells SSH not to try any auth methods
  • -o PasswordAuthentication=no: Prevents actual password prompt
  • 2>&1: Redirects stderr to stdout for parsing

For scripting environments, here's a complete bash function:

check_ssh_password_auth() {
    local host=$1
    local user=${2:-$(whoami)}
    
    if ssh -o PreferredAuthentications=none \
           -o PasswordAuthentication=no \
           -o ConnectTimeout=5 \
           "$user@$host" 2>&1 | grep -q "password"; then
        echo "WARNING: Password authentication enabled on $host"
        return 1
    else
        echo "SECURE: Password authentication disabled on $host"
        return 0
    fi
}

For large-scale audits across multiple servers:

#!/bin/bash

servers=("web1.example.com" "db1.example.com" "loadbalancer.example.com")
results=()

for server in "${servers[@]}"; do
    if ssh -o PreferredAuthentications=none \
           -o PasswordAuthentication=no \
           -o ConnectTimeout=3 \
           "admin@$server" 2>&1 | grep -q "password"; then
        results+=("$server: INSECURE")
    else
        results+=("$server: SECURE")
    fi
done

printf '%s\n' "${results[@]}"

Be aware of these edge cases:

  • Some SSH servers might timeout differently
  • Banner messages may contain the word "password" creating false positives
  • Rate limiting could temporarily block your IP

For servers where SSH access isn't available:

nmap -p 22 --script ssh-auth-methods target_host

This NSE script provides detailed authentication method information without attempting full login.