0

私はドメイン管理者で、API (C++ など) でプログラムを使用して、ドメインの一部のサーバーにある共有フォルダーの所有権を取得したいと考えています。いくつかの読み取り作業を行ったところ、ドメイン管理者はデフォルトでメンバー マシンの Local Admins グループに含まれており、Local Admins ユーザーはとにかく所有権を取得できることがわかりました。この方法でいくつかのコードを書きましたが、GetNamedSecurityInfo を使用して所有者の sid を取得するときに ERROR_ACCESS_DENIED が発生しましたか? 問題はどこですか?

興味深い点: GetNamedSecurityInfo の 2 番目の引数を SE_FILE_OBJECT から SE_LMSHARE に変更すると、成功します (1 つも設定されます)。しかし、フォルダーのプロパティの [セキュリティ] タブで所有者が変更されたことはわかりませんでした。「共有」権限は「セキュリティ」権限とは異なることを知っています。「共有」権限には所有者がいなくても。では、SE_LMSHARE 引数で GetNamedSecurityInfo を呼び出したときに、どの所有者を取得したのでしょうか?

サーバー「strServerName」でフォルダー「strFileName」の所有権を取得するために使用する機能は次のとおりです。変更された所有者は、「strDomainName」「strUserName」「strPassword」として知られるドメイン管理者アカウントであり、元の所有者は「pOriginSID」で予約されています"。GetNamedSecurityInfo 呼び出し (これも Set の呼び出し) でエラー コード 5 を受け取りました。動作しないように見える偽装メソッド「logOnByUserPassword」も書いているので、以下に貼り付けます。

HANDLE ADPermissionSearch::getAccessTokenByCredential(CString strDomainName, CString strUserName, CString strPassword) {

CString strUPNUserName = strUserName + _T("@") + strDomainName;

HANDLE hToken;
BOOL bResult;
//bResult = LogonUser(strUserName, strDomainName, strPassword, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT,
//  &hToken);
if (strDomainName != _T(""))
{
    bResult = LogonUser(strUPNUserName, _T(""), strPassword, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, 
        &hToken);
}
else
{
    bResult = LogonUser(strUserName, _T("."), strPassword, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, 
        &hToken);
}
if (bResult == FALSE)
{
    MyMessageBox_Error(_T("getAccessTokenByCredential Error."), _T("Error"));
    return FALSE;
}
else
{
    return hToken;
}

}

int ADPermissionSearch::takeOwnership(CString strServerName, CString strFileName, CString strDomainName, CString strUserName, CString strPassword, __out PSID &pOriginSID) {

CString strUNCFileName = _T("\\\\") + strServerName + _T("\\") + strFileName;
_bstr_t bstrUNCFileName = _bstr_t(strUNCFileName);
PSID pSIDAdmin = NULL;
SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
HANDLE hToken = NULL;
DWORD dwRes;

// Create a SID for the BUILTIN\Administrators group.
if (!AllocateAndInitializeSid(&SIDAuthNT, 2,
    SECURITY_BUILTIN_DOMAIN_RID,
    DOMAIN_ALIAS_RID_ADMINS,
    0, 0, 0, 0, 0, 0,
    &pSIDAdmin))
{
    if (pSIDAdmin)
        FreeSid(pSIDAdmin);
    if (hToken)
        CloseHandle(hToken);
    MyMessageBox_Error(_T("takeOwnership"));
    return 0;
}

// If the preceding call failed because access was denied,
// enable the SE_TAKE_OWNERSHIP_NAME privilege, create a SID for
// the Administrators group, take ownership of the object, and
// disable the privilege. Then try again to set the object's DACL.

// Open a handle to the access token for the calling process.
/*
if (!OpenProcessToken(GetCurrentProcess(),
                      TOKEN_ADJUST_PRIVILEGES,
                      &hToken))
{
    if (pSIDAdmin)
        FreeSid(pSIDAdmin);
    if (hToken)
        CloseHandle(hToken);
    MyMessageBox_Error(_T("takeOwnership"));
    return 0;
}
*/
if ((hToken = getAccessTokenByCredential(strDomainName, strUserName, strPassword)) == NULL)
{
    if (pSIDAdmin)
        FreeSid(pSIDAdmin);
    if (hToken)
        CloseHandle(hToken);
    MyMessageBox_Error(_T("takeOwnership"));
    return 0;
}

// Enable the SE_TAKE_OWNERSHIP_NAME privilege.
if (!setPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, TRUE))
{
    if (pSIDAdmin)
        FreeSid(pSIDAdmin);
    if (hToken)
        CloseHandle(hToken);
    MyMessageBox_Error(_T("takeOwnership"));
    return 0;
}

