Określ, czy proces systemu Windows ma uprawnienia do tworzenia dowiązania symbolicznego
Chcę programowo określić, czy bieżący użytkownik (lub proces) ma dostęp do tworzenia dowiązań symbolicznych. W systemie Windows (Vista i nowszym) nie można utworzyć dowiązania symbolicznego bez SeCreateSymbolicLinkPrivilege i domyślnie jest ono przypisywane tylko administratorom. Jeśli ktoś próbuje utworzyć dowiązanie symboliczne bez tego przywileju, pojawia się błąd systemu Windows 1314 (klient nie ma wymaganego przywileju).
Aby zademonstrować to ograniczenie, stworzyłem czystą instalację systemu Windows, zalogowanego jako początkowe konto administratora (ograniczone przez UAC) i nie mogłem utworzyć dowiązania symbolicznego w katalogu domowym.
Po uruchomieniu wiersza polecenia jako administrator lub wyłączeniu kontroli konta użytkownika polecenie to jest wykonywane bez błędu.
WedługTen artykuł, „każdy proces wykonywany w imieniu użytkownika ma kopię tokena [dostęp]”.
Więc stworzyłemskrypt Pythona do wyszukiwania uprawnień. Dla wygody i potomności zamieszczam poniżej fragment.
Ideą skryptu jest wyliczenie wszystkich uprawnień i określenie, czy proces ma wymagane uprawnienia. Niestety, uważam, że obecny proces w rzeczywistości nie ma pożądanego przywileju, nawet jeśli może tworzyć dowiązania symboliczne.
Podejrzewam, że problem polega na tym, że nawet jeśli obecne uprawnienia użytkownika nie obejmują wyraźnie tego przywileju, jego członkostwo w grupie pozwala na ten przywilej.
W skrócie, jak mogę określić, czy dany proces będzie miał przywilej tworzenia dowiązań symbolicznych (bez próby jego utworzenia)? Preferowany jest przykład w C lub C ++ lub Pythonie, choć odpowiednie będzie wszystko, co wykorzystuje API Windows.
def get_process_token():
token = wintypes.HANDLE()
TOKEN_ALL_ACCESS = 0xf01ff
res = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, token)
if not res > 0: raise RuntimeError("Couldn't get process token")
return token
def get_privilege_information():
# first call with zero length to determine what size buffer we need
return_length = wintypes.DWORD()
params = [
get_process_token(),
TOKEN_INFORMATION_CLASS.TokenPrivileges,
None,
0,
return_length,
]
res = GetTokenInformation(*params)
# assume we now have the necessary length in return_length
buffer = ctypes.create_string_buffer(return_length.value)
params[2] = buffer
params[3] = return_length.value
res = GetTokenInformation(*params)
assert res > 0, "Error in second GetTokenInformation (%d)" % res
privileges = ctypes.cast(buffer, ctypes.POINTER(TOKEN_PRIVILEGES)).contents
return privileges
privileges = get_privilege_information()
print("found {0} privileges".format(privileges.count))
map(print, privileges)