ハッシュ形式識別の知識マップ(知識グラフ)
この記事は、ログやDBに残るハッシュ文字列の方式を見分ける手順を扱っており、bcryptやArgon2のように先頭に方式名を置くMCFやPHC string format系の保存形式は文字列だけでほぼ特定できる一方、プレーンな16進やBase64だけの文字列は長さと文字種から候補を絞ることしかできないと整理しています。sha256crypt・sha512crypt・md5cryptはいずれもcrypt(3)関数の出力形式でSHA-256・SHA-512・MD5を反復適用しており、openssl passwdで同じsaltを与えて再計算すれば形式を検証できます。また64桁の16進はSHA-256だけでなく複数のアルゴリズムが候補になるため長さだけでの断定は避けるべきであり、NTハッシュはMD5ではなくMD4をもとに計算される点でNTLMとも区別すべきだとしています。候補方式が分かったあとはhashcatのモード番号に翻訳して調査を進めます。
パスワードハッシュ文字列
パスワードを保存する目的で、salt・rounds・メモリコストなどのパラメータをハッシュ値本体と一緒に1つの文字列へ埋め込んで表現する保存形式の総称。
パスワードハッシュ形式
長さだけによる誤判定
文字列の長さだけを根拠にハッシュアルゴリズムを断定してしまう誤りで、同じ出力長を持つ複数の候補アルゴリズムが存在するために生じる。
64 hex = SHA-256の決め打ち
長さだけでの断定
crypt(3)
Unixのパスワードハッシュ関数そのものを指す、Cライブラリの関数名。
crypt関数
crypt(3)関数
MCF(Modular Crypt Format)
先頭に$id$を置いて方式を示す書き方の通称で、単一の仕様書ではなくcrypt(3)系実装が増える中で慣習として固まった書式。
$id$形式
PHC string format
MCFを整理し直し、バージョンやパラメータの書き方まで明文化した仕様。
Password Hashing Competition string format
Argon2
Password Hashing Competitionの優勝アルゴリズムで、Argon2id/Argon2i/Argon2dの3種の変種を持つパスワードハッシュ方式。
bcrypt
Blowfish暗号を基にしたパスワードハッシュアルゴリズムで、$2a$/$2b$/$2y$という接頭辞と2桁のコストパラメータを持つ文字列で表現される。
sha256crypt
crypt(3)系の$5$という接頭辞を持つ、SHA-256を反復適用するUnix系パスワードハッシュ形式。
$5$形式
sha512crypt
crypt(3)系の$6$という接頭辞を持つ、SHA-512を反復適用するUnix系パスワードハッシュ形式。
$6$形式
md5crypt
crypt(3)系の$1$という接頭辞を持つ、MD5を反復適用するUnix系パスワードハッシュ形式。
$1$形式
SHA-256
SHA-2ファミリーのうち256ビット(32バイト)の出力を生成するハッシュアルゴリズムで、NIST FIPS 180-4で規定される。
SHA-256メッセージダイジェスト
SHA-512
SHA-2ファミリーのうち512ビット(64バイト)の出力を生成するハッシュアルゴリズムで、NIST FIPS 180-4で規定される。
SHA-512メッセージダイジェスト
MD5
128ビット(16バイト)のハッシュ値を生成するメッセージダイジェストアルゴリズムで、RFC 1321で規定される。
MD5メッセージダイジェスト
16進表現(hex encoding)
バイト列を0-9a-fの16進文字で表現するエンコーディングで、文字数は元のバイト長の2倍になる。
16進数表現
NTハッシュ
MD4(UNICODE(パスワード))として計算される、パスワードの一方向ハッシュ。NTLM認証の資格情報の出発点で、NTLMv2の応答鍵もここから導出される。
MD4ハッシュ
MD4
128ビットのハッシュ値を生成する、MD5の前身にあたるメッセージダイジェストアルゴリズム。NTハッシュの計算に使われる。
MD4メッセージダイジェスト
NTLM
パスワードの一方向ハッシュを使ったチャレンジ/レスポンス方式の認証プロトコル群(LANMAN・NTLMv1・NTLMv2を含む)。相互認証を持たず、サーバーが本物であると仮定できる環境向けに設計されている。
NTLM認証
openssl passwd
指定したsaltと平文からcrypt系パスワードハッシュ文字列を再計算できるOpenSSLのコマンド。
hashcat
GPUを使ってパスワードハッシュを解析するツールで、対象の方式をモード番号(-m)で指定する。
PBKDF2
HMACを繰り返し適用して共有秘密から鍵を導出するアルゴリズムで、RFC 8018(PKCS #5)で規定される。
Password-Based Key Derivation Function 2
scrypt
メモリを大量に必要とする設計のパスワードハッシュ/鍵導出関数で、RFC 7914で規定される。
LDAPスキームプレフィックス({SHA}等)
{SHA}/{SSHA}/{MD5}/{SMD5}のように、方式名を波括弧で前置してハッシュ値を表現するLDAP/Apache系の表記法。
Base64(RFC 4648)
バイト列を64文字の集合で表現するRFC 4648のエンコーディング方式。
SHA-1
160ビットの出力を生成するハッシュアルゴリズム。
SHA-1メッセージダイジェスト
crypt(3)系実装の出力は、saltやroundsなどのパラメータをMCF系の$id$のようなprefix付き書式に埋め込んで表現する
PHC string formatはMCFの書き方を整理し直し、バージョンとパラメータの記法まで定めた仕様である
Argon2はPHC string formatに従い$argon2id$v=19$m=...のような文字列でパラメータを表現する
bcryptは$2a$/$2b$/$2yという接頭辞でコストパラメータを示す、MCF系の書式を使う
sha256cryptはUnixのcrypt(3)関数が出力する書式の一つとして計算される
sha512cryptはUnixのcrypt(3)関数が出力する書式の一つとして計算される
md5cryptはUnixのcrypt(3)関数が出力する書式の一つとして計算される
sha256cryptはSHA-256を複数ラウンド反復適用してハッシュを計算する
sha512cryptはSHA-512を複数ラウンド反復適用してハッシュを計算する
md5cryptはMD5を複数ラウンド反復適用してハッシュを計算する
16進文字列は文字種と長さしか手がかりがなく、同じ長さの複数アルゴリズムが候補になるため長さだけで断定する誤りを招きやすい
先頭に$id$を置くMCF系の書式は文字列だけで方式を特定できるため、長さだけに頼る誤判定を避けられる
NTハッシュはUTF-16LEでエンコードしたパスワードにMD4を適用して計算される(NTOWFv1(Passwd, User, UserDom) = MD4(UNICODE(Passwd)))
NTLMはNTハッシュを鍵としてチャレンジ/レスポンス認証を行う
sha512crypt形式かどうかは、文字列中のsaltをopenssl passwd -6に渡して再計算し、出力が一致するかで確認できる
sha256crypt形式かどうかは、文字列中のsaltをopenssl passwd -5に渡して再計算し、出力が一致するかで確認できる
md5crypt形式かどうかは、文字列中のsaltをopenssl passwd -1に渡して再計算し、出力が一致するかで確認できる
hashcatではMD5はモード番号0として指定する
hashcatではSHA-256はモード番号1400として指定する
hashcatではsha512cryptはモード番号1800として指定する
hashcatではbcryptはモード番号3200として指定する
hashcatではAD由来のNTハッシュはモード番号1000として指定する
hashcatではDjangoのPBKDF2-HMAC-SHA256形式はモード番号10000として指定する
hashcatではscrypt系の保存形式はモード番号8900として指定する
{SHA}/{SSHA}のような方式では、SHA-1やそのsalt付きdigestをBase64表現で埋め込む({CRYPT}のような素通し方式は対象外)
{SHA}はApache/LDAP系でBase64化したSHA-1 digestを指すことが多い
{SHA}/{SSHA}のような波括弧の方式名プレフィックスも、文字列だけで方式を特定できるため長さだけに頼る誤判定を避けられる