7

DCOMのプログラミング方法についてはあらゆる種類のものを見つけることができますが、プログラムでセキュリティを設定/チェックする方法については実際には何もありません。

私はdcomcnfgを再作成しようとはしていませんが、C#(推奨、またはVB.net)でdcomcnfgのすべての機能を再現する方法を知っていれば、私の目標は見えています。

これに関する優れたリソース、オープンソースAPI、または各ステップの実行方法の簡単な例さえも見つけることができないようです。ここでも、DCOMまたはdcomcnfgはほとんど結果を返さず、セキュリティを設定/検証/一覧表示する方法については何も返しません。

誰かがオープンAPIまたはいくつかの例へのポインタを持っているなら、私はそれをいただければ幸いです。

4

5 に答える 5

12

ダニエルが投稿した回答は非常に役に立ちました。どうもありがとう、ダニエル!

Microsoft のドキュメントの問題は、レジストリ値に ACL がバイナリ形式で含まれていることを示していることです。したがって、たとえば、(プロセスごとではなく) コンピューターの既定のアクセスを設定しようとしている場合は、レジストリ キー HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole\DefaultAccessPermission にアクセスすることになります。ただし、最初に System.Security.AccessControl.RawACL クラスを使用してこのキーにアクセスしようとすると失敗しました。

ダニエルのコードが示すように、値は実際には ACL ではなく、ACL を含む SecurityDescriptor です。

したがって、この投稿が古いことはわかっていますが、セキュリティ設定を確認して設定し、デフォルトのローカル アクセス用に NetworkService を追加するためのソリューションを投稿します。もちろん、これを利用して改善することもできますが、開始するには、キーとアクセス マスクを変更するだけで済みます。

static class ComACLRights{
    public const int COM_RIGHTS_EXECUTE= 1;
    public const int COM_RIGHTS_EXECUTE_LOCAL = 2;
    public const int COM_RIGHTS_EXECUTE_REMOTE = 4;
    public const int COM_RIGHTS_ACTIVATE_LOCAL = 8;
    public const int COM_RIGHTS_ACTIVATE_REMOTE = 16;
}
class Program
{
    static void Main(string[] args)
    {
        var value = Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Ole", "DefaultAccessPermission", null);

        RawSecurityDescriptor sd;
        RawAcl acl;

        if (value == null)
        {
            System.Console.WriteLine("Default Access Permission key has not been created yet");
            sd = new RawSecurityDescriptor("");
        }else{
            sd = new RawSecurityDescriptor(value as byte[], 0);
        }
        acl = sd.DiscretionaryAcl;
        bool found = false;
        foreach (CommonAce ca in acl)
        {
            if (ca.SecurityIdentifier.IsWellKnown(WellKnownSidType.NetworkServiceSid))
            {
                //ensure local access is set
                ca.AccessMask |= ComACLRights.COM_RIGHTS_EXECUTE | ComACLRights.COM_RIGHTS_EXECUTE_LOCAL | ComACLRights.COM_RIGHTS_ACTIVATE_LOCAL;    //set local access.  Always set execute
                found = true;
                break;
            }
        }
        if(!found){
            //Network Service was not found.  Add it to the ACL
            SecurityIdentifier si = new SecurityIdentifier( 
                WellKnownSidType.NetworkServiceSid, null);
            CommonAce ca = new CommonAce(
                AceFlags.None, 
                AceQualifier.AccessAllowed, 
                ComACLRights.COM_RIGHTS_EXECUTE | ComACLRights.COM_RIGHTS_EXECUTE_LOCAL | ComACLRights.COM_RIGHTS_ACTIVATE_LOCAL, 
                si, 
                false, 
                null);
            acl.InsertAce(acl.Count, ca);
        }
        //re-set the ACL
        sd.DiscretionaryAcl = acl;

        byte[] binaryform = new byte[sd.BinaryLength];
        sd.GetBinaryForm(binaryform, 0);
        Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Ole", "DefaultAccessPermission", binaryform, RegistryValueKind.Binary);
    }
}
于 2013-03-26T13:26:27.903 に答える
7

同様の状況 (MSI からの DCOM セキュリティの構成) に直面して、HKEY_CLASSES_ROOT\AppID{APP-GUID-GOES-HERE} のレジストリ キーの値を変更することで、必要なソリューションを作成することができました。私を正しい道に導いてくれたArnoutの答えに感謝します。

