2011/12/08

/etc/shadowについて勉強してみた

Table of Contents

  1. Linuxでのアカウント情報管理について
  2. /etc/passwdについて
  3. /etc/shadowについて
  4. パスワードのハッシュ化について
    • Shadowの項目について
    • Hash方式について
    • ハッシュ化とは?
    • Saltについて
  5. 参考文献
2012/11/05: 表示が乱れていたので修正した。(今見ると、あんまり見やすくないページだ…)

1 Linuxでのアカウント情報管理について

 Linuxでユーザのアカウント情報を保管しているファイルといえば、
  • /etc/passed
  • /etc/shadow
があります。
以下では、パスワードの情報などは /etc/shadow に保管されている状況で、それぞれどんな情報が格納されているかまとめてみました。
( /etc/passwdにパスワードを保管しないのは、/etc/passwdが他のユーザからRead可能なファイルだからです。 そしてRead権限がないと困ります。/etc/passwdをRead可能にしなければ、たとえば
$ id (他のユーザ)
$ ls -l hoge
などが正しく動作しないことになります。後者についてはuid,gid番号から、ユーザーが誰か判別できないので。。。)

------------------------------------------------------------------------------------------------------------------------------
 以下で、
#から始まるコマンドは管理者権限で実行、
$から始まるコマンドはユーザ権限で実行していることにします。

Ubuntu11.10で実験しています。
 # useradd -c TEST -d /home/test -e 2011/12/10 -f 1 -m -e /bin/bash test  
というコマンドでユーザを追加して、
# passwd test
test
として、パスワードを"test"としていることにします。 オプションの意味については、
$ man useradd
を参照するか、後の記述から推測してください。
 システムユーザ,root,testユーザの例で話を進めます。 実際の値とは一部変更してあることがあります。
-------------------------------------------------------------------------------------------------------------------------------

2 /etc/passwdについて

まずはじめに、/etc/passwdが誰から読めるか確認しておきます。
$ ls -l /etc/passwd
誰からでも読めるようになっていることと思います。
では、実際に/etc/passwdの一部を抜き出してみます。
root:x:0:0:root:/root:/bin/bash
sshd:x:114:65534::/var/run/sshd/usr/sbin/nologin
test:x:1001:1001:TEST:/home/test:/bin/bash
この見方は、次のとおりです。
  • :(コロン)が区切り
  • 各区切られた区間は次の順番で見る。 ログイン名:暗号化パスワード:ユーザID:グループID:コメントorユーザ名:ホームディレクトリ:ログイン時に実行するコマンド 詳しくは、
    $ man 5 passwd
    (man passwdとは内容が違う。man manを読むなどすれば良い。)
よって、/etc/passwdは、以下の通りになっています。

ログイン名パスワードuidgidコメントホームディレクトリログイン時実行するコマンド
root      x0    0        root          /root/bin/bash
sshd      x114   5534
     /var/run/sshd/usr/sbin/nologin
test      x10011001   TEST       /home/test/bin/bash

見て面白そうなところは、
  • 暗号化パスワードがxになっているのは、ディストリビューションによって違うかもしれない。とりあえず、空になっている。
  • rootはuid,gidとも0である。
  • sshdはシステムユーザで、uidが999以下。
  • コメントはあってもなくても良い。
  • ホームディレクトリはログイン時に、どこがカレントディレクトリになるかや、 環境変数$HOMEなどに関係する(詳しくはman usrmodを参照)。
  • 最後のログイン時に実行するコマンドについて、これは$SHELLを定める。 この欄が空の場合、デフォルトでは/bin/shを実行する。
  • /usr/sbin/nologinは実行できるので、試しに実行すると何をするやつかわかる気になる。 (コマンド名通りsshdではログインできない。)
  • ついでに、一度、sshdの/usr/sbin/nologinを削除して空欄にして、sudo su sshdとかしてみると ログインできることがわかる。(試したら戻しておくこと。)

3 /etc/shadowについて

/etc/shadowは誰から読めるのでしょうか。
$ ls -l /etc/shadow
  -rw-r-----で所有者root,所有グループshadowとなっていると思います。 このように、一般ユーザからは読めないことがわかります。
「誰から読めるか」を分けることによって、パスワードを一般のユーザが直接見ることができないようにしています。
shadowの中を見てみましょう。
test:\$6$eIaYHAqm$y/.5CEj/m2RDrubIh...(省略):15316:0:99999:7:1:15318:
のようになっています。先ほどと同様
  • :(コロン)で区切られている
  • 各区切られた区間は以下の順番。($ man 5 shadowの一部改変) 
  ログイン名 : 暗号化パスワード : 1970/1/1から最後にパスワードが変更された日までの日数: 
パスワードが変更できるまでの日数:パスワードを変更しないといけなくなるまでの日数 : 
パスワードが有効な期限の前にユーザが警告を受ける日数 : パスワードが無効になってからアカウントが使えなくなるまでの日数 : 1970/1/1からアカウントが使えなくなるまでの日数 : 予約フィールド
testユーザの例だと、
  • ログイン名: test
  • 暗号化パスワード: $6$eIaYHAqm$y/.5CEj/m2RDrubIh...(省略)
  • 1970/1/1から最後にパスワードが変更された日までの日数: 15316
  • パスワードが変更できるまでの日数: 0
  • パスワードを変更しないといけなくなるまでの日数: 99999
  • パスワードが有効な期限の前にユーザが警告を受ける日数: 7
  • パスワードが無効になってからアカウントが使えなくなるまでの日数: 1
  • 1970/1/1からアカウントが使えなくなるまでの日数: 15318
  • 予約フィールド:
