[Linux]ユーザのアカウント・パスワード管理についてメモ

LDAP のようなディレクトリサービスは一旦忘れて、大昔からあるローカルシステムで閉じたユーザのアカウント・パスワード管理についてメモ。
expire/lock 周りの細かい仕様を知る必要があったので。

検証には CentOS 6 を利用。

アカウント・パスワードは主に以下の2ファイルで管理。

  • /etc/passwd アカウント情報を管理。
  • /etc/shadow アカウントのパスワードを暗号化して管理。

まずはパスワードを設定せずに新規ユーザーを追加

# useradd foo

/etc/passwd を見る

/etc/passwd ファイルにあるアカウント情報を確認
/etc/passwd のパーミッションは -rw-r--r-- なのでだれでも read 可能。

# getent passwd foo ($ grep ^foo /etc/passwd でも OK)
foo:x:504:505::/home/foo:/bin/bash

1行1アカウントで、: 区切りでアカウント情報が並んでいる。

  • 1カラム目がユーザ名。
  • 2カラム目がパスワード。

牧歌的な時代はここに暗号化されたパスワードが記載されていたが、近代ではパスワードは shadow ファイルで管理している。

PASSWD(5)から引用

These days many people run some version of the shadow password suite, where /etc/passwd has an ‘x’ character in the password field, and the encrypted passwords are in /etc/shadow, which is readable by the superuser only.

/etc/shadow を見る

/etc/shadow ファイルにあるパスワード情報を確認
/etc/shadow のパーミッションは ---------- なのでスーパーユーザーだけが read/write 可能。

# getent shadow foo
foo:!!:16195:0:99999:7:::
  • 1カラム目がユーザ名。
  • 2カラム目がパスワード。

RedHat 系ではパスワードが設定されていない場合、パスワード欄が "!!" となる。

パスワードを設定して、変化を確認

# passwd foo
Changing password for user foo.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
# getent shadow foo
foo:$1$Ml1TwfGg$olbOXvZ1fdk9LVmpG.LIe1:16195:0:99999:7:::

2カラム目が $1$Ml1TwfGg$olbOXvZ1fdk9LVmpG.LIe1 となった。
このカラムは $ で区切って情報が入っていて
1つめ : ハッシュ方式。$1 は md5。$2a だと bcrypt, $5 だと SHA-256, $6 だと SHA-512 となる。
2つめ : salt。今回の例では “Ml1TwfGg”
3つめ : CRYPT(3)にsaltとパスワードを入力したハッシュ値。

openssl コマンド経由で実際にハッシュ値を確認してみる

# openssl passwd  --help
Usage: passwd [options] [passwords]
where options are
-crypt             standard Unix password algorithm (default)
-1                 MD5-based password algorithm
-apr1              MD5-based password algorithm, Apache variant
-salt string       use provided salt
-in file           read passwords from file
-stdin             read passwords from stdin
-noverify          never verify when reading password from terminal
-quiet             no warnings
-table             format output as table
-reverse           switch table columns
# openssl passwd -1 -salt 'Ml1TwfGg'
Password:
$1$Ml1TwfGg$olbOXvZ1fdk9LVmpG.LIe1

ということで /etc/shadow と一致している。

アカウントを lock

アカウントを lock すると、パスワード認証が無効化される。
ただし、鍵認証は通る。

ロック前

# passwd -S test
test PS 2014-05-05 0 99999 7 -1 (Password set, MD5 crypt.)
# getent shadow test
test:$1$hZosduXo$vH4KgbuC806dmcvUYbrWc1:16195:0:99999:7:::

アカウントをロック

# usermod --lock test

ロック後

# passwd -S test
test LK 2014-05-05 0 99999 7 -1 (Password locked.)
# getent shadow test
test:!$1$hZosduXo$vH4KgbuC806dmcvUYbrWc1:16195:0:99999:7:::

"passwd -S" の2カラム目が PS(has a passwrd) から LK(cloked)にかわっている。

The status is “PS” if the user has a password, “LK” if the user has an
administrative lock, or “NP” if the user has no password.
http://h50146.www5.hp.com/products/software/oe/tru64unix/manual/v51a_ref/HTML/MAN/MAN1/0275____.HTM

また、 /etc/shadow ファイルの2カラム目が "!" で始まるようになっている。
crypt のハッシュ値に “!” は含まれないのでパスワード認証を無効化している。
$ ssh test@localhost としても、パスワード認証に失敗する。

SHADOW(5) から

If the password field contains some string that is not a valid result of crypt(3), for instance ! or *, the user will not be able to use a unix password to log in (but the user may log in the system by other means).

ロック解除

# usermod --unlock test

アンロック後

# passwd -S test
test PS 2014-05-05 0 99999 7 -1 (Password set, MD5 crypt.)
# getent shadow test
test:$1$hZosduXo$vH4KgbuC806dmcvUYbrWc1:16195:0:99999:7:::

アカウントを expire

アカウントが expire すると、鍵認証もできなくなる。

# usermod  --expiredate 2014-05-01 test
# getent shadow test
test:$1$wUWokF2k$DaUHD/FAR4MA/b28VSAJa/:16195:0:99999:7::16191:
# chage -l test
Last password change                                    : May 05, 2014
Password expires                                        : never
Password inactive                                       : never
Account expires                                         : May 01, 2014
Minimum number of days between password change          : 0
Maximum number of days between password change          : 99999
Number of days of warning before password expires       : 7

実際に ssh してみると

# ssh -i ~/.ssh/id_rsa test@localhost
Your account has expired; please contact your system administrator
Connection closed by ::1

というように鍵認証でも弾かれる。

accout の expire を never に戻す

