Linuxでシステムコールを「監視」する信頼できる方法はありますか?
たとえば、システムコールとシグナルを監視するためのstrace
があります。プロセスがstrace
を回避する方法はありますか?はいの場合、システムコールを監視する(そしてシグナルを受信する)もう1つの信頼できる安全な方法はありますか?プロセスは(適切なLinux実装を前提として)回避できません。
Linuxでは、 監査サブシステム を使用して、システムコールまたはファイルアクセスの選択を確実に監視できます。 auditd
デーモンが実行されていることを確認してから、ログに記録する内容を auditctl
で構成します。ログに記録された各操作は、/var/log/audit/audit.log
に記録されます(一般的な構成)。
auditctl
の使用例 このサイト 、 サーバー障害 、および nix Stack Exchange の簡単な例があります。
strace
またはptrace
を使用する関連プログラムはシステムコールを監視する信頼できる方法ですが、悪意のあるプログラムでそれらを使用することには注意が必要です。頭から離れる方法を言うことはできませんでしたが、監視対象のプログラムが正しいptrace
呼び出しを行って監視を回避できるようにする必要があります。
悪意のあるプログラムが監査されていないプロセスを生成し、ログに記録されないコードを実行する可能性があることに注意してください。たとえば、mmap
を使用して、ファイルの内容がシステムコールの引数として表示されることなくファイルに書き込み、このファイルを実行可能にして、ファイルを実行するプロセスを生成できます。生成されたプロセスは通常、ssh localhost
のようなものでプロセスツリーを壊す可能性があります。特定のユーザーによって実行されたすべてのプロセスを監査する場合(単一のプロセスとその子孫だけではなく)、すべてをログに記録できます。
はいの場合、システムコールを「監視」する(そしておそらくシグナルを受信する)もう1つの信頼できる安全な方法はありますか?そのプロセスは中断できません(適切なLinux実装を想定しています)?
D.W.とは少し異なる方法で繰り返します。すでに述べたように、ptraceはstrace
、gdb
などがプロセスのアクションを監視するために行うシステムコールです。このアプローチには2つの問題があります。
ptrace
を置き換えることは完全に可能であり、別のプロセスまたは他のそのような不正行為の出力を提供します。プロセスは常にデバッガに喜んで提出するように作成されているわけではありません。あなたは このチャレンジセット (win32に焦点を当てた-最初のエントリを見て、難しくするために読み続けてください)をappsec会社(私はそれらとリンクしていません)から読みたいかもしれません。 IsDebuggerPresent()
メカニズムに焦点を当てていますが、同様の ptraceのソリューションが存在します です。これを実際に見て、スカイプがLinuxボックスにインストールされている場合は、デバッグしてみてください。
ここでこれらの手法を繰り返すと、2つの明確な反ptraceメカニズムがあります。
_if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {
printf("being ptraced\n");
exit(1);
}
_
この方法は、プロセスを2回トレースできないという事実に依存しています。自分自身をトレースできない場合は、トレースされています。
_struct timespec spec;
signal(SIGALRM, SIG_IGN);
alarm(1);
spec.tv_sec = 2;
spec.tv_nsec = 0;
if (nanosleep(&spec, NULL) < 0) {
/* EINTR */
printf("being ptraced\n");
exit(1);
}
_
これを説明するには、 nanosleep()
を見て、元の記事を読んでください。簡単に言えば、nanosleep()
は再起動不可能なシステムコールであり、シグナルがプロセスによって処理されると早期に戻ります。この特定のプロセスは、デバッグされていない場合、その特定の信号を処理しないだけなので、起動されません。ただし、ptracedプロセスがそれを処理するため、nanosleep
が早く戻ります。これが発生する別の例は、select()
システムコールです。
最終的には、開始する前にシステムの整合性を確保し、十分なセキュリティ対策と適切に構成されたカーネルを適用することで、1の影響を軽減できます。
2について確実にできることは何ですか?元のバイナリコードを変更しなければ、それほど多くはありません。デバッグのための任意の手法は、どこかで観察可能な不整合や実装の問題を引き起こすためです。
tl; drptrace
は、ターゲットプロセスがデバッガを考慮して書かれていない場合に役立ちます。
Linux監査フレームワークはsyscallモニタリングをサポートしています-あなたが探しているものだと思います。
はい。監視対象のプロセスが悪意のないものである限り、straceはシステムコールとその引数を監視するための適切な方法です。監視されているプロセスが悪意のあるものであり、straceを回避するように記述されている場合、それができると思います。 straceはセキュリティツールとして作成されたのではなく、プロセスがそれを無効にするいくつかの方法を仮定できます。たとえば、Robert Watsonの システムコールラッパーの同時実行の脆弱性の悪用 またはTal Garfinkelの トラップと落とし穴:システムコールの割り込みベースのセキュリティツールの実用的な問題 を参照してください。
悪意のあるコードが心配な場合は、セキュリティのために設計されていないstraceなどのツールではなく、セキュリティのために設計されたサンドボックスを使用することをお勧めします。このようなサンドボックスを構築する一般的なアプローチは、システムコールの割り込みを使用して、監視対象プロセスを含め、そのアクションを監視することです。 1つの移植可能な方法は、ptraceを使用することですが、これはすべてのシステム呼び出しでコンテキスト切り替えを強制するため、重要なパフォーマンスオーバーヘッドを招く可能性があります。 Solarisでは、/ procを使用できます。/procを使用すると、ラッピングに関心のあるシステムコールのサブセットを指定できます。これにより、互換性を犠牲にしてパフォーマンスを向上させることができます。
Plash、Systrace、Subterfugueを見て、これらの種類のメソッドを使用するいくつかの機能するシステムを確認してください。また、さまざまなメカニズム(Linuxでのseccompを含む)を使用するChromeのサンドボックスも見てください。
外部gdbインスタンスを使用してカーネル側のシステムコールを監視することについてはどうでしょうか。
これは、対象のコードを実行するように構成されている仮想マシンをセットアップすることで実行できます。次に、QEMUとKVM(私の知る限り)は、カーネルのgdbデバッグ用のポートを開くように構成する必要があります(以下のガイドを参照してください)。
これがVMが起動している場合、gdbは起動時にカーネルに接続されている可能性があります。
次のステップでは、gdbプロパティとブレークポイントを設定して、対象のコードを新しいプログラムとして設定するすべてのexecve(およびconsorts)で起動します。次に、このブレークポイントに到達するまでgdbを実行します。この時点で、プログラムの実行中に、対象のコードを実行しているプロセスのpidを抽出し、このプロセスの任意のシステムコール(forkおよびexecveを含む)で(カーネルコードで)ヒットするブレークポイントをgdbに設定できます。監視する追加プロセスにつながる可能性がある呼び出し)。
理論的には、これは元に戻すのが難しい優れたソリューションになるはずです。
1つの問題は、ゲストシステムのすべてがひどく遅くなり、大量の不要な呼び出しがbycatchとして発生する可能性があることです(gdbを使用してフィルタリングする必要があります...)。 python)を使用して追加のgdbを拡張し、必要な条件で動作する条件付きブレークポイントを取得する必要がある場合があります(特に自動子プロセス検出の場合)。
Gdbをゲストに接続する方法のガイド: Whamcloud Wiki 、 ReadHat Helpdesk 、 Stackoverflow
(私はこれらのガイドを試しませんでした。数年前にgdbを使用して、学生プロジェクトのカーネルの詳細をデバッグしました。そこで、特定のプロセスのフォーク呼び出しを検出するために、ブレークポイントで単純な条件を使用しました。)
これらに加えて、 カーネルのデバッグ を行う他のいくつかの手法があります。
PS:仮想マシンをエスケープする方法があることに注意してください( 古い例 )。