条件付き入力には pam_exec.so を使用します。

条件付き入力には pam_exec.so を使用します。

RedHat 7.5でPAMシナリオをテストしています。

pamモジュールpam_succeed_if.soは、PAMが提供する必要がある最も基本的なレベルの条件付きテストのように見えますが、私の要件を満たしていません。 user、uid、gid、shell、home、ruser、rhost、tty、および service フィールドに対してのみテストを生成できます。

私の場合は、「rhost」フィールドに基づいてテストしたかったのですが、モジュールをデバッグに入れた後にrhostフィールドが設定されていないことがわかりました。

私の目標はPAMモジュールのみを実行することです。/etc/pam.d/sudoユーザーがコンピュータにローカルにログインした場合。ユーザーがSSH経由でログインしたことを検出できる場合は、このモジュールをスキップしたいと思います。私は実際に効果があると思った3つの異なるアイデアを思い出しましたが、すべて失敗しました。

最終的に失敗したいくつかの解決策を共有しましょう。

条件付き入力には pam_exec.so を使用します。

条件付きでスキップしたい pam モジュールの上部に次の pam エントリを追加したいと思います。

auth    [success=ok default=1]    pam_exec.so /etc/security/deny-ssh-user.sh

/etc/security/deny-ssh-user.shの内容

#!/bin/bash
# Returns 1 if the user is logged in through SSH
# Returns 0 if the user is not logged in through SSH
SSH_SESSION=false
if [ -n "${SSH_CLIENT}" ] || [ -n "${SSH_TTY}" ] || [ -n "${SSH_CONNECTION}" ]; then
    SSH_SESSION=true
else
    case $(ps -o comm= -p $PPID) in
        sshd|*/sshd) SSH_SESSION=true;;
    esac
fi

if "${SSH_SESSION}"; then
    exit 1
else
    exit 0
fi

pam_exec.soのソースコードを調べました。https://github.com/linux-pam/linux-pam/blob/master/modules/pam_exec/pam_exec.c驚くべきことに、スクリプトの終了コードに関係なく、常にPAM_SUCCESSを返します。 pam_execモジュールがPAM_SERVICE_ERR、PAM_SYSTEM_ERR、またはPAM_IGNOREを返すようにするスクリプトを取得できません。

条件付き入力に pam_access.so を使用

今回も条件付きでスキップする pam モジュールの上部に次の pam エントリを追加します。

auth    [success=ok perm_denied=1]    pam_access.so    accessfile=/etc/security/ssh-sudo-access.conf noaudit

/etc/security/ssh-sudo-access.confの内容

+:ALL:localhost 127.0.0.1 
-:ALL:ALL

うわー、本当にきれいですか?ローカルにログインしている場合は成功を返し、他のすべてを拒否します。まあ…いいえ。 pam_access.soモジュールがデバッグに入ると、リモートホストについては知らず、使用中の端末だけがわかることがわかりました。したがって、 pam_access は実際にはリモートホストのアクセスをブロックできません。

PAMモジュールをスキップするためにどのような黒魔術を詠唱する必要があるかを知るために、文字通りソースコードを読むのは面倒な日でした。

ベストアンサー1

これは私に合ったソリューションです。私のもの/etc/pam.d/sudo

#%PAM-1.0
auth            [success=1]     pam_exec.so    /tmp/test-pam
auth            required        pam_deny.so
auth            include         system-auth
account         include         system-auth
session         include         system-auth

そして/tmp/test-pam

#! /bin/bash
/bin/last -i -p now ${PAM_TTY#/dev/} | \
    /bin/awk 'NR==1 { if ($3 != "0.0.0.0") exit 9; exit 0; }'

私は次のような行動をとります。

$ sudo date
[sudo] password for jdoe:
Thu Jun 28 23:51:58 MDT 2018
$ ssh localhost
Last login: Thu Jun 28 23:40:23 2018 from ::1
valli$ sudo date
/tmp/test-pam failed: exit code 9
[sudo] password for jdoe:
sudo: PAM authentication error: System error
valli$

最初の行はデフォルトのpam.d/sudo呼び出しに追加されpam_exec、成功すると次の項目はスキップされます。 2行目は単にアクセスを無条件に拒否します。

/tmp/test-pamマイコールからlast電話TTY pamに関連付けられているIPアドレスを取得します。${PAM_TTY#/dev/}デバイス全体のパスが認識されないため、値の前半から削除されました。このフラグを使用すると、IPアドレスまたはプレースホルダが表示されます(IPアドレスがない場合)。デフォルトでは、チェックするのが難しい情報文字列が表示されます。これが私が代わりに同様のオプションを使用しない理由でもあります。このオプションはチェックしている出力の最初の行だけを見ることができるため、必ずしも必要ではありませんが、現在ログインしているユーザーのみを表示するように制限されています。/dev/last-ilast0.0.0.0lastwhow-p nowawklast

このコマンドは最初の行だけをチェックし、awk3番目のフィールドではない場合は0.0.0.0エラーで終了します。これがの最後のコマンドなので、/tmp/test-pamawkの終了コードがスクリプトの終了コードになります。

あなたが試したテストのどれも私のシステムで動作しませんでしたdeny-ssh-user.sh。これをenv > /tmp/test-pam.logスクリプトの上に置くと、環境が削除され、SSH_FOO変数が設定されていないことがわかります。 $ PPIDは複数のプロセスを指すことがあります。たとえば、実行してperl -e 'system("sudo cat /etc/passwd")'$ PPIDがプロセスを参照している場所を確認しますperl

4.16.11-1-ARCHカーネルであるArch Linux(Arch Linux)があります。しかし、私はそうする必要はないと思います。

おすすめ記事