# usermod -L -e '' test (OR # chage -E -1 test)
# chage -l test
Last password change                                    : May 05, 2014
Password expires                                        : never
Password inactive                                       : never
Account expires                                         : never
Minimum number of days between password change          : 0
Maximum number of days between password change          : 99999
Number of days of warning before password expires       : 7

パスワードを expire させる。

アカウントではなくパスワードを expire させることもできる。
(効果があるかはともかく)運用ポリシーで定期的にパスワードを変更させる場合に利用。

パスワードの最終更新日(-d)が 2014/04/01, 30日でパスワードを切れさせ(-M)、パスワードが切れる7日前から警告メッセージを表示させたい(-W)場合

# chage -d '2014/04/10' -M 30 -W 7 test
# chage -l test
Last password change                                    : Apr 10, 2014
Password expires                                        : May 10, 2014
Password inactive                                       : never
Account expires                                         : never
Minimum number of days between password change          : 0
Maximum number of days between password change          : 30
Number of days of warning before password expires       : 7

ssh でパスワードログインしてみる

# ssh test@localhost
test@localhost's password:
Warning: your password will expire in 5 days
Last login: Mon May  5 08:26:33 2014 from localhost
Welcome to your Vagrant-built virtual machine.
$

ログイン成功後、 “Warning: your password will expire in 5 days” というような警告メッセージが表示される。
有効期限はパスワードに対するものなので、鍵認証の場合はこの影響を受けない。

即座にパスワードを無効化

passwd -e で特定のアカウントのパスワードを即座に無効化できる。

# passwd -e test
Expiring password for user test.
passwd: Success
# chage -l test
Last password change                                    : password must be changed
Password expires                                        : password must be changed
Password inactive                                       : password must be changed
Account expires                                         : never
Minimum number of days between password change          : 0
Maximum number of days between password change          : 30
Number of days of warning before password expires       : 7

パスワード認証でログインすると、パスワードが切れているので再設定するように促される。

# ssh test@localhost
test@localhost's password:
You are required to change your password immediately (root enforced)
Last login: Mon May  5 08:30:57 2014 from localhost
Welcome to your Vagrant-built virtual machine.
WARNING: Your password has expired.
You must change your password now and login again!
Changing password for user test.
Changing password for test.
(current) UNIX password:
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
Connection to localhost closed.

古いパスワードで認証後、パスワードの更新だけが行われ、ログインはしない。

# chage -l test
Last password change                                    : May 05, 2014
Password expires                                        : Jun 04, 2014
Password inactive                                       : never
Account expires                                         : never
Minimum number of days between password change          : 0
Maximum number of days between password change          : 30
Number of days of warning before password expires       : 7

“Password expires” が更新されている。

暗号方式を変える

パスワード暗号化のハッシュ関数は authconfig コマンドで確認できる。

# authconfig --test | grep password
 shadow passwords are enabled
 password hashing algorithm is md5

この出力から /etc/shadow ファイルを利用し、 md5 でハッシュ化していることがわかる。

このハッシュ関数をよりセキュアな sha512 に変更してみる

# authconfig --passalgo=sha512 --update
# authconfig --test | grep password
 shadow passwords are enabled
 password hashing algorithm is sha512

ハッシュ関数が sha512 になったところでパスワード(“asdfqwer1234)を再設定

# passwd  foo
Changing password for user foo.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
# getent shadow foo
foo:$6$.TyxHKUj$d5.JkU6dmR1mhr4Y3iHsuzUVi/c4klAeqQvnxHWOUBAqtpx.Ss9/DsSyzxN2ASZzJ2OsHWL8E9DpLn8fAxI.f.:16195:0:30:7:::

暗号方式が $6 となっているので sha512 とわかる。
また、ハッシュ文字列も md5 に比べてはるかに長い。

Python の標準ライブラリーの crypt からも確認。
crypt 関数のsalt にはハッシュ方式($6$)も含める

# python -c "import crypt;print crypt.crypt('asdfqwer1234', '$6$.TyxHKUj')"
$6$.TyxHKUj$d5.JkU6dmR1mhr4Y3iHsuzUVi/c4klAeqQvnxHWOUBAqtpx.Ss9/DsSyzxN2ASZzJ2OsHWL8E9DpLn8fAxI.f.

ということで /etc/passwd と一致している。

お遊びで、ハッシュを DES にし、shadow ファイルも無効化してみる。

# authconfig --disableshadow --passalgo=descrypt --update

パスワードを “asdfqwer1234” に設定。

# passwd foo
Changing password for user foo.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.

getent/etc/passwd/etc/shadow を確認

# getent passwd foo
foo:/ANI6mKDVNsRg:502:503::/home/foo:/bin/bash
# getent shadow foo
# passwd -S foo
foo PS (Password set, DES crypt.)

shadow ファイルは空なので出力がない。

次に openssl コマンドでハッシュを確認。
crypt 関数の仕様で、DES の場合、2カラム目(“/ANI6mKDVNsRg”)の先頭2文字を salt として使い、crypt に渡すキーはパスワードの先頭8文字を利用する。

# openssl passwd -crypt -salt '/A'
Password:   <- type "asdfqwer"
/ANI6mKDVNsRg

Python の標準ライブラリーの crypt からも確認。

# python -c "import crypt;print crypt.crypt('asdfqwer', '/A')"
/ANI6mKDVNsRg

ということで /etc/passwd と一致している。

References

 

One thought on “[Linux]ユーザのアカウント・パスワード管理についてメモ

  1. /etc/shadow の仕様(生成方法)について知らず、
    Ansible から任意のパスワード・リストを基に
    自動的にユーザ・アカウントを登録する処理を
    作る際に役立ちました。ありがとうございます。

    (公式のガイドにも、やり方は書かれているのですが、
    これは何かという基本的な説明は省かれていたので。)

Leave a comment