こんにちは。CTOの馬場です。

Serverspec使ってますか? ハートビーツでは使っています。

サーバ構築後などに弊社標準のスケルトンをもとにテストを作成・実行しています。

最近「弱いパスワードを利用しているユーザがいないかチェックしたい」という要望があったため、 実現するために ServerspecWeakPassword を書いて公開したので紹介します。 自分のメイン言語はPythonとGoですが、ServerspecはRubyなので素直にRubyで書きました。

ServerspecWeakPassword

Utility to check specified user's password is so weak. - github.com/heartbeatsjp/serverspecweakpassword

パスワードが以下の条件に合致しているかを確認し、 合致している場合はテストがfailします。

  • (自分を含む)サーバ内のユーザと同じパスワード
  • List of the most common passwords にリストアップされているパスワード
  • 上記を2回繰り返し or 上記の逆順 or 上記+上記の逆順

使う時は Gemfile に以下のように書いて bundle install でインストールします。

gem 'serverspec_weak_password', git: 'https://github.com/heartbeatsjp/serverspec_weak_password.git'

root ユーザのパスワードをチェックするテストコードは以下のように書きます。

require 'serverspec_weak_password'
describe 'root password is not weak' do
  shadow = ServerspecWeakPassword::ServerspecWeakPassword.get_shadow('root')
  next if shadow.nil?

  it { expect(shadow[:hash]).not_to eq('') }
  next if shadow[:hash] == ''

  ServerspecWeakPassword::ServerspecWeakPassword.get_weak_hashes(shadow[:hash_type], shadow[:salt]).each do |hash|
    it { expect(shadow[:hash]).not_to eq(hash) }
  end
end

実行するとこんな感じでテストがfailします。 (これはVagrant上のCentOS6で試しました)

Run options: include {:locations=>{"./spec/default_spec.rb"=>[193]}}

root password is not weak
  should not eq ""
  (snip)
  should not eq "D9EWLguLP2bTgGL8GllQCA2KRsTWQyPYqcuKOwGfszfVtAOGaAIzFR4AfmPvsNy6ngrrEUdPTv7RiXbE4hqkp." (FAILED - 1)
  (snip)

Failures:

  1) root password is not weak should not eq "D9EWLguLP2bTgGL8GllQCA2KRsTWQyPYqcuKOwGfszfVtAOGaAIzFR4AfmPvsNy6ngrrEUdPTv7RiXbE4hqkp."
     On host `centos6'
     Failure/Error: it { expect(shadow[:hash]).not_to eq(hash) }

       expected: value != "D9EWLguLP2bTgGL8GllQCA2KRsTWQyPYqcuKOwGfszfVtAOGaAIzFR4AfmPvsNy6ngrrEUdPTv7RiXbE4hqkp."
            got: "D9EWLguLP2bTgGL8GllQCA2KRsTWQyPYqcuKOwGfszfVtAOGaAIzFR4AfmPvsNy6ngrrEUdPTv7RiXbE4hqkp."

       (compared using ==)

     # ./spec/default_spec.rb:201:in `block (3 levels) in '

Finished in 0.05951 seconds (files took 3.82 seconds to load)
329 examples, 1 failure

Failed examples:

rspec './spec/default_spec.rb[17:4]' # root password is not weak should not eq "D9EWLguLP2bTgGL8GllQCA2KRsTWQyPYqcuKOwGfszfVtAOGaAIzFR4AfmPvsNy6ngrrEUdPTv7RiXbE4hqkp."

パスワード検証の仕組み

/etc/shadow を見てhash化の方式とsaltを確認し、 hashを計算してみて比較できるようにしています。 力技です。

細かい仕組みは man 5 shadowman crypt に書いてあります。

  1. /etc/shadow からユーザ名一覧、対象ユーザの encrypted password を取得
  2. encrypted password のフォーマット $id$salt$encrypted に従い idsaltencrypted を取得
  3. id から方式を確定し、 salt と比較対象パスワードから生成したものを encrypted と比較

どうぞご活用ください。

株式会社ハートビーツのインフラエンジニアから、ちょっとした情報をお届けします。