詳しくは、
$ man 5 shadow
を参照して欲しいでし。

ほとんどのフィールドは全く使わないと思うので、必要にならない限り無視してよいと思うけど、 こんなものも設定できる、ということで。

4 パスワードのハッシュ化について

4.1 Shadowの項目について

ここでは、特に上記の暗号化パスワードについて考えていきます。 そもそもパスワードは``test``だったわけで、これが非常に長い文字列になっています。
これは、パスワードをハッシュ(Hash)して格納しているからですが、暗号化パスワードの部分は、 実際には次のように分かれています。

Hash方式Salt$Hash化されたパスワード
  $6$eIaYHAqm$y/.5CEj/m2RDrubIh...(省略)

4.2 Hash方式について

Hash方式として、DES,MD5,SHA256,SHA512などがあります。 (DESは使うべきでないので、ここでは除外します。/etc/Shadowの暗号化パスワードの項が$から始まっていれば良いです。)

Hash方式実際のHash方式
  $1$MD5
  $5$SHA-256
  $6$SHA-512
それぞれについてはここでは詳しく述べません。 linuxjm.sourceforge.jp/html/LDP_man-pages/man3/crypt.3.html
など、他の多くの方が書かれている文献を参考にしてください。 ここでは、現状はSHA512のままで良いのではないか、ということだけ述べておきます。

4.3 ハッシュ化とは?

まず、ハッシュ化とは大雑把に言って

文字列-------------->文字列
   A複雑な変換B
という一連の流れのことと言ってよいと思います。

ユーザがログイン時など認証する際には、

入力 --------------->Hash化
   A' 複雑な変換B'
 を計算して、B'と上記のHash化されたパスワードが一致するかどうかをチェックします。

今パスワードを保管するために、この複雑な変換が持つべき性質として、
  • AからBへの変換の過程にかかる時間はそんなに長くかからない 
           –  認証の度に時間がかかっていると鬱陶しい。
  • Aが違えば、Hash化後のBもほぼ間違いなく違う。 
            – ユーザが意図した入力(Aに対応する内容)を、第3者が変更できない。(Aを変更したらBがほぼ間違いなく変わるから。)
            – 例えば、上記のtestユーザでログインしようとして、パスワードをhogehogeと打って、認証に成功すると困る。
  • BからAを類推しづらい。 
            – これは、かなり類推できるけど膨大な時間がかかる、場合もあります。
            – Hash後の値は常に読まれてしまう可能性があります。 通信路上や、特に/etc/shadowは管理者に読まれます。
            – 元々のAが自分以外にバレると、"その事実に気づいて"(!!)パスワードを変更するくらいしか対策がしづらいです。


  特に2つ目と3つ目は'ほとんど'相反しています。 『A->Bが一意に決まる』ならば、『B->Aを決まる』はずです。(Bになるやつが1つしかないんだから。)
 重要な部分は、『しづらい』とか『ほぼ』とかで、 例えば、『B->A』を求めるのに多くの場合30日かかるなら、パスワードの有効期限を例えば15日などにしておけば、多くの場合大丈夫なのかもしれません。
  (多くの場合、という言葉は非常に悩ましい部分ですが。。。)

4.4 Saltについて

  ところで、上記の表でSaltという部分がありました。 これは一体何をするのでしょうか?これについて、詳しい話は他の場所に譲りますが、 Hash化の際に"複雑な変換"の部分をSaltを使うことで、各パスワードごとに微妙に変えていくわけです。

(簡単な例として、数字に対してHash化は「Saltを掛けてから、各桁を足す」、というものだったとします。 単純にやれば、12->3ですが、Saltが7の場合、12=>12*7=84->12となります。 Saltが11なら、12=>12*11->6となって、Hash化後には違うものになります。)

 これが何故必要か考えてみます。 Hash化の条件として、『B->A』を計算するのが難しい、時間が膨大にかかる、というものがありました。

   しかし、予め『AとBの対応表』を時間をかけて作っておけば、どうでしょうか? Hash化の方式はいくつかありますが、もし、みんなが本当に同じ変換を使ってしまっている場合、 1種類の対応表を作られてしまった瞬間に、Hash化する意味の多くが失われます。

   一方で、Saltを使うことで、そのような対応表をつくる方法がなくなります。 (Saltごとに対応表をつくる必要があり、1つの対応表をつくるために膨大な時間がかかるのです。)

5 参考文献

以下は参考になりそうなサイトです。 自分は特に読んでないので、内容については保証できませんが、このサイトの文章より確からしいと思います。
第1回神泉セキュリティ勉強会資料
linuxjm.sourceforge.jp/html/LDP_man-pages/man3/crypt.3.html

0 件のコメント:

コメントを投稿