Securing SSH Access by Disabling PermitEmptyPasswords with a Bash Script 

Ensuring secure access to servers is a top priority for IT professionals and Managed Service Providers (MSPs). A significant aspect of server security is managing SSH configurations to prevent unauthorized access. One critical security measure is to disable the PermitEmptyPasswords option in OpenSSH, which prevents users from logging in with an empty password. This post explores a Bash script designed to enforce this configuration, ensuring enhanced security for Linux systems.

Background

OpenSSH is a widely used protocol for secure remote server management. By default, the PermitEmptyPasswords option is set to “no,” but it’s essential to verify and enforce this setting to mitigate risks associated with misconfigured or overlooked setups. IT professionals managing multiple systems might overlook this detail, leaving servers vulnerable. This script provides an automated solution, ensuring compliance with best practices by explicitly disabling empty password logins.

For MSPs and administrators handling numerous servers, this script simplifies SSH hardening, offering a quick, reliable way to enhance security without manual intervention.

The Script:

#!/usr/bin/env bash

# Description: Explicitly disables PermitEmptyPasswords in OpenSSH.
# By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use.
# Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. 
# Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. 
# Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. 
# Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. 
# Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. 
# Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. 
# EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).
#
# PermitEmptyPasswords defaults to no when not specified in the sshd_config file.
# This script will ensure that it is set to no to prevent SSH from accepting empty passwords.
#
# Links: https://man.openbsd.org/sshd_config#PermitEmptyPasswords
#
# Release Notes: Initial Release

# Logs an error message and exits with the specified exit code
die() {
    local _ret="${2:-1}"
    echo "$1" >&2
    exit "${_ret}"
}

# Check that we are running as root
if [[ $EUID -ne 0 ]]; then
    die "[Error] This script must be run as root." 1
fi

_should_reload="false"

# Check if the sshd_config file exists
if [[ -f /etc/ssh/sshd_config ]]; then
    # Check if the PermitEmptyPasswords option is already set to no
    if grep -q "^PermitEmptyPasswords no" /etc/ssh/sshd_config; then
        echo "[Info] PermitEmptyPasswords is already set to no."
        _should_reload="false"
    elif grep -q "^PermitEmptyPasswords yes" /etc/ssh/sshd_config; then
        # First check if the option is not commented out and set to yes
        # Then set the PermitEmptyPasswords option to no
        sed -i 's/^PermitEmptyPasswords.*/PermitEmptyPasswords no/' /etc/ssh/sshd_config
        echo "[Info] PermitEmptyPasswords set to no."
        _should_reload="true"
    elif grep -q "^#PermitEmptyPasswords" /etc/ssh/sshd_config; then
        # First check if the option is commented out
        # Then set the PermitEmptyPasswords option to no
        sed -i 's/^#PermitEmptyPasswords.*/PermitEmptyPasswords no/' /etc/ssh/sshd_config
        echo "[Info] PermitEmptyPasswords set to no, as it was commented out."
        _should_reload="true"
    else
        # Append the PermitEmptyPasswords option to the end of the sshd_config file
        # If the past checks have not found the option, appending it will ensure that it is set to no
        echo "PermitEmptyPasswords no" >>/etc/ssh/sshd_config
        echo "[Info] PermitEmptyPasswords set to no at the end of the sshd_config file."
        _should_reload="true"
    fi

    # Check that this system is running systemd-based
    _type=$(
        # Get the type of init system
        file /sbin/init 2>/dev/null | awk -F/ '{print $NF}' 2>/dev/null
    )
    if [[ "${_type}" == "systemd" ]] && [ "$(command -v systemctl)" ]; then
        echo "[Info] Reloading ${sshd_service} service..."
        # Find the sshd service
        sshd_service=$(
            # Get the ssh service, if two are found use the first one. Likely the first one is a symlink to the actual service file.
            systemctl list-unit-files | grep -E "^(sshd|ssh|openssh-server)\.service" | awk -F' ' '{print $1}' | head -n 1
        )
        if [[ -z "${sshd_service}" ]]; then
            die "[Error] sshd service is not available. Please install it and try again." 1
        fi
        # Check that ssh service is enabled
        if systemctl is-enabled "${sshd_service}" >/dev/null; then
            echo "[Info] ${sshd_service} is enabled."
        else
            die "[Info] ${sshd_service} is not enabled. When enabled and started, PermitEmptyPasswords will be set to no." 0
        fi
        # Check that ssh service is running
        if systemctl is-active "${sshd_service}" >/dev/null; then
            echo "[Info] ${sshd_service} is running."
            if [[ "${_should_reload}" == "true" ]]; then
                # Reload sshd.service
                if systemctl reload "${sshd_service}"; then
                    echo "[Info] sshd service configuration reloaded."
                else
                    die "[Error] Failed to reload ${sshd_service}. Please try again." 1
                fi
            else
                echo "[Info] sshd service configuration will not be reloaded as there is no need to do so."
            fi
        else
            echo "[Info] ${sshd_service} is not running."
        fi
    else
        echo "[Info] Restarting sshd service..."
        # Check that the service command is available
        if ! [ "$(command -v service)" ]; then
            die "[Error] The service command is not available. Is this an initd type system (e.g. SysV)? Please try again." 1
        fi
        # Find the sshd service
        sshd_service=$(
            # Get the list of services
            service --status-all | awk -F' ' '{print $NF}' | grep sshd
        )
        if [[ -z "${sshd_service}" ]]; then
            die "[Error] sshd service is not available. Please install it and try again." 1
        fi
        if [[ "${_should_reload}" == "true" ]]; then
            # Restart sshd service
            if service "${sshd_service}" restart; then
                echo "[Info] sshd service restarted."
            else
                die "[Error] Failed to restart sshd service. Please try again." 1
            fi
        else
            echo "[Info] sshd service configuration will not be restarted as there is no need to do so."
        fi
    fi
