2

CreateNamedPipeWindows APIを使用して二重の名前付きパイプを作成し、シェル拡張とメインのデスクトップ アプリケーション間の IPC に使用しようとしています。

リモート接続を防止する、Vista 以降の関数に渡すことができるフラグがあります ( PIPE_REJECT_REMOTE_CLIENTS)。私が理解していることから、それはパイプが同じマシンでのみ接続可能であることを意味します。以前のバージョンの Windows で同じ機能を取得する方法を知っている人はいますか? 次のコードでオブジェクトを作成しようとしましたSECURITY_ATTRIBUTESが、正しく動作しているかどうか完全にはわかりません:

static bool GetLocalMachineOnlySecurityAttributes (SECURITY_ATTRIBUTES& sa)
{
    PSID plocalsid = NULL;
    SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_LOCAL_SID_AUTHORITY;
    if(!::AllocateAndInitializeSid (&SIDAuthWorld, 1, SECURITY_LOCAL_RID, 0, 0, 0, 0, 0, 0, 0, &plocalsid))
        return false;

    EXPLICIT_ACCESS ea = {0};
    ea.grfAccessPermissions = SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL;
    ea.grfAccessMode = SET_ACCESS;
    ea.grfInheritance = NO_INHERITANCE;
    ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
    ea.Trustee.ptstrName  = reinterpret_cast<LPWSTR>(plocalsid);

    PACL acl = NULL;
    if(!::SetEntriesInAcl (1, &ea, NULL, &acl))
        return false;

    //PSECURITY_DESCRIPTOR sd = reinterpret_cast<PSECURITY_DESCRIPTOR>(::LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH));
    static SECURITY_DESCRIPTOR sd = {0};
    if(!::InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION))
        return false;
    if(!::SetSecurityDescriptorDacl(&sd, TRUE, acl, FALSE))
        return false;

    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = &sd;
    sa.bInheritHandle = FALSE;
    return true;
}

私が正しいことをしているかどうか、または の決定的な説明を探すことができる場所を教えてくれる人がいれば、SECURITY_ATTRIBUTESとても感謝しています.

4

1 に答える 1

3

実際、パイプに適切な随意アクセス制御リスト (DACL) を作成することで、リモート接続を防ぐことができます。

あなたのコードはそれを試みていますが失敗しています。最初の理由は次の行にあります:

if(!::SetEntriesInAcl (1, &ea, NULL, &acl)) 

SetEntriesInAcl は、BOOL ではなく DWORD コードを返します。成功するとERROR_SUCCESS、値が 0L のコードが返されるため、関数は常にこの時点で終了し、SECURITY_ATTRIBUTES 構造は空のままになります。

コードは、SetEntriesInAcl. MSDN の例をガイドとして使用して、必要なすべてのクリーンアップを確実に行うことをお勧めします。

コードの戦略に目を向けると、現在、ローカル セキュリティ グループのすべてのアクセスを許可する単一のアクセス制御エントリ (ACE) を使用して問題を解決しようとしています。DACL の仕組み上、これは適切な方法ではありません。ローカル アクセスをホワイトリストに登録するのではなく、リモート アクセスを拒否する (つまり、ブラックリストに登録する) 必要があります。これには、少なくとも次の 2 つの理由があります。

  • 単一の ACE では、パイプにアクセスできるすべての人がまったく同じアクセス権を持ちます。つまり、パイプのセキュリティをより厳密に制御する能力が失われます。通常、少なくとも、目的のパイプ サーバーのみがパイプの新しいインスタンスを作成できるようにし、パイプのセキュリティを変更する機能を制限する必要があります。
  • アクセス トークンに Local グループのメンバーシップが付与される正確な状況は十分に文書化されておらず、このグループのグループ メンバーシップが要件と正確に一致していないと思われます。CreateNamedPipe のドキュメントには、以前のプラットフォームで PIPE_REJECT_REMOTE_CLIENTS と同じ結果を得るには、NETWORK へのアクセスを拒否する必要があることが明示的に記載されています。

そのため、次の ACE を含む DACL を構築するようにコードを修正する必要があります。

  1. すべてのアクセスを拒否する、既知のセキュリティ識別子グループ NETWORK USERS の「拒否」ACE
  2. パイプ サーバーであるアプリケーションがパイプのインスタンスを作成することを許可する「許可」ACE
  3. パイプ クライアントであるアプリケーションにパイプへの読み書きを許可する「許可」ACE

これらの最初のものは、SMB ベースのリモート名前付きパイプ プロトコルを含むリモート アクセス プロトコルによって作成されたすべてのログオン トークンに、自動的に NETWORK USERS グループ (既知の SID S-1-5-2)。この拒否 ACE は、DACL 内の許可 ACE の前に来る必要があります。

どのアプリケーションがパイプ サーバーで、どのアプリケーションがクライアントであるかはわかりません。両方が対話型ユーザーのセッションで実行される場合は問題にならない場合があります。この場合、ユーザーのセッションの SID へのすべてのアクセスを許可する allow ACE を 1 つだけ使用できる場合があります。

セキュリティ要件の詳細がなければ、サーバー ACE とクライアント ACE をどのようにセットアップする必要があるかを規定することは困難です。ただし、ほぼ確実に、アクセス権 FILE_CREATE_PIPE_INSTANCE を制限して、パイプ サーバーだけが持つようにする必要があります。

于 2012-06-14T12:41:20.633 に答える