Apache htpasswd secure password change

守給你的承諾、 提交于 2019-12-04 03:31:25

The Apache htpasswd file does not support any shadow functionality. Therefor you have to prevent the users accessing your web server in order to keep them away from the password file. So the only solution is your SSH based approach or any other remote solution. The following description will explain how to write a SSH command script to change the password only if the user knows his old password. The major problem is, that Apache does not provide a command line tool to verify a password in a htpasswd file. But this can be done by hand.

The following description assumes that the web server user is www-data and that the home directory of the user is /var/www.

First you have to create a htpasswd file, that is writable by the web server user:

# ls -la .htpasswd
-rw-r--r-- 1 www-data root 18 10. Mai 16:30 .htpasswd

Then you have to add the keys of all your users to the authorized_keys file of the web server user. You have to prefix each line with the command option.

# cat .ssh/authorized_keys 
command="/var/www/.htpasswd.sh" ssh-rsa AAAA... user@host

Whenever a user connects with his key only the .htpasswd.sh gets executed. The users do not have any shell access to the web server.

This is the script to change the password:

#! /bin/bash

HTPASSWD=/var/www/.htpasswd

die () { echo "$*" >&2 ; exit 1 ; }

read -p 'Enter user name: ' USER
read -s -p 'Old password: ' OLDPW ; echo
read -s -p 'New password: ' NEWPW0 ; echo
read -s -p 'Re-type new password: ' NEWPW1 ; echo

if LINE=$(grep ^"$USER": "$HTPASSWD")
then
    echo "$LINE" | sed 's/.*:\(..\)\(.\+\)/\1 \2/' | { 
        read SALT CRYPT
        if [[ "$SALT$CRYPT" = $(echo "$OLDPW" | mkpasswd -sS "$SALT") ]] ; then
            if [ "$NEWPW0" != "$NEWPW1" ] ; then
                die "Password verification error!"
            fi
            PWS=$(grep -v ^"$USER:" "$HTPASSWD")
            {
                echo "$PWS"
                echo -n "$USER:"
                echo "$NEWPW0" | mkpasswd -s
            } > "$HTPASSWD"
            echo "Updating password for user $USER."
        else
            die "Password verification error!"
        fi
    }
else
    die "Password verification error!"
fi

The tricky part is the password verification. It is done by reading the old salt and encrypting the old password with the old salt. The result is compared with the old encrypted password in the htpasswd file.

Now the user can connect to the web server in order to change the password:

$ ssh www-data@localhost
Enter user name: szi
Old password: 
New password: 
Re-type new password: 
Updating password for user szi.
Connection to localhost closed.

Everybody can change only his own password and nobody has access to the encrypted passwords of the other users. This solution has an additional benefit about using the original htpasswd program in a shell script, because the passwords are never used as a command line argument. This would not be possible with htpasswd, because it can not read the password from stdin like mkpasswd.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!