Skip to content

Commit 40db054

Browse files
JonasBKrvazarkar
andauthored
ACL objecttype tests (#195)
Co-authored-by: Rohan Vazarkar <rvazarkar@users.noreply.github.com>
1 parent 3220ed5 commit 40db054

2 files changed

Lines changed: 179 additions & 0 deletions

File tree

src/CommonLib/Processors/ACEGuids.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public class ACEGuids
1313
public const string AddKeyPrincipal = "5b47d60f-6090-40b2-9f37-2a4de88f3063";
1414
public const string UserAccountRestrictions = "4c164200-20c0-11d0-a768-00aa006e0529";
1515
public const string WriteGPLink = "f30e3bbe-9ff0-11d1-b603-0000f80367c1";
16+
public const string WriteTitle = "bf967a55-0de6-11d0-a285-00aa003049e2"; // Not an edge, just used for testing
1617

1718

1819
//Cert abuse ACEs

test/unit/ACLProcessorTest.cs

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,116 @@ public async Task ACLProcessor_ProcessACL_GenericAll() {
440440
Assert.Equal(actual.RightName, EdgeNames.GenericAll);
441441
}
442442

443+
[Fact]
444+
public async Task ACLProcessor_ProcessACL_GenericAll_WriteSPN() {
445+
var expectedPrincipalType = Label.Group;
446+
var expectedPrincipalSID = "S-1-5-21-3130019616-2776909439-2417379446-512";
447+
448+
var mockLDAPUtils = new Mock<ILdapUtils>();
449+
var mockSecurityDescriptor = new Mock<ActiveDirectorySecurityDescriptor>(MockBehavior.Loose, null);
450+
var mockRule = new Mock<ActiveDirectoryRuleDescriptor>(MockBehavior.Loose, null);
451+
var collection = new List<ActiveDirectoryRuleDescriptor>();
452+
mockRule.Setup(x => x.AccessControlType()).Returns(AccessControlType.Allow);
453+
mockRule.Setup(x => x.IsAceInheritedFrom(It.IsAny<string>())).Returns(true);
454+
mockRule.Setup(x => x.IdentityReference()).Returns(expectedPrincipalSID);
455+
mockRule.Setup(x => x.ActiveDirectoryRights()).Returns(ActiveDirectoryRights.GenericAll);
456+
mockRule.Setup(x => x.ObjectType()).Returns(new Guid(ACEGuids.WriteSPN));
457+
collection.Add(mockRule.Object);
458+
459+
mockSecurityDescriptor.Setup(m => m.GetAccessRules(It.IsAny<bool>(), It.IsAny<bool>(), It.IsAny<Type>()))
460+
.Returns(collection);
461+
mockSecurityDescriptor.Setup(m => m.GetOwner(It.IsAny<Type>())).Returns((string)null);
462+
mockLDAPUtils.Setup(x => x.MakeSecurityDescriptor()).Returns(mockSecurityDescriptor.Object);
463+
mockLDAPUtils.Setup(x => x.ResolveIDAndType(It.IsAny<string>(), It.IsAny<string>()))
464+
.ReturnsAsync((true, new TypedPrincipal(expectedPrincipalSID, expectedPrincipalType)));
465+
var mockData = new[] { LdapResult<IDirectoryObject>.Fail() };
466+
mockLDAPUtils.Setup(x => x.PagedQuery(It.IsAny<LdapQueryParameters>(), It.IsAny<CancellationToken>()))
467+
.Returns(mockData.ToAsyncEnumerable());
468+
469+
var processor = new ACLProcessor(mockLDAPUtils.Object);
470+
var bytes = Utils.B64ToBytes(UnProtectedUserNtSecurityDescriptor);
471+
var result = await processor.ProcessACL(bytes, _testDomainName, Label.User, false).ToArrayAsync();
472+
473+
Assert.Single(result);
474+
var actual = result.First();
475+
Assert.Equal(actual.PrincipalType, expectedPrincipalType);
476+
Assert.Equal(actual.PrincipalSID, expectedPrincipalSID);
477+
Assert.False(actual.IsInherited);
478+
Assert.Equal(actual.RightName, EdgeNames.WriteSPN);
479+
}
480+
481+
[Fact]
482+
public async Task ACLProcessor_ProcessACL_GenericAll_ForceChangePassword() {
483+
var expectedPrincipalType = Label.Group;
484+
var expectedPrincipalSID = "S-1-5-21-3130019616-2776909439-2417379446-512";
485+
486+
var mockLDAPUtils = new Mock<ILdapUtils>();
487+
var mockSecurityDescriptor = new Mock<ActiveDirectorySecurityDescriptor>(MockBehavior.Loose, null);
488+
var mockRule = new Mock<ActiveDirectoryRuleDescriptor>(MockBehavior.Loose, null);
489+
var collection = new List<ActiveDirectoryRuleDescriptor>();
490+
mockRule.Setup(x => x.AccessControlType()).Returns(AccessControlType.Allow);
491+
mockRule.Setup(x => x.IsAceInheritedFrom(It.IsAny<string>())).Returns(true);
492+
mockRule.Setup(x => x.IdentityReference()).Returns(expectedPrincipalSID);
493+
mockRule.Setup(x => x.ActiveDirectoryRights()).Returns(ActiveDirectoryRights.GenericAll);
494+
mockRule.Setup(x => x.ObjectType()).Returns(new Guid(ACEGuids.UserForceChangePassword));
495+
collection.Add(mockRule.Object);
496+
497+
mockSecurityDescriptor.Setup(m => m.GetAccessRules(It.IsAny<bool>(), It.IsAny<bool>(), It.IsAny<Type>()))
498+
.Returns(collection);
499+
mockSecurityDescriptor.Setup(m => m.GetOwner(It.IsAny<Type>())).Returns((string)null);
500+
mockLDAPUtils.Setup(x => x.MakeSecurityDescriptor()).Returns(mockSecurityDescriptor.Object);
501+
mockLDAPUtils.Setup(x => x.ResolveIDAndType(It.IsAny<string>(), It.IsAny<string>()))
502+
.ReturnsAsync((true, new TypedPrincipal(expectedPrincipalSID, expectedPrincipalType)));
503+
var mockData = new[] { LdapResult<IDirectoryObject>.Fail() };
504+
mockLDAPUtils.Setup(x => x.PagedQuery(It.IsAny<LdapQueryParameters>(), It.IsAny<CancellationToken>()))
505+
.Returns(mockData.ToAsyncEnumerable());
506+
507+
var processor = new ACLProcessor(mockLDAPUtils.Object);
508+
var bytes = Utils.B64ToBytes(UnProtectedUserNtSecurityDescriptor);
509+
var result = await processor.ProcessACL(bytes, _testDomainName, Label.User, false).ToArrayAsync();
510+
511+
Assert.Single(result);
512+
var actual = result.First();
513+
Assert.Equal(actual.PrincipalType, expectedPrincipalType);
514+
Assert.Equal(actual.PrincipalSID, expectedPrincipalSID);
515+
Assert.False(actual.IsInherited);
516+
Assert.Equal(actual.RightName, EdgeNames.ForceChangePassword);
517+
}
518+
519+
[Fact]
520+
public async Task ACLProcessor_ProcessACL_GenericAll_WrongOjectType() {
521+
var expectedPrincipalType = Label.Group;
522+
var expectedPrincipalSID = "S-1-5-21-3130019616-2776909439-2417379446-512";
523+
var expectedRightName = ActiveDirectoryRights.GenericAll;
524+
525+
var mockLDAPUtils = new Mock<ILdapUtils>();
526+
var mockSecurityDescriptor = new Mock<ActiveDirectorySecurityDescriptor>(MockBehavior.Loose, null);
527+
var mockRule = new Mock<ActiveDirectoryRuleDescriptor>(MockBehavior.Loose, null);
528+
var collection = new List<ActiveDirectoryRuleDescriptor>();
529+
mockRule.Setup(x => x.AccessControlType()).Returns(AccessControlType.Allow);
530+
mockRule.Setup(x => x.IsAceInheritedFrom(It.IsAny<string>())).Returns(true);
531+
mockRule.Setup(x => x.IdentityReference()).Returns(expectedPrincipalSID);
532+
mockRule.Setup(x => x.ActiveDirectoryRights()).Returns(expectedRightName);
533+
mockRule.Setup(x => x.ObjectType()).Returns(new Guid(ACEGuids.WriteTitle));
534+
collection.Add(mockRule.Object);
535+
536+
mockSecurityDescriptor.Setup(m => m.GetAccessRules(It.IsAny<bool>(), It.IsAny<bool>(), It.IsAny<Type>()))
537+
.Returns(collection);
538+
mockSecurityDescriptor.Setup(m => m.GetOwner(It.IsAny<Type>())).Returns((string)null);
539+
mockLDAPUtils.Setup(x => x.MakeSecurityDescriptor()).Returns(mockSecurityDescriptor.Object);
540+
mockLDAPUtils.Setup(x => x.ResolveIDAndType(It.IsAny<string>(), It.IsAny<string>()))
541+
.ReturnsAsync((true, new TypedPrincipal(expectedPrincipalSID, expectedPrincipalType)));
542+
var mockData = new[] { LdapResult<IDirectoryObject>.Fail() };
543+
mockLDAPUtils.Setup(x => x.PagedQuery(It.IsAny<LdapQueryParameters>(), It.IsAny<CancellationToken>()))
544+
.Returns(mockData.ToAsyncEnumerable());
545+
546+
var processor = new ACLProcessor(mockLDAPUtils.Object);
547+
var bytes = Utils.B64ToBytes(UnProtectedUserNtSecurityDescriptor);
548+
var result = await processor.ProcessACL(bytes, _testDomainName, Label.User, false).ToArrayAsync();
549+
550+
Assert.Empty(result);
551+
}
552+
443553
[Fact]
444554
public async Task ACLProcessor_ProcessACL_WriteDacl() {
445555
var expectedPrincipalType = Label.Group;
@@ -479,6 +589,40 @@ public async Task ACLProcessor_ProcessACL_WriteDacl() {
479589
Assert.Equal(actual.RightName, expectedRightName.ToString());
480590
}
481591

592+
[Fact]
593+
public async Task ACLProcessor_ProcessACL_WriteDacl_WrongOjectType() {
594+
var expectedPrincipalType = Label.Group;
595+
var expectedPrincipalSID = "S-1-5-21-3130019616-2776909439-2417379446-512";
596+
var expectedRightName = ActiveDirectoryRights.WriteDacl;
597+
598+
var mockLDAPUtils = new Mock<ILdapUtils>();
599+
var mockSecurityDescriptor = new Mock<ActiveDirectorySecurityDescriptor>(MockBehavior.Loose, null);
600+
var mockRule = new Mock<ActiveDirectoryRuleDescriptor>(MockBehavior.Loose, null);
601+
var collection = new List<ActiveDirectoryRuleDescriptor>();
602+
mockRule.Setup(x => x.AccessControlType()).Returns(AccessControlType.Allow);
603+
mockRule.Setup(x => x.IsAceInheritedFrom(It.IsAny<string>())).Returns(true);
604+
mockRule.Setup(x => x.IdentityReference()).Returns(expectedPrincipalSID);
605+
mockRule.Setup(x => x.ActiveDirectoryRights()).Returns(expectedRightName);
606+
mockRule.Setup(x => x.ObjectType()).Returns(new Guid(ACEGuids.WriteSPN));
607+
collection.Add(mockRule.Object);
608+
609+
mockSecurityDescriptor.Setup(m => m.GetAccessRules(It.IsAny<bool>(), It.IsAny<bool>(), It.IsAny<Type>()))
610+
.Returns(collection);
611+
mockSecurityDescriptor.Setup(m => m.GetOwner(It.IsAny<Type>())).Returns((string)null);
612+
mockLDAPUtils.Setup(x => x.MakeSecurityDescriptor()).Returns(mockSecurityDescriptor.Object);
613+
mockLDAPUtils.Setup(x => x.ResolveIDAndType(It.IsAny<string>(), It.IsAny<string>()))
614+
.ReturnsAsync((true, new TypedPrincipal(expectedPrincipalSID, expectedPrincipalType)));
615+
var mockData = new[] { LdapResult<IDirectoryObject>.Fail() };
616+
mockLDAPUtils.Setup(x => x.PagedQuery(It.IsAny<LdapQueryParameters>(), It.IsAny<CancellationToken>()))
617+
.Returns(mockData.ToAsyncEnumerable());
618+
619+
var processor = new ACLProcessor(mockLDAPUtils.Object);
620+
var bytes = Utils.B64ToBytes(UnProtectedUserNtSecurityDescriptor);
621+
var result = await processor.ProcessACL(bytes, _testDomainName, Label.User, false).ToArrayAsync();
622+
623+
Assert.Empty(result);
624+
}
625+
482626
[Fact]
483627
public async Task ACLProcessor_ProcessACL_WriteOwner() {
484628
var expectedPrincipalType = Label.Group;
@@ -518,6 +662,40 @@ public async Task ACLProcessor_ProcessACL_WriteOwner() {
518662
Assert.Equal(actual.RightName, expectedRightName.ToString());
519663
}
520664

665+
[Fact]
666+
public async Task ACLProcessor_ProcessACL_WriteOwner_WrongOjectType() {
667+
var expectedPrincipalType = Label.Group;
668+
var expectedPrincipalSID = "S-1-5-21-3130019616-2776909439-2417379446-512";
669+
var expectedRightName = ActiveDirectoryRights.WriteOwner;
670+
671+
var mockLDAPUtils = new Mock<ILdapUtils>();
672+
var mockSecurityDescriptor = new Mock<ActiveDirectorySecurityDescriptor>(MockBehavior.Loose, null);
673+
var mockRule = new Mock<ActiveDirectoryRuleDescriptor>(MockBehavior.Loose, null);
674+
var collection = new List<ActiveDirectoryRuleDescriptor>();
675+
mockRule.Setup(x => x.AccessControlType()).Returns(AccessControlType.Allow);
676+
mockRule.Setup(x => x.IsAceInheritedFrom(It.IsAny<string>())).Returns(true);
677+
mockRule.Setup(x => x.IdentityReference()).Returns(expectedPrincipalSID);
678+
mockRule.Setup(x => x.ActiveDirectoryRights()).Returns(expectedRightName);
679+
mockRule.Setup(x => x.ObjectType()).Returns(new Guid(ACEGuids.WriteSPN));
680+
collection.Add(mockRule.Object);
681+
682+
mockSecurityDescriptor.Setup(m => m.GetAccessRules(It.IsAny<bool>(), It.IsAny<bool>(), It.IsAny<Type>()))
683+
.Returns(collection);
684+
mockSecurityDescriptor.Setup(m => m.GetOwner(It.IsAny<Type>())).Returns((string)null);
685+
mockLDAPUtils.Setup(x => x.MakeSecurityDescriptor()).Returns(mockSecurityDescriptor.Object);
686+
mockLDAPUtils.Setup(x => x.ResolveIDAndType(It.IsAny<string>(), It.IsAny<string>()))
687+
.ReturnsAsync((true, new TypedPrincipal(expectedPrincipalSID, expectedPrincipalType)));
688+
var mockData = new[] { LdapResult<IDirectoryObject>.Fail() };
689+
mockLDAPUtils.Setup(x => x.PagedQuery(It.IsAny<LdapQueryParameters>(), It.IsAny<CancellationToken>()))
690+
.Returns(mockData.ToAsyncEnumerable());
691+
692+
var processor = new ACLProcessor(mockLDAPUtils.Object);
693+
var bytes = Utils.B64ToBytes(UnProtectedUserNtSecurityDescriptor);
694+
var result = await processor.ProcessACL(bytes, _testDomainName, Label.User, false).ToArrayAsync();
695+
696+
Assert.Empty(result);
697+
}
698+
521699
[Fact]
522700
public async Task ACLProcessor_ProcessACL_Self() {
523701
var expectedPrincipalType = Label.Group;

0 commit comments

Comments
 (0)