-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added more test coverage for LdapPropertyProcessor
- Loading branch information
Showing
1 changed file
with
258 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,13 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.ComponentModel; | ||
using System.DirectoryServices; | ||
using System.Security.Cryptography; | ||
using System.Security.Cryptography.X509Certificates; | ||
using System.Security.Principal; | ||
using System.Threading.Tasks; | ||
using CommonLibTest.Facades; | ||
using Moq; | ||
using SharpHoundCommonLib; | ||
using SharpHoundCommonLib.Enums; | ||
using SharpHoundCommonLib.OutputTypes; | ||
|
@@ -990,6 +993,41 @@ public void LDAPPropertyProcessor_ParseAllProperties_GUID() { | |
Assert.Equal(guidExpected.ToString(), guidActual); | ||
} | ||
|
||
[Fact] | ||
public void LDAPPropertyProcessor_ReadACAProperties() { | ||
var ecdsa = ECDsa.Create(); | ||
var req = new CertificateRequest("cn=foobar", ecdsa, HashAlgorithmName.SHA256); | ||
var cert = req.CreateSelfSigned(DateTimeOffset.Now, DateTimeOffset.Now.AddYears(5)); | ||
|
||
var bytes = cert.Export(X509ContentType.Cert, "abc"); | ||
var mock = new MockDirectoryObject( | ||
"CN\u003dDUMPSTER-DC01-CA,CN\u003dAIA,CN\u003dPUBLIC KEY SERVICES,CN\u003dSERVICES,CN\u003dCONFIGURATION,DC\u003dDUMPSTER,DC\u003dFIRE", | ||
new Dictionary<string, object> | ||
{ | ||
{"description", null}, | ||
{"domain", "DUMPSTER.FIRE"}, | ||
{"name", "[email protected]"}, | ||
{"domainsid", "S-1-5-21-2697957641-2271029196-387917394"}, | ||
{"whencreated", 1683986131}, | ||
{LDAPProperties.CACertificate, bytes} | ||
}, "","2F9F3630-F46A-49BF-B186-6629994EBCF9"); | ||
|
||
var test = LdapPropertyProcessor.ReadRootCAProperties(mock); | ||
var keys = test.Keys; | ||
|
||
//These are not common properties | ||
Assert.DoesNotContain("domain", keys); | ||
Assert.DoesNotContain("name", keys); | ||
Assert.DoesNotContain("domainsid", keys); | ||
|
||
Assert.Contains("whencreated", keys); | ||
Assert.Contains("certthumbprint", keys); | ||
Assert.Contains("certname", keys); | ||
Assert.Contains("certchain", keys); | ||
Assert.Contains("hasbasicconstraints", keys); | ||
Assert.Contains("basicconstraintpathlength", keys); | ||
} | ||
|
||
[Fact] | ||
public async void LDAPPropertyProcessor_ReadDomainProperties_TestExpirePassword() | ||
{ | ||
|
@@ -1167,6 +1205,33 @@ public async Task LDAPPropertyProcessor_ReadUserProperties_TestLastLogonNull() | |
|
||
} | ||
|
||
[Fact] | ||
public async void LDAPPropertyProcessor_ReadDomainProperties_ConvertNanoDuration_TestReadableString() | ||
{ | ||
var mock = new MockDirectoryObject("DC\u003dtestlab,DC\u003dlocal", new Dictionary<string, object> | ||
{ | ||
{LDAPProperties.MaxPwdAge, -11211100000000} | ||
}, "S-1-5-21-3130019616-2776909439-2417379446",""); | ||
|
||
var processor = new LdapPropertyProcessor(new MockLdapUtils()); | ||
var test = await processor.ReadDomainProperties(mock,"testlab.local"); | ||
Assert.Contains("maxpwdage", test.Keys); | ||
Assert.Equal("12 days, 23 hours, 25 minutes, 10 seconds", test["maxpwdage"] as string); | ||
} | ||
|
||
[Fact] | ||
public async void LDAPPropertyProcessor_ReadDomainProperties_ConvertNanoDuration_TestNull() | ||
{ | ||
var mock = new MockDirectoryObject("DC\u003dtestlab,DC\u003dlocal", new Dictionary<string, object> | ||
{ | ||
{LDAPProperties.MaxPwdAge, 100} | ||
}, "S-1-5-21-3130019616-2776909439-2417379446",""); | ||
|
||
var processor = new LdapPropertyProcessor(new MockLdapUtils()); | ||
var test = await processor.ReadDomainProperties(mock,"testlab.local"); | ||
Assert.DoesNotContain("maxpwdage", test.Keys); | ||
} | ||
|
||
[WindowsOnlyFact] | ||
public async Task LDAPPropertyProcessor_ReadUserProperties_TestLastLogonTimeStampNull() | ||
{ | ||
|
@@ -1358,6 +1423,12 @@ public async Task LDAPPropertyProcessor_ReadComputerProperties_TestDelegatesNull | |
[WindowsOnlyFact] | ||
public async Task LDAPPropertyProcessor_ReadComputerProperties_AllowedToActOnBehalfOfOtherIdentity() | ||
{ | ||
var mockUtils = new Mock<ILdapUtils>(); | ||
var mockSecurityDescriptor = new Mock<ActiveDirectorySecurityDescriptor>(MockBehavior.Loose, null); | ||
var mockRule = new Mock<ActiveDirectoryRuleDescriptor>(MockBehavior.Loose, null); | ||
var collection = new List<ActiveDirectoryRuleDescriptor>(); | ||
var expectedPrincipalSID = "S-1-5-21-3130019616-2776909439-2417379446-512"; | ||
var expectedPrincipalType = Label.CertTemplate; | ||
var mock = new MockDirectoryObject("CN\u003dWIN10,OU\u003dTestOU,DC\u003dtestlab,DC\u003dlocal", | ||
new Dictionary<string, object> | ||
{ | ||
|
@@ -1370,30 +1441,81 @@ public async Task LDAPPropertyProcessor_ReadComputerProperties_AllowedToActOnBeh | |
{"mail", "[email protected]"}, | ||
{"admincount", "c"}, | ||
{ | ||
"sidhistory", new[] | ||
{ | ||
"msds-allowedtoactonbehalfofotheridentity", | ||
|
||
Utils.B64ToBytes("AQUAAAAAAAUVAAAAIE+Qun9GhKV2SBaQUQQAAA==") | ||
} | ||
}, | ||
|
||
} | ||
}, "S-1-5-21-3130019616-2776909439-2417379446-1101",""); | ||
|
||
var sd = new ActiveDirectorySecurityDescriptor(new ActiveDirectorySecurity()); | ||
mockUtils.Setup(x => x.MakeSecurityDescriptor()).Returns(sd); | ||
mockSecurityDescriptor.Setup(m => m.SetSecurityDescriptorBinaryForm(It.IsAny<byte[]>())).Throws(new OverflowException()); | ||
mockUtils.Setup(x => x.MakeSecurityDescriptor()).Returns(mockSecurityDescriptor.Object); | ||
collection.Add(mockRule.Object); | ||
mockSecurityDescriptor.Setup(m => m.GetAccessRules(It.IsAny<bool>(), It.IsAny<bool>(), It.IsAny<Type>())) | ||
.Returns(collection); | ||
mockUtils.Setup(x => x.ResolveIDAndType(It.IsAny<string>(), It.IsAny<string>())) | ||
.ReturnsAsync((true, new TypedPrincipal(expectedPrincipalSID, expectedPrincipalType))); | ||
|
||
|
||
var processor = new LdapPropertyProcessor(mockUtils.Object); | ||
var test = await processor.ReadComputerProperties(mock, "testlab.local"); | ||
|
||
//AllowedToAct | ||
Assert.Single(test.AllowedToAct); | ||
Assert.Contains(new TypedPrincipal | ||
{ | ||
ObjectIdentifier = expectedPrincipalSID, | ||
ObjectType = expectedPrincipalType | ||
}, test.AllowedToAct); | ||
} | ||
|
||
[WindowsOnlyFact] | ||
public async Task LDAPPropertyProcessor_ConvertEncryptionTypes_SupportedEncrypTionTypes_0() | ||
{ | ||
var mock = new MockDirectoryObject("CN\u003dWIN10,OU\u003dTestOU,DC\u003dtestlab,DC\u003dlocal", | ||
new Dictionary<string, object> | ||
{ | ||
{"description", "Test"}, | ||
{"useraccountcontrol", 0x1001000.ToString()}, | ||
{"lastlogon", "132673011142753043"}, | ||
{"lastlogontimestamp", "132670318095676525"}, | ||
{"operatingsystem", "Windows 10 Enterprise"}, | ||
{"operatingsystemservicepack", "1607"}, | ||
{"mail", "[email protected]"}, | ||
{"admincount", "c"}, | ||
{ | ||
"msds-allowedtodelegateto", new[] | ||
{ | ||
"ldap/PRIMARY.testlab.local/testlab.local", | ||
"ldap/PRIMARY.testlab.local", | ||
"ldap/PRIMARY" | ||
} | ||
}, | ||
{"pwdlastset", "132131667346106691"}, | ||
"msds-supportedencryptiontypes", "0" | ||
} | ||
}, "S-1-5-21-3130019616-2776909439-2417379446-1101",""); | ||
|
||
var processor = new LdapPropertyProcessor(new MockLdapUtils()); | ||
var test = await processor.ReadComputerProperties(mock, "testlab.local"); | ||
var props = test.Props; | ||
var keys = props.Keys; | ||
|
||
Assert.Contains("supportedencryptiontypes", keys); | ||
|
||
Assert.Equal(new List<String>(["Not defined"]), (List<String>)props["supportedencryptiontypes"]); | ||
} | ||
|
||
[WindowsOnlyFact] | ||
public async Task LDAPPropertyProcessor_ReadComputerProperties_ConvertEncryptionTypes_DES_CBC_CRC() | ||
{ | ||
var mock = new MockDirectoryObject("CN\u003dWIN10,OU\u003dTestOU,DC\u003dtestlab,DC\u003dlocal", | ||
new Dictionary<string, object> | ||
{ | ||
{"description", "Test"}, | ||
{"useraccountcontrol", 0x1001000.ToString()}, | ||
{"lastlogon", "132673011142753043"}, | ||
{"lastlogontimestamp", "132670318095676525"}, | ||
{"operatingsystem", "Windows 10 Enterprise"}, | ||
{"operatingsystemservicepack", "1607"}, | ||
{"mail", "[email protected]"}, | ||
{"admincount", "c"}, | ||
{ | ||
"serviceprincipalname", new[] | ||
{ | ||
"WSMAN/WIN10", | ||
"WSMAN/WIN10.testlab.local", | ||
"RestrictedKrbHost/WIN10", | ||
"HOST/WIN10", | ||
"RestrictedKrbHost/WIN10.testlab.local", | ||
"HOST/WIN10.testlab.local" | ||
} | ||
"msds-supportedencryptiontypes", "1" | ||
} | ||
}, "S-1-5-21-3130019616-2776909439-2417379446-1101",""); | ||
|
||
|
@@ -1402,55 +1524,125 @@ public async Task LDAPPropertyProcessor_ReadComputerProperties_AllowedToActOnBeh | |
var props = test.Props; | ||
var keys = props.Keys; | ||
|
||
//UAC | ||
Assert.Contains("enabled", keys); | ||
Assert.Contains("unconstraineddelegation", keys); | ||
Assert.Contains("trustedtoauth", keys); | ||
Assert.Contains("isdc", keys); | ||
Assert.Contains("lastlogon", keys); | ||
Assert.Contains("lastlogontimestamp", keys); | ||
Assert.Contains("pwdlastset", keys); | ||
Assert.True((bool)props["enabled"]); | ||
Assert.False((bool)props["unconstraineddelegation"]); | ||
Assert.True((bool)props["trustedtoauth"]); | ||
Assert.False((bool)props["isdc"]); | ||
Assert.Contains("supportedencryptiontypes", keys); | ||
|
||
Assert.Contains("lastlogon", keys); | ||
Assert.Equal(1622827514, (long)props["lastlogon"]); | ||
Assert.Contains("lastlogontimestamp", keys); | ||
Assert.Equal(1622558209, (long)props["lastlogontimestamp"]); | ||
Assert.Contains("pwdlastset", keys); | ||
Assert.Equal(1568693134, (long)props["pwdlastset"]); | ||
Assert.Equal(new List<String>(["DES-CBC-CRC"]), (List<String>)props["supportedencryptiontypes"]); | ||
} | ||
|
||
[WindowsOnlyFact] | ||
public async Task LDAPPropertyProcessor_ReadComputerProperties_ConvertEncryptionTypes_DES_CBC_MD5() | ||
{ | ||
var mock = new MockDirectoryObject("CN\u003dWIN10,OU\u003dTestOU,DC\u003dtestlab,DC\u003dlocal", | ||
new Dictionary<string, object> | ||
{ | ||
{"description", "Test"}, | ||
{"useraccountcontrol", 0x1001000.ToString()}, | ||
{"lastlogon", "132673011142753043"}, | ||
{"lastlogontimestamp", "132670318095676525"}, | ||
{"operatingsystem", "Windows 10 Enterprise"}, | ||
{"operatingsystemservicepack", "1607"}, | ||
{"mail", "[email protected]"}, | ||
{"admincount", "c"}, | ||
{ | ||
"msds-supportedencryptiontypes", "2" | ||
} | ||
}, "S-1-5-21-3130019616-2776909439-2417379446-1101",""); | ||
|
||
//AllowedToDelegate | ||
Assert.Single(test.AllowedToDelegate); | ||
Assert.Contains(new TypedPrincipal | ||
{ | ||
ObjectIdentifier = "S-1-5-21-3130019616-2776909439-2417379446-1001", | ||
ObjectType = Label.Computer | ||
}, test.AllowedToDelegate); | ||
var processor = new LdapPropertyProcessor(new MockLdapUtils()); | ||
var test = await processor.ReadComputerProperties(mock, "testlab.local"); | ||
var props = test.Props; | ||
var keys = props.Keys; | ||
|
||
//Other Stuff | ||
Assert.Contains("serviceprincipalnames", keys); | ||
Assert.Equal(6, (props["serviceprincipalnames"] as string[]).Length); | ||
Assert.Contains("operatingsystem", keys); | ||
Assert.Equal("Windows 10 Enterprise 1607", props["operatingsystem"] as string); | ||
Assert.Contains("description", keys); | ||
Assert.Equal("Test", props["description"] as string); | ||
Assert.Contains("email", keys); | ||
Assert.Equal("[email protected]", props["email"] as string); | ||
Assert.Contains("supportedencryptiontypes", keys); | ||
|
||
//SidHistory | ||
Assert.Contains("sidhistory", keys); | ||
var sh = props["sidhistory"] as string[]; | ||
Assert.Single(sh); | ||
Assert.Contains("S-1-5-21-3130019616-2776909439-2417379446-1105", sh); | ||
Assert.Single(test.SidHistory); | ||
Assert.Contains(new TypedPrincipal | ||
{ | ||
ObjectIdentifier = "S-1-5-21-3130019616-2776909439-2417379446-1105", | ||
ObjectType = Label.User | ||
}, test.SidHistory); | ||
Assert.Equal(new List<String>(["DES-CBC-MD5"]), (List<String>)props["supportedencryptiontypes"]); | ||
} | ||
|
||
[WindowsOnlyFact] | ||
public async Task LDAPPropertyProcessor_ReadComputerProperties_ConvertEncryptionTypes_RC4_HMAC_MD5() | ||
{ | ||
var mock = new MockDirectoryObject("CN\u003dWIN10,OU\u003dTestOU,DC\u003dtestlab,DC\u003dlocal", | ||
new Dictionary<string, object> | ||
{ | ||
{"description", "Test"}, | ||
{"useraccountcontrol", 0x1001000.ToString()}, | ||
{"lastlogon", "132673011142753043"}, | ||
{"lastlogontimestamp", "132670318095676525"}, | ||
{"operatingsystem", "Windows 10 Enterprise"}, | ||
{"operatingsystemservicepack", "1607"}, | ||
{"mail", "[email protected]"}, | ||
{"admincount", "c"}, | ||
{ | ||
"msds-supportedencryptiontypes", "4" | ||
} | ||
}, "S-1-5-21-3130019616-2776909439-2417379446-1101",""); | ||
|
||
var processor = new LdapPropertyProcessor(new MockLdapUtils()); | ||
var test = await processor.ReadComputerProperties(mock, "testlab.local"); | ||
var props = test.Props; | ||
var keys = props.Keys; | ||
|
||
Assert.Contains("supportedencryptiontypes", keys); | ||
|
||
Assert.Equal(new List<String>(["RC4-HMAC-MD5"]), (List<String>)props["supportedencryptiontypes"]); | ||
} | ||
|
||
[WindowsOnlyFact] | ||
public async Task LDAPPropertyProcessor_ReadComputerProperties_ConvertEncryptionTypes_AES128_CTS_HMAC_SHA1_96() | ||
{ | ||
var mock = new MockDirectoryObject("CN\u003dWIN10,OU\u003dTestOU,DC\u003dtestlab,DC\u003dlocal", | ||
new Dictionary<string, object> | ||
{ | ||
{"description", "Test"}, | ||
{"useraccountcontrol", 0x1001000.ToString()}, | ||
{"lastlogon", "132673011142753043"}, | ||
{"lastlogontimestamp", "132670318095676525"}, | ||
{"operatingsystem", "Windows 10 Enterprise"}, | ||
{"operatingsystemservicepack", "1607"}, | ||
{"mail", "[email protected]"}, | ||
{"admincount", "c"}, | ||
{ | ||
"msds-supportedencryptiontypes", "8" | ||
} | ||
}, "S-1-5-21-3130019616-2776909439-2417379446-1101",""); | ||
|
||
var processor = new LdapPropertyProcessor(new MockLdapUtils()); | ||
var test = await processor.ReadComputerProperties(mock, "testlab.local"); | ||
var props = test.Props; | ||
var keys = props.Keys; | ||
|
||
Assert.Contains("supportedencryptiontypes", keys); | ||
|
||
Assert.Equal(new List<String>(["AES128-CTS-HMAC-SHA1-96"]), (List<String>)props["supportedencryptiontypes"]); | ||
} | ||
|
||
[WindowsOnlyFact] | ||
public async Task LDAPPropertyProcessor_ReadComputerProperties_ConvertEncryptionTypes_AES256_CTS_HMAC_SHA1_96() | ||
{ | ||
var mock = new MockDirectoryObject("CN\u003dWIN10,OU\u003dTestOU,DC\u003dtestlab,DC\u003dlocal", | ||
new Dictionary<string, object> | ||
{ | ||
{"description", "Test"}, | ||
{"useraccountcontrol", 0x1001000.ToString()}, | ||
{"lastlogon", "132673011142753043"}, | ||
{"lastlogontimestamp", "132670318095676525"}, | ||
{"operatingsystem", "Windows 10 Enterprise"}, | ||
{"operatingsystemservicepack", "1607"}, | ||
{"mail", "[email protected]"}, | ||
{"admincount", "c"}, | ||
{ | ||
"msds-supportedencryptiontypes", "16" | ||
} | ||
}, "S-1-5-21-3130019616-2776909439-2417379446-1101",""); | ||
|
||
var processor = new LdapPropertyProcessor(new MockLdapUtils()); | ||
var test = await processor.ReadComputerProperties(mock, "testlab.local"); | ||
var props = test.Props; | ||
var keys = props.Keys; | ||
|
||
Assert.Contains("supportedencryptiontypes", keys); | ||
|
||
Assert.Equal(new List<String>(["AES256-CTS-HMAC-SHA1-96"]), (List<String>)props["supportedencryptiontypes"]); | ||
} | ||
} | ||
} |