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.
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
- What happens if PermitEmptyPasswords is not specified in the configuration file?
The script appends PermitEmptyPasswords no to the file, explicitly disabling empty password logins. - Can this script break SSH access?
No, it only modifies a specific directive and reloads/restarts the SSH service without disrupting active sessions. - Is this script compatible with all Linux distributions?
It is designed for distributions using OpenSSH and supports both systemd and init.d systems. - 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.