- check unix username and password in a shellscript
- 4 Answers 4
- How to check the password entered is a valid password for this user?
- 5 Answers 5
- Security Notes
- It might not be the right approach.
- It has not been audited.
- Another user who's "watching" may be able to discover the user's salt.
- Be careful how you call this script.
- Other Notes
- It supports reading hashes from the shadow database only.
- Keep IFS in mind when modifying this script.
- check password linux user
check unix username and password in a shellscript
I want to check in a shell script if a local unix-user’s passed username and password are correct. What is the easiest way to do this? Only thing that I found while googling was using ‘expect’ and ‘su’ and then checking somehow if the ‘su’ was successful or not.
4 Answers 4
the username and passwords are written in the /etc/shadow file. just get the user and the password hash from there ( sed would help), hash your own password and check.
use mkpasswd to generate the hash. you hve to look which salt your version is using. the newest shadow is using sha-512 so :
mkpasswd -m sha-512 password salt
manpages can help you there a lot.
Easier would be to use php and the pam-aut module. there you can check vie php on group access pwd user.
more details about the implementation of this approach: ubuntuforums.org/archive/index.php/t-1232715.html
oh ok, nice. I spend 6 hours figuring this approach out by myself a few month ago. this site would have helped a lot. but i needed this for web authentification, so i finally used the auth-pam module of php
nowhere. it was how I finally solved an similar problem. cluelessCoder has never said what he wants to do. it you want an simple shell solution you have to prse the shadow file. for web authentification this module is easy. Well you can also create a php file and coll this one from batch and parse the output (a bit overkill but easy to accomplish too. you only need to have a php server running on the local machine). Just several ways to accomplish a goal.
Ok, now this is the script that I used to solve my problem. I first tried to write a small c-programm as susgested by Aaron Digulla, but that proved much too difficult.
Perhaps this Script is useful to someone else.
#!/bin/bash # # login.sh $USERNAME $PASSWORD #this script doesn't work if it is run as root, since then we don't have to specify a pw for 'su' if [ $(id -u) -eq 0 ]; then echo "This script can't be run as root." 1>&2 exit 1 fi if [ ! $# -eq 2 ]; then echo "Wrong Number of Arguments (expected 2, got $#)" 1>&2 exit 1 fi USERNAME=$1 PASSWORD=$2 # Setting the language to English for the expected "Password:" string, see http://askubuntu.com/a/264709/18014 export LC_ALL=C #since we use expect inside a bash-script, we have to escape tcl-$. expect < exit [lindex \$wait_result 3] >else < exit 1 >EOF
How to check the password entered is a valid password for this user?
The scenario: In a bash script, I have to check if a password given by a user is a valid user password. I.e suppose I have a user A with password PA.. In the script I asked user A to enter his password, So how to check if the string entered is really his password.
@A.B. I know it will be a security hole but here you already know the user name also. In other words its just a test if the password is for this user..
5 Answers 5
Since you want to do this in a shell script, a couple of contributions in How to check password with Linux? (on Unix.SE, suggested by A.B.) are especially relevant:
- rozcietrzewiacz’s answer on generating a password hash that matches an entry in /etc/shadow gives part of the solution.
- Daniel Alder’s comment explains the different syntax of the mkpasswd command present in Debian (and Ubuntu).
To manually check if a string is really some user’s password, you must hash it with the same hash algorithm as in the user’s shadow entry, with the same salt as in the user’s shadow entry. Then it can be compared with the password hash stored there.
I’ve written a complete, working script demonstrating how to do this.
- If you name it chkpass , you can run chkpass user and it will read a line from standard input and check if it’s user ‘s password.
- Install the whois package to obtain the mkpasswd utility on which this script depends.
- This script must be run as root to succeed.
- Before using this script or any part of it to do real work, please see Security Notes below.
#!/usr/bin/env bash xcorrect=0 xwrong=1 enouser=2 enodata=3 esyntax=4 ehash=5 IFS=$ die() < printf '%s: %s\n' "$0" "$2" >&2 exit $1 > report() < if (($1 == xcorrect)) then echo 'Correct password.' else echo 'Wrong password.' fi exit $1 >(($# == 1)) || die $esyntax "Usage: $(basename "$0") " case "$(getent passwd "$1" | awk -F: '')" in x) ;; '') die $enouser "error: user '$1' not found";; *) die $enodata "error: $1's password appears unshadowed!";; esac if [ -t 0 ]; then IFS= read -rsp "[$(basename "$0")] password for $1: " pass printf '\n' else IFS= read -r pass fi set -f; ent=($(getent shadow "$1" | awk -F: '')); set +f case "$" in 1) hashtype=md5;; 5) hashtype=sha-256;; 6) hashtype=sha-512;; '') case "$" in \*|!) report $xwrong;; '') die $enodata "error: no shadow entry (are you root?)";; *) die $enodata 'error: failure parsing shadow entry';; esac;; *) die $ehash "error: password hash type is unsupported";; esac if [[ "$" = "$(mkpasswd -sm $hashtype -S "$" <<<"$pass")" ]] then report $xcorrect else report $xwrong fi
Security Notes
It might not be the right approach.
Whether or not an approach like this should be considered secure and otherwise appropriate depends on details about your use case that you haven't provided (as of this writing).
It has not been audited.
Although I've tried to exercise care while writing this script, it has not been properly audited for security vulnerabilities. It is intended as a demonstration, and would be "alpha" software if released as part of a project. Furthermore.
Another user who's "watching" may be able to discover the user's salt.
Due to limitations in how mkpasswd accepts salt data, this script contains a known security flaw, which you may or may not consider acceptable depending on use case. By default, users on Ubuntu and most other GNU/Linux systems can view information about processes run by other users (including root), including their command-line arguments. Neither the user's input nor the stored password hash is passed as a command-line argument to any external utility. But the salt, extracted from the shadow database, is given as a command-line argument to mkpasswd , since this is the only way that utility accepts a salt as input.
- another user on the system, or
- anyone who has the ability to make any user account (e.g., www-data ) run their code, or
- anyone who otherwise can view information about running processes (including by manually inspecting entries in /proc )
is able to check the command-line arguments to mkpasswd as it is run by this script, then they can obtain a copy of the the user's salt from the shadow database. They might have to be able to guess when that command is run, but that is sometimes achievable.
An attacker with your salt is not as bad as an attacker with your salt and hash, but it's not ideal. The salt doesn't provide enough information for someone to discover your password. But it does allow someone to generate rainbow tables or pre-computed dictionary hashes specific to that user on that system. This is initially worthless, but if your security is compromised at a later date and the full hash is obtained, it could then be cracked more quickly to obtain the user's password before they get a chance to change it.
Thus this security flaw is an exacerbating factor in a more complex attack scenario rather than a fully exploitable vulnerability. And you might consider the above situation far-fetched. But I am reluctant to recommend any method for general, real-world use that leaks any non-public data from /etc/shadow to a non-root user.
You can avoid this problem completely by:
- writing part of your script in Perl or some other language that lets you call C functions, as shown in Gilles's answer to the related Unix.SE question, or
- writing your whole script/program in such a language, rather than using bash. (Based on the way you've tagged the question, it appears you prefer to use bash.)
Be careful how you call this script.
If you allow an untrusted user to run this script as root or to run any process as root that calls this script, be careful. By changing the environment, they can make this script--or any script that runs as root--do anything. Unless you can prevent this from occurring, you must not allow users elevated privileges for running shell scripts.
See 10.4. Shell Scripting Languages (sh and csh Derivatives) in David A. Wheeler's Secure Programming for Linux and Unix HOWTO for more information on this. While his presentation focuses on setuid scripts, other mechanisms can fall prey to some of the same problems if they don't correctly sanitize the environment.
Other Notes
It supports reading hashes from the shadow database only.
Passwords must be shadowed for this script to work (i.e., their hashes should be in a separate /etc/shadow file that only root can read, not in /etc/passwd ).
This should always be the case in Ubuntu. In any case, if needed the script can be trivially extended to read password hashes from passwd as well as shadow .
Keep IFS in mind when modifying this script.
I set IFS=$ at the beginning, since the three data in the hash field of a shadow entry are separated by $ .
- They also have a leading $ , which is why the hash type and salt are "$" and "$" rather than "$" and "$" , respectively.
The only places in this script where $IFS determines how the shell splits or combines words are
- when these data are split into an array, by initializing it from the unquoted $( ) command substitution in:
set -f; ent=($(getent shadow "$1" | awk -F: '')); set +f
if [[ "$" = "$(mkpasswd -sm $hashtype -S "$" <<<"$pass")" ]]
If you modify the script and have it perform word splitting (or word joining) in other situations, you'll need to set IFS to different values for different commands or different parts of the script.
If you don't keep this in mind and assume $IFS is set to the usual whitespace ( $' \t\n' ), you could end up making your script behave in some pretty weird-seeming ways.
check password linux user
I am on debian 9. I have a problem to check the password of a linux user in my scripts. I realized that the different linux tools for creating and modifying a user password gave results of different pattern in /etc/shadow To create a user
pwLinux="abcdef1234" userLinux="toto02" pwCrypt=$(perl -e 'print crypt($ARGV[0], "zzz")' $pwLinux) useradd -m -G adm,dip,plugdev,www-data,sudo -p $pwCrypt $userLinux
toto02:zzDxrNjXuUs3U:17469:0:99999:7.
USERNAME="toto02" PASSWD="abcdef1234" ORIGPASS=`grep -w "$USERNAME" /etc/shadow | cut -d: -f2` ORIGPASS=`echo $ORIGPASS | cut -d"$" -f2` GENPASS=$(perl -e 'print crypt($ARGV[0], "zzz")' $PASSWD) if [ "$GENPASS" == "$ORIGPASS" ]; then echo "Valid Password" exit 0 else echo "Invalid Password" exit 1 fi
# username "toto02", newPwd "aabbcc" echo "$:$" | chpasswd
toto02:$6$rLklwx9K$Brv4lvNjR.S7f8i.Lmt8.iv8pgcbKhwDgINzhT1XwCBbD7XkB98lCtwUK3/4hdylkganoLuh/eIc38PtMArgZ/:17469:0:99999:7.
If i want to check this password i must use a different script.
First problem how to have the same pattern of password in both cases? i use:
#!/bin/bash USERNAME="toto02" PASSWD="aabbcc" ORIGPASS=`grep -w "$USERNAME" /etc/shadow | cut -d: -f2` export ALGO=`echo $ORIGPASS | cut -d"$" -f2` export SALT=`echo $ORIGPASS | cut -d"$" -f3` echo "algo: -$ALGO-" echo "salt: -$SALT-" echo "pwd entré: -$PASSWD-" echo "shadow: -$ORIGPASS-" GENPASS="$(perl -e 'print crypt("$ENV","\$$ENV\$$ENV\$")')" echo "pwd généré: -$GENPASS-" if [ "$GENPASS" == "$ORIGPASS" ]; then echo "Valid Password" exit 0 else echo "Invalid Password" exit 1 fi
algo: -6- salt: -rLklwx9K- pwd entré: -aabbcc- shadow: -$6$rLklwx9K$Brv4lvNjR.S7f8i.Lmt8.iv8pgcbKhwDgINzhT1XwCBbD7XkB98lCtwUK3/4hdylkganoLuh/eIc38PtMArgZ/- pwd généré: -$6$rLklwx9K$AIX1bUMAK9bwdd2g3ST5VtXTvHlHXHxnh4Xj.fLdxjaEkAAvHeeN5islid0wtmZN5u1zWQBup./IP8IH9i6W7/- Invalid Password