// Get the original owner in the object's security descriptor.
dwRes = GetNamedSecurityInfo(
    bstrUNCFileName,             // name of the object
    SE_FILE_OBJECT,                  // type of object
    OWNER_SECURITY_INFORMATION,  // change only the object's owner
    &pOriginSID,                 // SID of Administrator group
    NULL,
    NULL,
    NULL,
    NULL);
if (dwRes != ERROR_SUCCESS)
{
    if (pSIDAdmin)
        FreeSid(pSIDAdmin);
    if (hToken)
        CloseHandle(hToken);
    MyMessageBox_Error(_T("takeOwnership"));
    return 0;
}

// Set the owner in the object's security descriptor.
dwRes = SetNamedSecurityInfo(
            bstrUNCFileName,             // name of the object
            SE_FILE_OBJECT,                  // type of object
            OWNER_SECURITY_INFORMATION,  // change only the object's owner
            pSIDAdmin,                   // SID of Administrator group
            NULL,
            NULL,
            NULL);
if (dwRes != ERROR_SUCCESS)
{
    if (pSIDAdmin)
        FreeSid(pSIDAdmin);
    if (hToken)
        CloseHandle(hToken);
    MyMessageBox_Error(_T("takeOwnership"));
    return 0;
}

// Disable the SE_TAKE_OWNERSHIP_NAME privilege.
if (!setPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, FALSE))
{
    if (pSIDAdmin)
        FreeSid(pSIDAdmin);
    if (hToken)
        CloseHandle(hToken);
    MyMessageBox_Error(_T("takeOwnership"));
    return 0;
}

return 1;

}

BOOL ADDirectorySearch::logOnByUserPassword(CString strDomainName, CString strUserName, CString strPassword) {

CString strUPNUserName = strUserName + _T("@") + strDomainName;

HANDLE hToken;
BOOL bResult;
//bResult = LogonUser(strUserName, strDomainName, strPassword, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT,
//  &hToken);
if (strDomainName != _T(""))
{
    bResult = LogonUser(strUPNUserName, _T(""), strPassword, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, 
        &hToken);
}
else
{
    bResult = LogonUser(strUserName, _T("."), strPassword, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, 
        &hToken);
}
if (bResult == FALSE)
{
    MyMessageBox_Error(_T("logOnByUserPassword Error."), _T("Error"));
    return FALSE;
}
else
{
    bResult = ImpersonateLoggedOnUser(hToken);
    if (bResult == FALSE)
    {
        MyMessageBox_Error(_T("logOnByUserPassword Error."), _T("Error"));
        return FALSE;
    }
    else
    {
        return TRUE;
    }
}

}

4

1 に答える 1

1

ローカル管理者は、1 つの例外を除いて、通常の Windows セキュリティ チェックの対象となります。アクセス許可に関係なく、セキュリティで保護されたオブジェクトの所有権を常に取得できます。これにより、管理者は常に制御を取り戻すことができます。

ただし、所有権を取得しようとしているのではなく、現在の所有者を読み取ろうとしており、必ずしもそれを行う権限があるとは限りません。

コードからは、所有者を読み取ろうとしている理由が明確ではありません。あなたはそれで何もしていないようです。おそらく、GetNamedSecurityInfo への呼び出しを完全に削除してください。

アップデート

目的は、すべての共有で DACL をチェックするプログラムを作成することです。そのため、現在の所有者を保存し、所有権を取得し、DACL を読み取り、所有者を復元する必要があります。ただし、所有権が取得されるまで、現在の所有者を読み取ることはできません。

この動作は仕様によるものだと思います。当初の意図は、管理者が所有権を取得できるようにすることでしたが、オブジェクトの所有者から所有していたという事実を隠すことはできませんでしたが、これを回避する方法はあります。たとえば、ファイルの場合、バックアップ特権を有効にし、BackupRead を呼び出し、出力 (データが続く WIN32_STREAM_ID 構造のシーケンス) を解析することにより、完全なセキュリティ記述子 (所有者を含む) を読み取ることができます。もっと簡単な方法があるかどうかはわかりません。

共有に関する情報は、次のレジストリに保存されます。

SYSTEM\CurrentControlSet\Services\LanmanServer\Shares

セキュリティ情報はSecurity、共有にちなんで名付けられた値のサブキーに保存されているようです。このバイナリ値はセキュリティ記述子のように見えるため、所有者を で読み取ることができますGetSecurityDescriptorOwner。このセキュリティ記述子から他のすべてのセキュリティ情報を読み取ることもできるため、所有者を変更する必要はまったくありません。

于 2012-07-08T18:26:59.593 に答える