Временно олицетворять и включать привилегии? - PullRequest
2 голосов
/ 17 марта 2010

Мы поддерживаем DLL, которая делает много системных вещей; обход файловой системы, реестра и т. д. Призыватели этой DLL-библиотеки могут использовать или не использовать олицетворение. Чтобы лучше поддерживать все возможные сценарии, я пытаюсь изменить его, чтобы он был умнее. Я буду использовать пример удаления файла. В настоящее время мы просто вызываем DeleteFile (), и если это не удается, это конец. Я придумал следующее:

BOOL TryReallyHardToDeleteFile(LPCTSTR lpFileName)
{
    // 1. caller without privilege
    BOOL bSuccess = DeleteFile(lpFileName);
    DWORD dwError = GetLastError();
    if(!bSuccess && dwError == ERROR_ACCESS_DENIED)
    {
        // failed with access denied; try with privilege
        DWORD dwOldRestorePrivilege = 0;
        BOOL bHasRestorePrivilege = SetPrivilege(SE_RESTORE_NAME, SE_PRIVILEGE_ENABLED, &dwOldRestorePrivilege);
        if(bHasRestorePrivilege)
        {
            // 2. caller with privilege
            bSuccess = DeleteFile(lpFileName);
            dwError = GetLastError();
            SetPrivilege(SE_RESTORE_NAME, dwOldRestorePrivilege, NULL);
        }
        if(!bSuccess && dwError == ERROR_ACCESS_DENIED)
        {
            // failed with access denied; if caller is impersonating then try as process
            HANDLE hToken = NULL;
            if(OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_IMPERSONATE, TRUE, &hToken))
            {
                if(RevertToSelf())
                {
                    // 3. process without privilege
                    bSuccess = DeleteFile(lpFileName);
                    dwError = GetLastError();
                    if(!bSuccess && dwError == ERROR_ACCESS_DENIED)
                    {
                        // failed with access denied; try with privilege
                        bHasRestorePrivilege = SetPrivilege(SE_RESTORE_NAME, SE_PRIVILEGE_ENABLED, &dwOldRestorePrivilege);
                        if(bHasRestorePrivilege)
                        {
                            // 4. process with privilege
                            bSuccess = DeleteFile(lpFileName);
                            dwError = GetLastError();
                            SetPrivilege(SE_RESTORE_NAME, dwOldRestorePrivilege, NULL);
                        }
                    }
                    SetThreadToken(NULL, hToken);
                }
                CloseHandle(hToken);
                hToken = NULL;
            }
        }
    }
    if(!bSuccess)
    {
        SetLastError(dwError);
    }
    return bSuccess;
}

Итак, сначала он пытается звонить. Если это не удается, когда доступ запрещен, он временно включает привилегии в токене вызывающего абонента и пытается снова. Если произойдет сбой при отказе в доступе, а вызывающий абонент будет выдавать себя за другого, он временно не будет выдавать себя за другого и попытается снова Если произойдет сбой при отказе в доступе, он временно активирует привилегии в маркере процесса и попытается снова. Я думаю, что это должно справиться практически с любой ситуацией, но мне было интересно, есть ли лучший способ добиться этого? Существует множество операций, которые мы потенциально хотели бы использовать этот метод (то есть практически любую операцию, которая обращается к защищаемым объектам).

Ответы [ 3 ]

1 голос
/ 18 марта 2010

Резервное копирование и восстановление привилегий вместе обеспечат полный доступ ко всем файлам, полную остановку. Они доступны для LocalSystem. Вы должны открыть файлы с помощью FILE_FLAG_BACKUP_SEMANTICS, чтобы использовать это. Некоторые Win32 API не были предназначены для использования с этим и не будут передавать флаг ядру, хотя в некоторых из этих случаев вы можете использовать CreateFile, чтобы открыть каталог. (Для ядра каталоги - это просто другой вид файла).

Если вам действительно нужно иметь доступ ко всему, я бы сказал, включите эти привилегии и выполните операции сканирования, которые должны завершиться успешно, независимо от безопасности вызывающего абонента.

Одна нерешенная проблема заключается в том, что файлы могут быть заблокированы или открыты, но без общего доступа. Нет способа обойти это из пользовательского режима (без уничтожения процесса, который владеет ресурсом, возможно, излишним). Вот почему известные мне сканеры реализуют эту функцию с помощью драйвера фильтра файловой системы в режиме ядра.

Кроме того, подумайте об аудите: хотите, чтобы записи аудита отображались для LocalSystem или для пользователя, связанного с вызывающим процессом?

0 голосов
/ 24 марта 2010

единственный способ сделать это - запустить как службу и выдать себя за пользователя внутри службы. службе должна быть предоставлена ​​ привилегия олицетворения, которой все учетные записи служб предоставляются по умолчанию. когда вы выдаете себя за абонента, вам, вероятно, придется выдавать себя за делегирование, чтобы вы могли легко выйти из машины.

0 голосов
/ 17 марта 2010

все это кажется действительно интересным для DLL! это звучит как работа для службы , а не для DLL, или, если вы собираетесь разрешить учетной записи пользователя удалять данные, помещенные туда привилегированной учетной записью, то почему бы просто не установить ACL на объект, который разрешает операцию удаления?

С учетом сказанного, что вы на самом деле пытаетесь сделать? Учетная запись пользователя обычно не может удалять данные, помещенные туда учетной записью администратора!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...