
アカウントに2つのパスワードを割り当てたいです。私が知りたいことは1)これは可能ですか? 2)これはセキュリティにどのような影響を与えますか?
私がこれをしたかったのは、現在いくつかのローカルテストで忙しく、これが特定の状況で役に立つと思ったからです。いくつかの調査の最後に、次のツールが見つかりました。ポリアクリルアミド、インストール/構成のしくみに関する情報を見つけるのが困難です。
私はUbuntu 12.04を実行しています。
答え1
はい、非常にまれですが、確かに可能です。
直接実装しようとするよりも、基本ベースの/etc/password
/etc/shadow
認証方法はこれらの構成を提供しないため、すでにユーザーに対して複数のパスワードをサポートしているバックエンドに認証を委任する方が簡単なアプローチです。
よく知られているのはLDAPuserPassword
複数値を持つ属性RFC4519:
「userPassword」属性に複数の値が必要な例は、ユーザーが自動化システムで生成された毎月異なるパスワードを使用する必要がある環境です。移行期間の最後の日や最初の日など、移行期間中に、2 つの連続した期間に 2 つのパスワードをシステムで有効にする必要がある場合があります。
このRFCにもかかわらず、この設定を実際に適用するには、ほとんどのディレクトリサーバー実装でパスワードポリシー設定を変更する必要があります。
Linux側ではこれを禁止するものはありません(ここではアカウント名が指定され、属性値でtestuser
指定されています)。pass1
pass2
userPassword
$ uname -a
Linux lx-vb 3.8.0-19-generic #29-Ubuntu SMP Wed Apr 17 18:16:28 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
$ grep VERSION /etc/os-release
VERSION="13.04, Raring Ringtail"
$ grep "^passwd" /etc/nsswitch.conf
passwd: files ldap
$ ldapsearch -LLL -h localhost -p 1389 -D "cn=directory manager" -w xxxxxxxx "uid=testuser" userPassword
dn: uid=testuser,ou=People,dc=example,dc=com
userPassword:: e1NTSEF9b2JWYXFDcjhNQmNJVXZXVHMzbE40SFlReStldC9XNFZ0NU4yRmc9PQ==
userPassword:: e1NTSEF9eDlnRGZ5b0NhKzNROTIzOTFha1NiR2VTMFJabjNKSWYyNkN3cUE9PQ==
$ grep testuser /etc/passwd
$ getent passwd testuser
testuser:*:12345:12345:ldap test user:/home/testuser:/bin/sh
$ sshpass -p pass1 ssh testuser@localhost id
uid=12345(testuser) gid=12345 groups=12345
$ sshpass -p pass2 ssh testuser@localhost id
uid=12345(testuser) gid=12345 groups=12345
$ sshpass -p pass3 ssh testuser@localhost id
Permission denied, please try again.
これらの構成のいくつかの技術とセキュリティ関連の影響は次のとおりです。
- ユーザーアカウントは明らかに脆弱ですが、ここで本当に重要なのは、パスワードの数ではなくパスワードの品質と保護です。
- ほとんどのユーティリティは、ユーザーが1つのパスワードしか持っていないと仮定するため、ユーザーはパスワードの1つを個別に更新することはできません。パスワードの変更により、ユーザーがパスワード属性を持つことがあります。
- 複数の人が自分のパスワードを使用して同じアカウントを共有できるようにすることを目的としている場合は、使用されたパスワードに基づいて実際にログインしている人を識別するメカニズムはありません。
答え2
私はファイルにユーザー用の2つのエントリを作成しようとしましたが、/etc/shadow
成功しませんでした。最初の項目は使用されたパスワード項目です。
はい
テストユーザーを作成しました。
$ useradd -d /home/newuser newuser
パスワードを「super123」に設定します。
$ passwd newuser
/etc/shadow
ファイルを手動で編集して2番目のエントリを作成します。
newuser:$6$....password #1...:15963:0:99999:7:::
newuser:$6$....password #2...:15963:0:99999:7:::
次に、2つのパスワードを使用してアカウントにログインします。
su - newuser
最初の項目/etc/shadow
はgetが使用するもので、2番目の位置の項目は次のように反転しても機能しません。
newuser:$6$....password #2...:15963:0:99999:7:::
newuser:$6$....password #1...:15963:0:99999:7:::
これにより、2番目のパスワードは有効ですが、1番目のパスワードは無効です。
sudoを使う
この方法は私が使用する完全なハッキングでありsudo
、sudo
これが存在する理由の一部です。
このエントリをsudoersファイル(/etc/sudoers
)に追加すると、ユーザーjoeは次のことを行うことができます。
joe ALL=(yourusername) ALL
答え3
これを行うことができればしないでください。
PAM構成は幾分複雑であり、認証メカニズムについて当然の事実がある。正しい構成セットは有限で安全でない構成セットは無限です。これは、自分が何をしているのかを正確に知らずに状況を変えようとすると、物事を台無しにすることをほぼ確実にします。
セキュリティと「特定の状況での利便性」のいずれかを選択する必要がある場合は、前者を選択してください。
答え4
1つのアカウントに複数の異なる(ハードコードされた)パスワードを許可する小さなPAMモジュールを作成できます。
以下は、そのようなモジュールのサンプルソースコードです。
// Compile with:
// gcc -fPIC -shared -o pam_multipass.so pam_multipass.c -lpam -lssl -lcrypto
// Install into /lib/security/ (or other location, depending on your distribution):
// sudo install --mode=0755 --owner=root --group=root pam_multipass.so /lib/security/pam_multipass.so
#define _GNU_SOURCE
#include <stdio.h>
#include <security/pam_modules.h>
#include <security/pam_ext.h>
#include <string.h>
#include <openssl/sha.h>
#define USERNAME "username"
#define PASSWORD_HASH_1 "xxxxxxxx"
#define PASSWORD_HASH_2 "xxxxxxxx"
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) {
const char *username;
char *password;
unsigned char result[SHA256_DIGEST_LENGTH];
char hexstring[65];
// Get the username
pam_get_user(pamh, &username, NULL);
if (strcmp(username, USERNAME) != 0) {
return PAM_IGNORE; // Not the user we're interested in
}
// Prompt for password
if (pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &password, "%s", "Password: ") != PAM_SUCCESS) {
fprintf(stderr, "pam_multipass pam_prompt failed\n");
return PAM_IGNORE;
}
if (pam_set_item(pamh, PAM_AUTHTOK, password) != PAM_SUCCESS) {
fprintf(stderr, "pam_multipass failed to set PAM_AUTHTOK\n");
}
SHA256((unsigned char *) password, strlen(password), result);
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
sprintf(hexstring + (i * 2), "%02x", result[i]);
}
// Compare with expected hash
if (
strcmp(hexstring, PASSWORD_HASH_1) == 0
|| strcmp(hexstring, PASSWORD_HASH_2) == 0
) {
return PAM_SUCCESS;
} else {
return PAM_IGNORE; // Allow other modules to authenticate
}
}
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) { return PAM_IGNORE; }
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) { return PAM_IGNORE; }
PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { return PAM_IGNORE; }
PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { return PAM_IGNORE; }
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) { return PAM_IGNORE; }
PAM構成にモジュールを追加する必要がありますが、これは難しい場合があります。私はArch Linuxディストリビューションを例に挙げ、必要に応じて他のディストリビューションに適用します。
# in /etc/pam.d/system-auth
auth required pam_faillock.so preauth
auth [success=3 default=ignore] pam_multipass.so # <--- our module
auth [success=2 default=ignore] pam_unix.so try_first_pass nullok
-auth [success=1 default=ignore] pam_systemd_home.so
auth [default=die] pam_faillock.so authfail
auth optional pam_permit.so
auth required pam_env.so
auth required pam_faillock.so authsucc
しかしとにかく慎重に注意してください。実行しているすべての作業を完全に理解していない場合は、このようなことをしないでください(success=3
PAM構成になぜディレクティブがあるのですか?)。