具体的には、LaunchPermission および AccessPermission レジストリ キー値に格納されている DCOM オブジェクトのセキュリティ アクセス許可を編集するメソッドを作成しました。これらはシリアル化されたセキュリティ記述子であり、バイナリ データを に渡すことでアクセスできますRawSecurityDescriptor。このクラスは、多くの詳細をおいしい .NET 形式で簡素化しますが、Windows ACL に関するすべての論理的な詳細に注意を払う必要があり、.NET を使用してセキュリティ記述子をレジストリに書き戻す必要があります RawSecurityDescriptor.GetBinaryForm

私が作成したメソッドは と呼ばれていましたEditOrCreateACE。このメソッドは、アカウントの既存の ACE を編集するか、新しい ACE を挿入して、アクセス マスクに渡されたフラグが設定されていることを確認します。としてここに添付します。これは、Windows ACL のことをまだほとんど知らないため、対処方法に関する権威ではありません。

// These are constants for the access mask on LaunchPermission.
// I'm unsure of the exact constants for AccessPermission
private const int COM_RIGHTS_EXECUTE = 1;
private const int COM_RIGHTS_EXECUTE_LOCAL = 2;
private const int COM_RIGHTS_EXECUTE_REMOTE = 4;
private const int COM_RIGHTS_ACTIVATE_LOCAL = 8;
private const int COM_RIGHTS_ACTIVATE_REMOTE = 16;

void EditOrCreateACE(string keyname, string valuename,
                      string accountname, int mask)
{
    // Get security descriptor from registry
    byte[] keyval = (byte[]) Registry.GetValue(keyname, valuename,
                                               new byte[] { });
    RawSecurityDescriptor sd;
    if (keyval.Length > 0) {
        sd = new RawSecurityDescriptor(keyval, 0);
    } else {
        sd = InitializeEmptySecurityDescriptor();
    }
    RawAcl acl = sd.DiscretionaryAcl;

    CommonAce accountACE = null;

    // Look for the account in the ACL
    int i = 0;
    foreach (GenericAce ace in acl) {
        if (ace.AceType == AceType.AccessAllowed) {
            CommonAce c_ace = ace as CommonAce;
            NTAccount account = 
                c_ace.SecurityIdentifier.Translate(typeof(NTAccount))
                as NTAccount;
            if (account.Value.Contains(accountname)) {
                accountACE = c_ace;
            }
            i++;
        }
    }

    // If no ACE found for the given account, insert a new one at the end
    // of the ACL, otherwise just set the mask
    if (accountACE == null) {
        SecurityIdentifier ns_account = 
            (new NTAccount(accountname)).Translate(typeof(SecurityIdentifier))
            as SecurityIdentifier;
        CommonAce ns = new CommonAce(AceFlags.None, AceQualifier.AccessAllowed,
                                     mask, ns_account, false, null);
        acl.InsertAce(acl.Count, ns);
    } else {
        accountACE.AccessMask |= mask;
    }

    // Write security descriptor back to registry
    byte[] binarySd = new byte[sd.BinaryLength];
    sd.GetBinaryForm(binarySd, 0);
    Registry.SetValue(keyname, valuename, binarySd);
}

private static RawSecurityDescriptor InitializeEmptySecurityDescriptor()
{
    var localSystem = 
        new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null);
    var new_sd =
        new RawSecurityDescriptor(ControlFlags.DiscretionaryAclPresent,
                                  localSystem, localSystem, null,
                                  new RawAcl(GenericAcl.AclRevision, 1));
    return new_sd;
}

このコードは決して完璧ではないことに注意してください。これらの ACL のレジストリ キー値全体がレジストリに存在しない場合、合成された ACL は渡されたアカウントへのアクセスのみを許可し、それ以外は何も許可しません。また、適切に処理できていないエラー状態や、詳細を見逃しているエラーがたくさんあると確信しています。繰り返しますが、これは .NET で DCOM ACL を処理する方法の例です。

于 2012-07-25T11:38:41.303 に答える
4

これを行う .NET の方法が見つかりませんでした。SDK の一部である MS コマンド ライン ユーティリティDCOMPerm (こちらも参照) を使用できます。

于 2009-01-18T21:16:03.100 に答える
4

この情報は と に保存されHKCR\AppID\{Your-AppID}\LaunchPermissionますAccessPermission。これらは、シリアル化されたセキュリティ記述子を含む REG_BINARY 値です。.NET からの便利なアクセスを提供するものがあるかどうかはわかりません...

詳細については、MSDNを参照してください。

于 2009-01-18T21:42:25.327 に答える