よくわからないエンジニア

よく分からないエンジニア(無音鈴鹿)の日々の記録

よくわからないエンジニア

【CentOS】/etc/shadowのハッシュ化パスワードについて

普段、別サーバにユーザーを移動させる時、パスワードは/etc/shadowのハッシュ化された値をコピーして移動させています。
ところが、特定のサーバでログインできないと言われることがたまに発生していました。
原因調査とshadowの挙動に興味を持ったので調べてみることにした。

目次

/etc/shadow

そもそも/etc/shadowはなんだろうかと聞かれれば、
『ユーザーのパスワードがハッシュ化された値が記述されているファイル』とざっくり説明します。
「ハッシュ化ってなんですか?」とか「どんな仕組みなんですか?」と突っ込んで質問されたら、逆ギレします。
人としての信頼を損なわないように、具体的に調べておくことにしました。

そもそもハッシュ化って何さ?

ハッシュ化はデータの置換そのものを目的している為、復号出来ないとの事。えっ、そうなの。。今はじめて知りました。
Linuxのshadowに記載されているパスワードもハッシュ化されているけど、それではどうやって確認しているのだろう。
どうやら、元の単語が何であったかを確認するのではなく、入力された単語から生成されたハッシュ値を比べて確認をしているらしい。

[分かり難い例]
1. ABCDをハッシュ化すると、ハッシュ値XYZDが生成される
ABCD -(ハッシュ化)→XYZD

  1. ハッシュ値を比較し、同じであれば認証。違えば拒否
    CCCC -(ハッシュ化)→RKXS≠XYZD ★拒否
    ABCD -(ハッシュ化)→XYZD=XYZD ☆認証

ざっくり上記のような挙動で確認しているらしい。

一旦確認してみる

user01とuser02をパスワード'password'で作成し、確認してみる。

#useradd test01 &&  passwd test01
#useradd test02 &&  passwd test02
# cat /etc/shadow |grep test0
test01:$6$rXw/Kruy$fknmFoVk3U4fO6j8zk7qVlx0VJHADoC/oGGGQhb77iihwy9FQtB4hbGfLhwmEV/XwZnbT5PZufhXkIF1Oocv0.
test02:$6$fWnK2bkd$z9ybINcoznEpMLrnhRoOWrDxhQebkBQy26KSyPvWHZIA1Yr/6jmH47NT/GJf8wC.1vIlyW.1dKTV6ghFAL1e6/

パスワードは同じはずなのに、ハッシュ値は全然違います。ここで絡んでくるのが、saltという値になります。
test01:$6$rXw/Kruy$
上記の$に囲まれた"rXw/Kruy"がsaltになります。
この値を元のパスワードに付け加えてからハッシュ化している為、ことなる文字列が生成されています。
test02側を見るとsaltは"fWnK2bkd"となり、test01とは異なるsaltが付与されているのが確認出来ます。その為、異なるハッシュ値が生成されています。
実際にどのようにハッシュ化しているのか確認してみます。これらのハッシュ値はcryptを使って生成されています。ワンライナーで書けるので、とりあえずperlを使ってハッシュ値を生成します。

# perl -e 'print crypt("password", "\$6\$rXw/Kruy");'
$6$rXw/Kruy$fknmFoVk3U4fO6j8zk7qVlx0VJHADoC/oGGGQhb77iihwy9FQtB4hbGfLhwmEV/XwZnbT5PZufhXkIF1Oocv0.
# perl -e 'print crypt("password", "\$6\$fWnK2bkd");'
$6$fWnK2bkd$z9ybINcoznEpMLrnhRoOWrDxhQebkBQy26KSyPvWHZIA1Yr/6jmH47NT/GJf8wC.1vIlyW.1dKTV6ghFAL1e6/

saltを指定した場合、shadowに記載されているハッシュ値と同じものが生成されています。

ハッシュ方式

shadowでハッシュ化されていたパスワードにはsaltの前方に"6"という数字が記載されている。
これは使用されているハッシュ方式を表しており、各数字が以下となる。
1→md5
5→sha-256
6→sha-512
自環境の場合、特に意識せずに6が指定されていたのだが、デフォルトでsha-512を使うようになっていた。調べてみると、どうやらpamでデフォルトのハッシュ方式を指定しているようなので変更してみる。

# vim /etc/pam.d/system-auth
#password    sufficient    pam_unix.so sha512 shadow nullok try_first_pass use_authtok
password    sufficient    pam_unix.so md5 shadow nullok try_first_pass use_authtok

sha512をコメントアウトし、md5を指定する。この状態でpasswdを設定する。。

# useradd test03 && passwd test03
# cat /etc/shadow |grep test03
test03:$1$Ff8D3InH$hXEhqMK/MeNYEmDbVcB1z1:17394

指定したとおり、md5のハッシュ方式でハッシュ値が生成されました。

glibcのバージョンによるハッシュ方式の差異

ここで冒頭の、なぜshadowにハッシュ値をコピーしたのにログインできないサーバがあるのか?問題に戻ります。
結論から言えば、glibcのバージョンが古く、sha-512のハッシュ値に対応していないことが原因でした。
先程user03に設定したパスワードはmd5でハッシュ化されたので、該当サーバで確認しても問題ありませんでした。

# perl -e 'print crypt("password", "\$1\$Ff8D3InH");'
$1$Ff8D3InH$hXEhqMK/MeNYEmDbVcB1z1

しかし、sha-512でハッシュ化したものは、該当サーバでハッシュ化するとハッシュ値が正しく変換されません。

# perl -e 'print crypt("password", "\$6\$rXw/Kruy");'
$66to3JK5RgZM

なんでかなぁとcryptのマニュアルを開くと以下記述がありました。

              ID  | Method
              ---------------------------------------------------------
              1   | MD5
              2a  | Blowfish (not in mainline glibc; added in some
                  | Linux distributions)
              5   | SHA-256 (since glibc 2.7)
              6   | SHA-512 (since glibc 2.7)

glibcのバージョンが2.7以前のものはSHAに対応していないようですね。
基本的に新しいサーバから古いサーバにユーザー移行させないと思うので、中々出会わない事象だとは思いますが、頭の片隅に入れといても良いかもしれないですね。

※2017年10月20日追記
デフォルトのハッシュ方式を変更する場合、pam.dを編集するよりも以下のコマンドのほうが良いかも。。

# authconfig --passalgo=md5 --update
# authconfig --test | grep hashing
 password hashing algorithm is md5

再起動しても有効だったので、変更する場合はこちらにしようかな。。しかしauthconfigってコマンド始めてみました。

ほんの少しは理解したような気がしていますが、誤りがありましたらご指摘頂けると嬉しいです。