web-dev-qa-db-ja.com

Windowsが親以外のプロセスにプロセスのメモリの読み取り/書き込みを許可するのはなぜですか?

私は最近、Windowsでは、プロセスが同じユーザーで実行されている限り、プロセスが別のプロセスのメモリを変更することを許可されていることを学びました。次のコードをさまざまなPIDで実行してみました。

#include <iostream>
#include <processthreadsapi.h>
#include <errhandlingapi.h>

int main()
{
    HANDLE handle = OpenProcess(PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION, FALSE, 1232);

    if (handle == NULL)
        std::cout << "DENIED " << GetLastError() << "\n";
    else
        std::cout << "ALLOWED\n";

    return 0;
}

ほとんどの場合、自分のユーザーとして実行されているプロセスへのアクセスが許可されていることに気付きました。システムまたは管理者として実行されているプロセスは、アクセスを拒否されました。

対照的に、Linuxでは、メモリからの読み取りとメモリへの書き込みのために、一般にptraceを使用して別のプロセスにアタッチする必要があることがわかりました。ただし、デフォルトでは、親だけが子プロセスにアタッチできます。

Windowsが、別のプロセスを生成したプロセスのみがそのメモリにアクセスできるという同様の制約を強制しない理由はありますか?

2
Samik

Windows(さらに言えばLinux)のセキュリティモデルでは、一般に、ユーザー(「ログインアカウント」の意味で)が行うことはすべて同じ信頼レベルで行われるとされています。つまり、同じセキュリティトークンで実行されている2つのプロセスは、まったく同じ量だけ信頼されます。 1つのプロセスが独自のメモリにアクセスできる場合(もちろん可能です)、他のプロセスにもアクセスできます。

攻撃者がアカウントで任意のコードを実行した場合、それはすでにゲームオーバーです。現在のプロセスのメモリへのアクセスを許可しなくても、デバッガーの下でプロセス自体を起動し、ユーザーが書き込み可能な場所(ログイン/シェルリソーススクリプトなど)に保存されたスクリプト/ライブラリ/実行可能ファイルを上書きし、読み取りまたは書き込みを行うことができます。プログラムがアクセスするように実行されているすべてのデータなど。つまり、ユーザーのプロセス間にセキュリティ境界を作成することにはほとんど価値がありません。

次に、そうしないことの利点を検討します。実行中のプロセスをデバッグするためにadmin/rootである必要はありません。これは、再作成が困難な奇妙な状態である可能性があります。ユーザーが書き込みできない場所にインストールされたプログラムの機能を変更または拡張するツールを作成できます(これは、たとえばゲームの改造で頻繁に使用されます)。基本的に、ユーザー(ユーザー)は、セッションで実行されているソフトウェアをより詳細に制御でき、昇格された特権を必要とせずにそれを実行できます。唯一のコストは、攻撃者があなたを傷つける可能性があるため、攻撃者がコードを実行するいくつかの新しい方法があり、その時点で、彼らはこれ以上実際に必要としないことです。

WindowsのプロセスオブジェクトにはACLがあります。ACLを使用して、他のユーザーにプロセスのメモリへのアクセスを許可したり、特定のアクセス(プロセスが終了したことを通知する機能など)を他のアクセス権(アクセス権など)なしで許可したりできます。メモリに書き込みます)。自分のユーザーからのプロセスへのアクセスを制限することもできます-自分が所有するファイルへのアクセスを制限するのと同じように-オブジェクトの所有者はACLを上書きできるため、その制限を上書きするだけで別のプロセスも実行できます(繰り返しますが、自分が所有するファイルを「読み取り専用」とマークするのと同じです)。


一般に、起動したプロセスを他のプロセスが改ざんできないようにしたい場合は、別のユーザーとして起動する必要があります。これを行うには、CreateProcessWithLogonやWindowsサービスの作成など、いくつかの方法があります。 Win32 APIは、ファイルに「setuid」ビットに相当するものを提供していませんが、特権サービスアカウントはその動作をエミュレートできます。アプリが実行できることを制限したい場合は、CreateRestrictedTokenを使用して独自のセキュリティトークンの低特権バージョンを簡単に作成し、それを使用してサンドボックスプロセスを作成できます(これのオープンソースの例はChromeサンドボックス)。

2
CBHacking

従来、Linuxでは独自のプロセスのメモリを読み取ることも可能でした。

他のプロセスをアタッチできることは、デバッグ時に、自分のプログラムに直接(たとえば、gdbを使用して、数分前にコンパイルした実行中のバイナリにアタッチする)だけでなく、プログラムを実行できない一般的な知識にも非常に役立ちます正しく動作しているように見えます(なぜこのプログラムに時間がかかるのですか?何を開こうとしているのですか?)。

プログラムはprctl(PR_SET_DUMPABLE, 0);を設定することでこれをオプトアウトできます。これは通常、機密データ(キーリング、キーエージェント...)を保持するプログラムによって行われます

ただし、ほとんどのユーザーはそれを必要としないか使用していません。この機能は、ユーザーセッションの悪意のあるプログラムが他のプログラムを変更する可能性があることを意味します-ここで ほとんどのユーザーデータが存在します -たとえば、使用されている資格情報を抽出します完全に別のアカウント。

これを阻止するために、このデバッグインターフェース(ptrace syscall)を保護するYamaと呼ばれるLinux Security Module(LSM)を書いた人もいます。これらのモードを定義します。

  • 0-従来のptraceアクセス許可:プロセスは、それがダンプ可能である(つまり、uidを移行しなかったか、特権を開始していないか、すでにprctl(PR_SET_DUMPABLE ...)を呼び出している)限り、同じuidで実行されている他のプロセスにPTRACE_ATTACHできます。同様に、PTRACE_TRACEMEは変更されていません。

  • 1-制限付きptrace:プロセスには、PTRACE_ATTACHを呼び出したい下位との関係が事前定義されている必要があります。デフォルトでは、この関係は、上記の従来の基準も満たされた場合の子孫のみの関係です。関係を変更するために、下位はprctl(PR_SET_PTRACER、debugger、...)を呼び出して、許可されたデバッガPIDを宣言し、下位でPTRACE_ATTACHを呼び出すことができます。 PTRACE_TRACEMEの使用に変更はありません。

  • 2-管理者のみのアタッチ:CAP_SYS_PTRACEを持つプロセスのみが、PTRACE_ATTACHで、または子を介してPTRACE_TRACEMEを呼び出すptraceを使用できます。

  • 3-アタッチなし:PTRACE_ATTACHを指定したプロセスやPTRACE_TRACEMEを介したプロセスはプロセスで使用できません。一度設定すると、このsysctl値は変更できません。

完全なドキュメントは https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/Documentation/security/Yama.txt?h=v4 .4.199

現在、ほとんどのカーネルはデフォルトでオプション1を使用しています。これにより、上記の攻撃シナリオをブロックしながら、一部のユーザーをトレースできます。

それでも、従来の方法とは異なり、開発者にとっては煩わしいものになる可能性があります。 * nixシステムと同様に、Microsoftも伝統的に任意のプロセスへの接続を許可しています。最近(Windows Vista)、追加された Integrity Levels により、オプトインベースで、別の信頼(ブラウザプロセスなど)でプログラムを実行できます これらのアクションを実行することはできません

2
Ángel