Chillbox  /  Security checks  /  Password logins

You set PasswordAuthentication no. Your server disagrees.

You edited /etc/ssh/sshd_config, restarted the daemon, and the login prompt still asks for a password. Nothing is broken. The line you edited was never the one in effect.

This is the most common wrong answer in SSH hardening, and it is wrong in a direction that matters: you believe the door is shut while bots are still knocking on it.

Get Chillbox · free to tryFree to download. 7 days to try it, then $7.99 once. No subscription, no account, no cloud.
Chillbox showing a security finding about SSH password logins on a monitored server
Chillbox reads what the daemon reports, not what the file says. If it cannot read either, it says so instead of passing you.
The measurement

On a stock Debian, that line is a comment

Install Debian, open /etc/ssh/sshd_config, and search for the directive. It is there, around line 57, and it is commented out:

#PasswordAuthentication yes

People read that as off by default. It is the opposite. A commented line is a line that does not exist, and OpenSSH's compiled-in default for PasswordAuthentication is yes. The comment is documentation of the default, not a setting.

So a fresh server accepts password logins, and the file it ships with says nothing about it either way.

Why uncommenting it does not always help

The Include is on line 12, and first value wins

Debian and Ubuntu put this near the top of the file:

12  Include /etc/ssh/sshd_config.d/*.conf
..
57  PasswordAuthentication no   # the line you just edited

The manual page is explicit about the rule: for each keyword, the first obtained value is used. Not the last. Not the most specific. The first one the daemon reads.

Line 12 is read before line 57. So anything inside /etc/ssh/sshd_config.d/ wins, and your edit on line 57 is dead text. If a cloud image, a provisioning tool or a package dropped a file in there saying PasswordAuthentication yes, that is the value in effect, and it will keep being the value in effect every time you edit the main file and restart.

Look in the directory before you touch anything else:

$ ls /etc/ssh/sshd_config.d/
50-cloud-init.conf
The other way it hides

Everything after Match is conditional

A Match block ends the global section. Every directive below it applies only when the condition holds, so a PasswordAuthentication no written under Match User deploy is not a server-wide setting, however much it looks like one in the middle of the file.

This is why reading the config with your eyes is not a check. You are not simulating an ordering rule, an include and a set of conditionals in your head correctly at 1am, and neither is a grep.

The answer

One command, and it is not grep

sshd -T makes the daemon print its effective configuration: includes resolved, defaults filled in, global section only. It is the same thing sshd will use on the next login.

Run this
sudo sshd -T | grep -iE '^(passwordauthentication|permitrootlogin) '

Needs root, because sshd refuses to dump a config it cannot fully read. Anything else — grepping the file, trusting the comment, trusting your memory of the edit — answers a different question than the one you asked.

If it prints passwordauthentication yes, find the file that is winning, fix it there, and check again. The check after the fix is the part people skip, and it is the only part that proves anything.

$ sudo sshd -T | grep -i passwordauth
passwordauthentication yes

# find who is setting it
$ grep -ri passwordauth /etc/ssh/sshd_config.d/
/etc/ssh/sshd_config.d/50-cloud-init.conf:PasswordAuthentication yes

# fix it where it is actually set, then re-check
$ sudo systemctl restart ssh
$ sudo sshd -T | grep -i passwordauth
passwordauthentication no
Why we wrote this

Chillbox got this wrong once, out loud

An earlier version of the app checked this with a grep of sshd_config. On a stock Debian the grep found nothing, and the app reported that as nothing to report. It showed a clean Security tile on a server that accepted password logins for root.

That is the failure this whole app is built against: not missing a problem, but printing a pass nobody measured. The check now runs sshd -T, falls back to reading the file and its drop-ins in the daemon's own order, and when it can read neither it says not evaluated and leaves the score alone. A check that could not run is never a check that passed.

What it reads
sshd -T first, the files and their drop-ins second
If it cannot read either
Says not evaluated. Never a pass
Needs
An SSH login. No agent, nothing installed on the server
Costs
Free to try, then $7.99 once

Check it on every server you own, from your phone

Add a server with the SSH login you already use. Chillbox reports what it found, and what it could not.

Get Chillbox · free to tryFree to download. 7 days to try it, then $7.99 once. No subscription, no account, no cloud.

Every security check Chillbox runs →