else
    die "[Error] The sshd_config file does not exist." 1
fi

 

Save time with over 300+ scripts from the NinjaOne Dojo.

Get access today.

Detailed Breakdown

This Bash script automates the process of explicitly setting PermitEmptyPasswords to “no” in the SSH configuration file (/etc/ssh/sshd_config). Below is a step-by-step breakdown of how the script operates:

1. Check for Root Privileges

The script begins by verifying if it is being run as the root user, as modifying SSH configurations requires elevated permissions. If not, it terminates with an error.

bash

Copy code

if [[ $EUID -ne 0 ]]; then
die “[Error] This script must be run as root.” 1
fi

2. Identify the Configuration File

The script checks for the existence of /etc/ssh/sshd_config. If this file is missing, it exits with an error, as the script cannot proceed without the SSH configuration file.

3. Modify PermitEmptyPasswords Setting

The script inspects the file for the PermitEmptyPasswords directive:

  • If the directive is set to “no,” no changes are made.
  • If set to “yes,” it is replaced with “no.”
  • If commented out, the script uncomments and sets it to “no.”
  • If the directive is missing entirely, it appends PermitEmptyPasswords no to the file.

4. Reload SSH Service

The script determines the system’s init system (systemd or init.d) to reload or restart the SSH service appropriately. It ensures the changes are applied without disrupting ongoing SSH sessions.

5. Error Handling

Comprehensive error handling ensures that the script gracefully exits if it encounters issues such as missing commands, disabled services, or unsupported init systems.

Potential Use Cases

Hypothetical Scenario

An IT administrator managing a fleet of servers notices that one server is allowing SSH access with empty passwords. Manually inspecting and modifying configuration files across all servers would be time-consuming. By deploying this script through automation tools like Ansible or directly via SSH, the administrator ensures that all servers enforce the PermitEmptyPasswords no setting consistently and efficiently.

Comparisons

Manual Configuration

Manually editing the sshd_config file and restarting the SSH service is straightforward but error-prone and inefficient for multiple servers.

Centralized Configuration Tools

Configuration management tools like Puppet or Chef can enforce SSH settings across infrastructure. However, these tools require setup and are more complex than this lightweight script for small-scale deployments.

The script offers a middle ground—simple, targeted, and effective for immediate implementation.

FAQs

  1. What happens if PermitEmptyPasswords is not specified in the configuration file?
    The script appends PermitEmptyPasswords no to the file, explicitly disabling empty password logins.
  2. Can this script break SSH access?
    No, it only modifies a specific directive and reloads/restarts the SSH service without disrupting active sessions.
  3. Is this script compatible with all Linux distributions?
    It is designed for distributions using OpenSSH and supports both systemd and init.d systems.
  4. Do I need to restart the SSH service manually?
    No, the script handles service reloads or restarts as required.

Implications

By enforcing PermitEmptyPasswords no, this script mitigates a critical security risk. Misconfigured SSH settings can expose servers to brute-force attacks and unauthorized access. This script ensures compliance with security best practices, reducing the attack surface and safeguarding sensitive systems.

Recommendations

  • Test Before Deployment: Run the script on a test environment to verify its behavior.
  • Automate Implementation: Use tools like Ansible to deploy this script across multiple servers.
  • Monitor Logs: Check SSH logs to ensure the configuration changes are effective.
  • Document Changes: Maintain records of applied configurations for auditing purposes.

Final Thoughts

Maintaining a secure SSH environment is vital for IT operations. Scripts like this one simplify the process of enforcing critical security measures, ensuring compliance and protecting systems from unauthorized access. For IT professionals managing large infrastructures, leveraging automation tools like NinjaOne enhances operational efficiency, offering centralized management and monitoring solutions tailored to their needs.

Next Steps

Building an efficient and effective IT team requires a centralized solution that acts as your core service deliver tool. NinjaOne enables IT teams to monitor, manage, secure, and support all their devices, wherever they are, without the need for complex on-premises infrastructure.

Learn more about NinjaOne Remote Script Deployment, check out a live tour, or start your free trial of the NinjaOne platform.

Categories:

You might also like

×

See NinjaOne in action!

By submitting this form, I accept NinjaOne's privacy policy.

NinjaOne Terms & Conditions

By clicking the “I Accept” button below, you indicate your acceptance of the following legal terms as well as our Terms of Use:

  • Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms.
  • Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party.
  • Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library belonging to or under the control of any other software provider.
  • Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations.
  • Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks.
  • Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script.
  • EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).