mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
220 lines
8.1 KiB
Python
220 lines
8.1 KiB
Python
import windows.security
|
|
from windows.security import SecurityDescriptor
|
|
from .pfwtest import *
|
|
import ctypes
|
|
|
|
|
|
|
|
# CC -> Create-Child -> 1
|
|
# GR -> Generic read -> 0x80000000L
|
|
# AN -> Anonymous -> S-1-5-7
|
|
|
|
TEST_SDDL = [
|
|
"O:ANG:AND:(A;;RPWPCCDCLCSWRCWDWOGA;;;S-1-0-0)(D;;RPWPCCDCLCSWRCWDWOGA;;;S-1-0-0)",
|
|
"O:ANG:AND:(A;;GR;;;S-1-0-0)",
|
|
"O:ANG:AND:(OA;;CC;;00000042-0043-0044-0045-000000000000;S-1-0-0)",
|
|
"O:ANG:AND:(OA;;CCGR;00004242-0043-0044-0045-000000000000;00000042-0043-0044-0045-000000000000;S-1-0-0)",
|
|
]
|
|
|
|
|
|
@pytest.mark.parametrize("sddl", TEST_SDDL)
|
|
def test_security_descriptor_from_string(sddl):
|
|
sd = SecurityDescriptor.from_string(sddl)
|
|
|
|
TEST_BIN_SDDL = [
|
|
# TapiSrv security descriptor
|
|
b'\x01\x00\x14\x80\x8c\x00\x00\x00\x98\x00\x00\x00\x14\x00\x00\x000\x00\x00\x00\x02\x00\x1c\x00\x01\x00\x00\x00\x02\x80\x14\x00\xff\x01\x0f\x00\x01\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x02\x00\\\x00\x04\x00\x00\x00\x00\x00\x14\x00\xfd\x01\x02\x00\x01\x01\x00\x00\x00\x00\x00\x05\x12\x00\x00\x00\x00\x00\x18\x00\xff\x01\x0f\x00\x01\x02\x00\x00\x00\x00\x00\x05 \x00\x00\x00 \x02\x00\x00\x00\x00\x14\x00\x9d\x01\x02\x00\x01\x01\x00\x00\x00\x00\x00\x05\x04\x00\x00\x00\x00\x00\x14\x00\x9d\x01\x02\x00\x01\x01\x00\x00\x00\x00\x00\x05\x06\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x05\x12\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x05\x12\x00\x00\x00',
|
|
]
|
|
|
|
@pytest.mark.parametrize("binsd", TEST_BIN_SDDL)
|
|
def test_security_descriptor_from_binary(binsd):
|
|
sd = SecurityDescriptor.from_binary(binsd)
|
|
|
|
|
|
def test_empty_security_descriptor():
|
|
esd = SecurityDescriptor.from_string("")
|
|
assert esd.owner is None # Should NOT be NULL PSID but None
|
|
assert esd.group is None # Should NOT be NULL PSID but None
|
|
assert esd.dacl is None
|
|
assert esd.sacl is None
|
|
|
|
def test_security_descriptor__str__():
|
|
sddl = "D:(A;;FA;;;WD)"
|
|
sd = SecurityDescriptor.from_string(sddl)
|
|
assert str(sd) == sddl
|
|
|
|
|
|
def test_pacl_object():
|
|
SDDL = "O:ANG:S-1-2-3D:(A;;;;;S-1-42-42)(A;;;;;S-1-42-43)(A;;;;;S-1-42-44)"
|
|
dacl = SecurityDescriptor.from_string(SDDL).dacl
|
|
assert dacl is not None
|
|
assert len(dacl) == 3 # __len__
|
|
assert len(list(dacl)) == 3 # __iter__
|
|
assert len(dacl.aces) == 3
|
|
|
|
assert ctypes.addressof(dacl[0]) == ctypes.addressof(dacl[0]) # __getitem__
|
|
assert len([ctypes.addressof(dacl[i])for i in range(3)]) == 3
|
|
|
|
with pytest.raises(IndexError):
|
|
x = dacl[3]
|
|
|
|
def test_sec_descrip_owner_group():
|
|
SDDL = "O:ANG:S-1-2-3"
|
|
sd = SecurityDescriptor.from_string(SDDL)
|
|
assert sd.owner.to_string() == "S-1-5-7"
|
|
assert sd.group.to_string() == "S-1-2-3"
|
|
assert sd.dacl is None
|
|
assert sd.sacl is None
|
|
|
|
def test_mask_sid_ace():
|
|
SDDL = "D:(A;CIOI;CCGR;;;S-1-42-42)"
|
|
# OBJECT_INHERIT_ACE(0x1L) | CONTAINER_INHERIT_ACE(0x2L)
|
|
# Create-Child | GENERIC_READ(0x80000000L)
|
|
sd = SecurityDescriptor.from_string(SDDL)
|
|
dacl = sd.dacl
|
|
assert dacl is not None
|
|
ace = dacl[0]
|
|
# Test the ACE
|
|
assert ace.Header.AceType == gdef.ACCESS_ALLOWED_ACE_TYPE
|
|
# flags + flags split
|
|
assert ace.Header.AceFlags == gdef.OBJECT_INHERIT_ACE | gdef.CONTAINER_INHERIT_ACE
|
|
assert set(ace.Header.flags) == {gdef.OBJECT_INHERIT_ACE, gdef.CONTAINER_INHERIT_ACE}
|
|
# mask + mask split
|
|
assert ace.Mask == 1 | gdef.GENERIC_READ
|
|
assert set(ace.mask) == {1, gdef.GENERIC_READ}
|
|
# SID
|
|
assert ace.sid.to_string() == "S-1-42-42"
|
|
|
|
|
|
|
|
SGUID = gdef.GUID.from_string
|
|
|
|
COMPLEXE_SDDL_GUID = [
|
|
("D:(OA;;;00000042-0043-0044-0045-000000000001;;S-1-0-0)",
|
|
SGUID("00000042-0043-0044-0045-000000000001"),
|
|
None),
|
|
("D:(OA;;;;00000042-0043-0044-0045-000000000000;S-1-0-0)",
|
|
None,
|
|
SGUID("00000042-0043-0044-0045-000000000000")),
|
|
("D:(OA;;;00000042-0043-0044-0045-000000000002;00000042-0043-0044-0045-000000000003;S-1-0-0)",
|
|
SGUID("00000042-0043-0044-0045-000000000002"),
|
|
SGUID("00000042-0043-0044-0045-000000000003")),
|
|
("D:(OA;;;;;S-1-0-0)",
|
|
None,
|
|
None),
|
|
]
|
|
|
|
@pytest.mark.parametrize("sddl, obj_guid, inherited_object_guid", COMPLEXE_SDDL_GUID)
|
|
def test_complex_ace_guid_sid(sddl, obj_guid, inherited_object_guid):
|
|
sd = SecurityDescriptor.from_string(sddl)
|
|
assert sd.dacl is not None
|
|
ace = sd.dacl[0]
|
|
assert ace.sid.to_string() == "S-1-0-0"
|
|
|
|
if obj_guid is None and inherited_object_guid is None:
|
|
# No GUID -> transformed in ACCESS_ALLOWED_ACE_TYPE
|
|
assert ace.Header.AceType == gdef.ACCESS_ALLOWED_ACE_TYPE
|
|
return
|
|
assert ace.object_type == obj_guid
|
|
assert ace.inherited_object_type == inherited_object_guid
|
|
|
|
ALL_DACL_ACE_TYPES = [
|
|
("D:(A;;;;;S-1-2-3)", gdef.ACCESS_ALLOWED_ACE_TYPE),
|
|
("D:(D;;;;;S-1-2-3)", gdef.ACCESS_DENIED_ACE_TYPE),
|
|
("D:(OA;;;;00000042-0043-0044-0045-000000000000;S-1-0-0)",
|
|
gdef.ACCESS_ALLOWED_OBJECT_ACE_TYPE),
|
|
("D:(OD;;;;00000042-0043-0044-0045-000000000001;S-1-0-0)",
|
|
gdef.ACCESS_DENIED_OBJECT_ACE_TYPE),
|
|
("D:AI(XA;;GR;;;WD;(YOLO))", gdef.ACCESS_ALLOWED_CALLBACK_ACE_TYPE),
|
|
("D:AI(XD;;GR;;;WD;(YOLO))", gdef.ACCESS_DENIED_CALLBACK_ACE_TYPE),
|
|
|
|
("D:AI(ZA;;GR;;00000042-0043-0044-0045-000000000001;WD;(YOLO))", gdef.ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE),
|
|
# NO SDDL DEFINE FOR : gdef.ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE)
|
|
]
|
|
|
|
@pytest.mark.parametrize("sddl, ace_type", ALL_DACL_ACE_TYPES)
|
|
def test_ace_dacl_subclass(sddl, ace_type):
|
|
sd = SecurityDescriptor.from_string(sddl)
|
|
dacl = sd.dacl
|
|
assert len(dacl) == 1
|
|
ace = dacl[0] # Will raise if AceHeader is not handled
|
|
assert ace.Header.AceType == ace_type
|
|
|
|
# SACL STUFF
|
|
|
|
ALL_SACL_ACE_TYPES = [
|
|
("S:(AU;;;;;AN)", gdef.SYSTEM_AUDIT_ACE_TYPE),
|
|
("S:(ML;;;;;S-1-16-4000)", gdef.SYSTEM_MANDATORY_LABEL_ACE_TYPE),
|
|
# S-1-19-512-4096 what retrieved in a ACE from a directory in C:\Program Files\WindowsApps\
|
|
("S:(TL;;;;;S-1-19-512-4096)", gdef.SYSTEM_PROCESS_TRUST_LABEL_ACE_TYPE),
|
|
("S:(SP;;;;;S-1-17-1)", gdef.SYSTEM_SCOPED_POLICY_ID_ACE_TYPE),
|
|
("S:(OU;;;;00000042-0043-0044-0045-000000000000;AN)", gdef.SYSTEM_AUDIT_OBJECT_ACE_TYPE),
|
|
("S:(XU;;;;;S-1-2-3;(YOLO))", gdef.SYSTEM_AUDIT_CALLBACK_ACE_TYPE),
|
|
## Reserved for futur use (RFS): not handled by ADVAPI.dll
|
|
# ("S:(AL;;;;;S-1-2-3)", gdef.SYSTEM_ALARM_OBJECT_ACE_TYPE),
|
|
#("S:(OL;;;;00000042-0043-0044-0045-000000000000;AN)", gdef.SYSTEM_ALARM_OBJECT_ACE_TYPE),
|
|
## NO SDDL FOR:
|
|
# SYSTEM_ALARM_CALLBACK_ACE_TYPE
|
|
# SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE
|
|
# SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE
|
|
]
|
|
|
|
@pytest.mark.parametrize("sddl, ace_type", ALL_SACL_ACE_TYPES)
|
|
def test_ace_sacl_subclass(sddl, ace_type):
|
|
sd = SecurityDescriptor.from_string(sddl)
|
|
sacl = sd.sacl
|
|
assert len(sacl) == 1
|
|
ace = sacl[0] # Will raise if AceHeader is not handled
|
|
assert ace.Header.AceType == ace_type
|
|
|
|
RESOURCE_ATTRIBUTES_SDDLS = [
|
|
("""S:(RA;;;;;WD; ("TestName",TI,0,-2, -1, 0, 1, 2))""",
|
|
(-2, -1, 0, 1, 2 )),
|
|
|
|
("""S:(RA;;;;;WD; ("TestName",TU,0,3,4,42))""",
|
|
(3, 4, 42)),
|
|
|
|
("""S:(RA;;;;;WD; ("TestName",TS,0,"Windows","SQL", ""))""",
|
|
("Windows", "SQL", "")),
|
|
|
|
("""S:(RA;;;;;WD; ("TestName",TD,0, AN, S-1-2-3-4-5-6-7-8-9))""",
|
|
(gdef.PSID.from_string("S-1-5-7"),
|
|
gdef.PSID.from_string("S-1-2-3-4-5-6-7-8-9"))),
|
|
|
|
("""S:(RA;;;;;WD; ("TestName",TX,0, 42000042, 0123456789abcdef))""",
|
|
(b"B\x00\x00B", b"\x01\x23\x45\x67\x89\xab\xcd\xef")),
|
|
|
|
("""S:(RA;;;;;WD; ("TestName",TB,0, 0, 1, 0, 0, 1))""",
|
|
(False, True, False, False, True)),
|
|
]
|
|
|
|
@pytest.mark.parametrize("sddl, expected_values", RESOURCE_ATTRIBUTES_SDDLS)
|
|
def test_ace_resource_attribute(sddl, expected_values):
|
|
sd = SecurityDescriptor.from_string(sddl)
|
|
ra = sd.sacl[0]
|
|
assert ra.Header.AceType == gdef.SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE
|
|
attr = ra.attribute
|
|
assert attr.name == "TestName"
|
|
assert attr.values == expected_values
|
|
|
|
CONDITIONAL_SDDLS = [
|
|
("D:AI(XA;;GR;;;WD;(ATTR1))", b"ATTR1"),
|
|
("D:AI(XD;;GR;;;WD;(ATTR2))", b"ATTR2"),
|
|
("S:AI(XU;;GR;;;WD;(ATTR3))", b"ATTR3")
|
|
]
|
|
|
|
@pytest.mark.parametrize("sddl, expected_value", CONDITIONAL_SDDLS)
|
|
def test_conditional_ace_applicationdata(sddl, expected_value):
|
|
sd = SecurityDescriptor.from_string(sddl)
|
|
acl = sd.dacl
|
|
if acl is None:
|
|
acl = sd.sacl
|
|
ace = acl[0]
|
|
appdata = ace.application_data
|
|
# https://msdn.microsoft.com/en-us/library/hh877860.aspx
|
|
assert appdata.startswith(b"artx")
|
|
assert expected_value in appdata.replace(b"\x00", b"")
|
|
|
|
|
|
|