Кто-нибудь знает, как получить SACL для удаленной службы с помощью C#? Я пробовал множество разных методов, но в основном ничего не работает. Я могу получить списки DACL и SACL на локальном компьютере, но получить их на удаленном компьютере не представляется возможным.
Что я сделал, так это создал класс под названием ServiceSecurity, который наследуется от NativeObjectSecurity и действует во многом как класс RegistrySecurity. Ниже приведены два конструктора, которые у меня есть:
public ServiceSecurity(string serviceName, AccessControlSections includeSections)
: base(true, ResourceType.Service, serviceName, includeSections, null, null)
{
}
public ServiceSecurity(System.Runtime.InteropServices.SafeHandle handle, AccessControlSections includeSections)
: base(true, ResourceType.Service, handle, includeSections)
{
}
Первый использует имя службы, а второй ожидает дескриптор службы. Очевидно, что первый отлично работает для получения DACL и SACL, потому что он все локален, но чтобы добраться до удаленной машины, я использую класс ServiceController для поиска службы на удаленной машине. Получив его, я передаю свойство ServiceHandle службы созданному мной классу ServiceSecurity, и в этот момент я получаю исключение несанкционированного доступа, что не кажется правильным, потому что моя учетная запись пользователя является администратором домена для домена, и локальный администратор на целевом поле. У меня также есть право SeSecurityPrivilege, которое должно позволить мне доступ.
У кого-нибудь есть идеи? Кажется, что SafeHandle, который я получаю, неправильный, но свойства SafeHandle говорят, что он не закрыт и что это действительный дескриптор, поэтому я не совсем понимаю, что происходит.
Вот код, который я использую, чтобы попытаться получить данные:
ServiceSecurity sSec = new ServiceSecurity(services[i].ServiceName, accessSections);
string outputData = sSec.GetSecurityDescriptorSddlForm(accessSections);
Вышеупомянутое будет работать для локальных разрешений и настроек аудита (DACL и SACL). Но он предназначен для работы на локальной машине. Если я сделаю это вместо этого:
ServiceSecurity sSec = new ServiceSecurity(services[i].ServiceHandle, accessSections);
string outputData = sSec.GetSecurityDescriptorSddlForm(accessSections);
Конструктор ServiceSecurity не работает как на локальных, так и на удаленных серверах для SACL следующим образом, но по-прежнему работает для DACL:
System.UnauthorizedAccessException: Attempted to perform an unauthorized operation.
at System.Security.AccessControl.Win32.GetSecurityInfo(ResourceType resourceType, String name, SafeHandle handle, AccessControlSections accessControlSections, RawSecurityDescriptor& resultSd)
at System.Security.AccessControl.NativeObjectSecurity.CreateInternal(ResourceType resourceType, Boolean isContainer, String name, SafeHandle handle, AccessControlSections includeSections, Boolean createByName, ExceptionFromErrorCode exceptionFromErrorCode, Object exceptionContext)
at System.Security.AccessControl.NativeObjectSecurity..ctor(Boolean isContainer, ResourceType resourceType, SafeHandle handle, AccessControlSections includeSections)
Для разделов доступа я указываю только один из AccessControlSections, будь то аудит или доступ и аудит, кажется, терпят неудачу каждый раз, когда я передаю ServiceHandle.
Обновлять:
Так что, возможно, действительно стоит вопрос, как мне получить дескриптор службы, имеющей права ACCESS_SYSTEM_SECURITY, чтобы я мог получить SACL?
На самом деле он не работает в конструкторе, который я перечислил





Дескриптор, который вы получаете от ServiceController, не будет иметь прав ACCESS_SYSTEM_SECURITY, поэтому вы не можете получить доступ к SACL с его помощью.
Чтобы получить это право, вам нужно разобраться с этим правом. Возможно, вам потребуется использовать DuplicateHandle для получения дополнительных прав, но включение SeSecurityPrivilege для удаленной системы может оказаться сложной задачей.
Вы пробовали использовать именованный конструктор службы с удаленным именем?
Мне нужно немного проверить это и вернуться к вам. Если к завтрашнему дню никто не ответит лучше, я откопаю для вас ответ.
Обновлено: Под именованным конструктором службы я имею в виду попытаться создать объект ServiceSecurity с именем службы в форме \\ server_name \ service_name или \\ IP_address \ service_name. Теоретически это должно работать, но это может не быть из-за того, что SeSecurityPrivilege будет включен на локальном компьютере, а не на удаленном.
Чтобы получить дескриптор с предоставленным правом ACCESS_SYSTEM_SECURITY, вы должны выполнить следующие шаги:
К сожалению, у меня нет тестовой среды, настроенной должным образом, чтобы проверить это, поэтому я не могу гарантировать, что она будет работать для удаленных служб. Включение SeSecurityPrivilege для удаленного сервера кажется основным камнем преткновения. В любом случае, я надеюсь, что это хоть немного поможет.
Я подумал, что права ACCESS_SYSTEM_SECURITY могут иметь к этому какое-то отношение. Я не понял, как применить их напрямую или создать дескриптор с этими правами. Не совсем понимаю, что вы имеете в виду под именованным конструктором службы.
Какой метод вы используете для получения информации? GetNamedSecurityInfo?