数回、さまざまなLinuxマシンでユーザーのパスワードを変更しようとしましたが、新しいパスワードが古いパスワードと似ている場合、OSはそれらがあまりにも似ていると不満を言いました。
システムはこれをどのように知っているのでしょうか?パスワードはハッシュとして保存されると思いました。これは、システムが新しいパスワードの類似性を比較できる場合、古いパスワードが実際にプレーンテキストとして保存されることを意味しますか?
数回、さまざまなLinuxマシンでユーザーのパスワードを変更しようとしましたが、新しいパスワードが古いパスワードと似ている場合、OSはそれらがあまりにも似ていると不満を言いました。
システムはこれをどのように知っているのでしょうか?パスワードはハッシュとして保存されると思いました。これは、システムが新しいパスワードの類似性を比較できる場合、古いパスワードが実際にプレーンテキストとして保存されることを意味しますか?
回答:
を使用する場合、古いパスワードと新しいパスワードの両方を提供する必要があるためpasswd
、ドライブ上のどこかに書き込むことなく、メモリ内のプレーンテキストで簡単に比較できます。
実際、パスワードは最終的に保存されるときにハッシュされますが、それが起こるまで、パスワードを入力しているツールはもちろん、他のプログラムがSTDINから読み込んでいる間にキーボードで入力したものにアクセスできるように直接アクセスできます。
これは、ツールのバックグラウンドで使用されるPAMシステムの機能passwd
です。PAMは、最新のLinuxディストリビューションで使用されています。
より具体的にpam_cracklib
は、PAMのモジュールであり、パスワードを非常に脆弱にするいくつかの弱点に基づいてパスワードを拒否できます。
安全ではないと考えられるのは、パスワードが似ているだけではありません。ソースコードは、 パスワードは回文または何編集距離は、二つの単語の間にあるかどうかを確認することができます例えば何の様々な例を、持っています。この考え方は、辞書攻撃に対するパスワードの耐性を高めることです。
参照してくださいmanページを。pam_cracklib
少なくとも私のUbuntuでは、「あまりにも似た」メッセージが出ました when:"...文字の半分以上が異なる文字です..."(詳細は以下を参照)。 @slhckの回答で明確に説明されているように、PAMサポートのおかげです。
:PAMが使用されていない他のプラットフォームについては、「似すぎ」のメッセージが出てくるとき「...複数の文字の半分以上異なるものです....」(詳細は下記を参照してください)
このステートメントを自分でさらに確認するには、ソースコードを確認することができます。方法は次のとおりです。
「passwd」プログラムは、passwdパッケージに含まれています。
verzulli@iMac:~$ which passwd
/usr/bin/passwd
verzulli@iMac:~$ dpkg -S /usr/bin/passwd
passwd: /usr/bin/passwd
オープンソース技術を扱っているため、ソースコードへの無制限のアクセスがあります。取得は次のように簡単です。
verzulli@iMac:/usr/local/src/passwd$ apt-get source passwd
その後、関連するコードの断片を簡単に見つけることができます。
verzulli@iMac:/usr/local/src/passwd$ grep -i -r 'too similar' .
[...]
./shadow-4.1.5.1/NEWS:- new password is not "too similar" if it is long enough
./shadow-4.1.5.1/libmisc/obscure.c: msg = _("too similar");
「obscure.c」を簡単に確認すると、これがわかります(関連するコードのみをカットアンドペーストしています)。
static const char *password_check (
const char *old,
const char *new,
const struct passwd *pwdp)
{
const char *msg = NULL;
char *oldmono, *newmono, *wrapped;
if (strcmp (new, old) == 0) {
return _("no change");
}
[...]
if (palindrome (oldmono, newmono)) {
msg = _("a palindrome");
} else if (strcmp (oldmono, newmono) == 0) {
msg = _("case changes only");
} else if (similar (oldmono, newmono)) {
msg = _("too similar");
} else if (simple (old, new)) {
msg = _("too simple");
} else if (strstr (wrapped, newmono) != NULL) {
msg = _("rotated");
} else {
}
[...]
return msg;
}
したがって、今では、古いものと新しいものの両方のチェックに基づいて、両方が類似しているかどうかに基づいた「類似の」関数があることがわかります。スニペットは次のとおりです。
/*
* more than half of the characters are different ones.
*/
static bool similar (const char *old, const char *new)
{
int i, j;
/*
* XXX - sometimes this fails when changing from a simple password
* to a really long one (MD5). For now, I just return success if
* the new password is long enough. Please feel free to suggest
* something better... --marekm
*/
if (strlen (new) >= 8) {
return false;
}
for (i = j = 0; ('\0' != new[i]) && ('\0' != old[i]); i++) {
if (strchr (new, old[i]) != NULL) {
j++;
}
}
if (i >= j * 2) {
return false;
}
return true;
}
私はCコードをレビューしていません。関数定義の直前のコメントを信頼することに自分自身を制限しました:-)
PAMとNON-PAM対応プラットフォームの違いは、次のような構造の「obscure.c」ファイルで定義されています。
#include <config.h>
#ifndef USE_PAM
[...lots of things, including all the above...]
#else /* !USE_PAM */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !USE_PAM */
passwd
古いパスワードと新しいパスワードの両方を要求するという事実が答えです。この答えの残りは無関係です。
答えはあなたが思っているよりもはるかに簡単です。実際、トリックを説明すると、消えてしまうので、ほとんど魔法の資格があります。
$ passwd
Current Password:
New Password:
Repeat New Password:
Password changed successfully
新しいパスワードが似ていることがわかります...直前に古いパスワードを入力したためです。
他の答えは正しいですが、これが機能するために古いパスワードを提供する必要はないことを言及する価値があります!
実際、提供された新しいパスワードに類似したパスワードの束を生成し、ハッシュし、これらのハッシュのいずれかが古いものと一致するかどうかを確認できます。この場合、新しいパスワードは古いパスワードと同様に判断されます!:)
n
)からの3の組み合わせ、62 * (n!)/(6 * (n - 3)!)
つまり12文字のパスワードに対して13540になります。しかし、誰かが何か違うことを考えると、方程式は役に立たないので、なぜわざわざ?