[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fTXInCXKqEH7FSpZtEsn8DF96r8dEQ6Qu-AdX8C2T4wM":3},{"id":4,"question":5,"answer":6,"answerHtml":7,"slug":8,"keywords":9,"article":10,"status":34,"aiModel":39,"aiConfidence":39,"updatedAt":51,"createdAt":51,"_status":50},414,"What is the difference between brute-forcing domain passwords inside vs. outside the domain, and what tools are used?","Inside the domain, you can use `DomainPasswordSpray` to perform LDAP queries via ADSI, which also allows retrieving the password policy. Outside the domain, you can use `ldapsearch` on Kali with a bash loop like `for i in $(cat test.txt); do ldapsearch ...`, or a modified version of `DomainPasswordSpray` that uses an LDAP path (e.g., `LDAP:\u002F\u002F192.168.1.1\u002FDC=test,DC=com`) instead of domain context. The article [Penetration Basics - Brute-Forcing Domain User Passwords via LDAP Protocol](\u002Fnews\u002Fpenetration-basics-brute-forcing-domain-user-passwords-via-ldap-protocol) provides detailed examples.","\u003Cp>Inside the domain, you can use `DomainPasswordSpray` to perform LDAP queries via ADSI, which also allows retrieving the password policy. Outside the domain, you can use `ldapsearch` on Kali with a bash loop like `for i in $(cat test.txt); do ldapsearch ...`, or a modified version of `DomainPasswordSpray` that uses an LDAP path (e.g., `LDAP:\u002F\u002F192.168.1.1\u002FDC=test,DC=com`) instead of domain context. The article [Penetration Basics - Brute-Forcing Domain User Passwords via LDAP Protocol](\u002Fnews\u002Fpenetration-basics-brute-forcing-domain-user-passwords-via-ldap-protocol) provides detailed examples.\u003C\u002Fp>\u003Cp>\u003Ca href=\"\u002Fnews\u002Fpenetration-basics-brute-forcing-domain-user-passwords-via-ldap-protocol\">Read the related One Day Sec article\u003C\u002Fa>\u003C\u002Fp>","what-is-the-difference-between-brute-forcing-domain-passwords-inside-vs-outside--1777483879468","DomainPasswordSpray, ldapsearch, ADSI, outside domain, brute-force",{"id":11,"title":12,"slug":13,"description":14,"content":15,"contentHtml":30,"cover":31,"author":32,"views":19,"readingTime":33,"status":34,"publishedAt":35,"seo":36,"tags":41,"qaPairs":42,"meta":47,"updatedAt":48,"createdAt":49,"_status":50},104,"Penetration Basics - Brute-Forcing Domain User Passwords via LDAP Protocol","penetration-basics-brute-forcing-domain-user-passwords-via-ldap-protocol","Learn methods for brute-forcing domain user passwords via LDAP, including attack techniques, password spraying, and detection strategies to secure Active Directory.",{"root":16},{"type":17,"format":18,"indent":19,"version":20,"children":21,"direction":29},"root","",0,1,[22],{"type":23,"format":18,"indent":19,"version":20,"children":24,"direction":29},"paragraph",[25],{"mode":26,"text":27,"type":28,"style":18,"detail":19,"format":19,"version":20},"normal","\u003Chtml>\u003Chead>\u003C\u002Fhead>\u003Cbody>\u003Ch2>0x00 Introduction\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>In domain penetration, if some domain user passwords have been obtained, the common approach is to identify password patterns, generate dictionary files, and attempt brute-force attacks on other domain user passwords.\u003C\u002Fp>\u003Cp>From a defensive perspective, it is necessary to ensure that domain users do not use weak passwords with identifiable patterns and to detect brute-force attempts against domain user passwords.\u003C\u002Fp>\u003Cp>This article will introduce common methods for brute-forcing domain user passwords both inside and outside the domain, along with attack methodologies and detection techniques.\u003C\u002Fp>\u003Ch2>0x01 Overview\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article will cover the following topics:\u003C\u002Fp>\u003Cul>\u003Cli>Methods for brute-forcing domain user passwords within the domain\u003C\u002Fli>\u003Cli>Methods for brute-forcing domain user passwords from outside the domain\u003C\u002Fli>\u003Cli>Detection methods\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>0x02 Considerations for Brute-Forcing Domain User Passwords\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Multiple incorrect password attempts will result in user account lockout, with the default threshold set to 5 attempts\u003C\u002Fp>\u003Cp>After a user account is locked, it typically requires a 30-minute waiting period by default before it can be used again.\u003C\u002Fp>\u003Cp>The time of the last incorrect password entry is recorded and cannot be cleared by modifying LDAP data, with the following prompt:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Error 0x209A Access to the attribute is not permitted because the attribute is owned by the Security Accounts Manager (SAM).\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>After a user account is locked, even if the correct password is entered, a password error prompt will still appear.\u003C\u002Fp>\u003Ch2>0x03 Methods for brute-forcing domain user passwords within the domain.\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>1. Obtain the password policy for users within the domain to avoid account lockouts.\u003C\u002Fh3>\u003Cp>For detailed methods on obtaining password policies, refer to the previous article 'Penetration Basics - Obtaining Domain User Password Policies'.\u003C\u002Fp>\u003Ch3>2. Obtain a list of all domain users.\u003C\u002Fh3>\u003Cp>For detailed methods on obtaining this, refer to the earlier article 'Penetration Basics - Obtaining Active Directory Information'.\u003C\u002Fp>\u003Cp>Here, additional judgment on user attributes is required to filter out disabled and locked users.\u003C\u002Fp>\u003Ch4>(1) Identifying disabled users.\u003C\u002Fh4>\u003Cp>The flag indicating whether a user is disabled is located in the userAccountControl attribute, specifically at position 0x0002.\u003C\u002Fp>\u003Cp>As shown in the figure below.\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770017374896_0_d02ce7fd68.jpeg\">\u003C\u002Fp>\u003Cp>References:\u003C\u002Fp>\u003Cp>https:\u002F\u002Fsupport.microsoft.com\u002Fen-us\u002Fhelp\u002F305144\u002Fhow-to-use-useraccountcontrol-to-manipulate-user-account-properties\u003C\u002Fp>\u003Cp>Use PowerView to view the ACCOUNTDISABLE attribute for all users with the following command:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Get-NetUser | select name,useraccountcontrol\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The output is as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770017395828_1_16b15a0508.jpeg\">\u003C\u002Fp>\u003Cp>To view the specific value of the ACCOUNTDISABLE attribute for a specified user, use the following command:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Get-NetUser test2| select useraccountcontrol | ConvertFrom-UACValue -ShowAll\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The output is as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770017440553_2_b7a5c97b30.jpeg\">\u003C\u002Fp>\u003Cp>It can be determined that user test2 has the following attributes:\u003C\u002Fp>\u003Cul>\u003Cli>ACCOUNTDISABLE\u003C\u002Fli>\u003Cli>NORMAL_ACCOUNT\u003C\u002Fli>\u003Cli>DONT_EXPIRE_PASSWORD\u003C\u002Fli>\u003C\u002Ful>\u003Ch4>(2) Identify locked users\u003C\u002Fh4>\u003Cp>Although the user's ACCOUNTDISABLE attribute is marked as LOCKOUT at offset 0x0010, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770017466661_3_ec0e676913.jpeg\">\u003C\u002Fp>\u003Cp>However, the value at this location cannot be used to determine whether the current user is locked out\u003C\u002Fp>\u003Cp>We can determine by reading the user's badPwdCount attribute and lockoutTime attribute\u003C\u002Fp>\u003Cp>Use PowerView to view the badPwdCount and lockoutTime attributes of all users, with the following command:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Get-NetUser | select name,badPwdCount,lockoutTime\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The output result is shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770017480973_4_3ea5ca7a7c.jpeg\">\u003C\u002Fp>\u003Cp>Clearly, it can be seen that user testa is in a locked state\u003C\u002Fp>\u003Ch3>3. Use DomainPasswordSpray for password spraying\u003C\u002Fh3>\u003Cp>Address:\u003C\u002Fp>\u003Cp>https:\u002F\u002Fgithub.com\u002Fdafthack\u002FDomainPasswordSpray\u003C\u002Fp>\u003Cp>Principle: Attempt LDAP queries through ADSI (Active Directory Services Interface) to obtain results\u003C\u002Fp>\u003Cp>Example as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Invoke-DomainPasswordSpray -UserList .\\users.txt -Password DomainUser123! -Verbose\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The output result is as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770017490694_5_4e86bafc03.jpeg\">\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>DomainPasswordSpray supports the function of filtering users, obtaining a list of all users, and excluding disabled and locked-out users\u003C\u002Fp>\u003Cp>The command is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Get-DomainUserList -RemoveDisabled -RemovePotentialLockouts\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>In my test environment (dc: Server2012R2), this function encountered a bug and could not identify the locked-out user testa\u003C\u002Fp>\u003Cp>As shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770017500157_6_771c6d5063.jpeg\">\u003C\u002Fp>\u003Cp>In reality, the status of user testa is locked, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770017507160_7_49b94c99b3.jpeg\">\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770017512745_8_6439eaf29f.jpeg\">\u003C\u002Fp>\u003Cp>Personal speculation on the cause of the bug is as follows:\u003C\u002Fp>\u003Cp>DomainPasswordSpray determines whether a user is locked by checking the ACCOUNTDISABLE attribute at offset 0x0010 (marked as LOCKOUT). The corresponding code location is: https:\u002F\u002Fgithub.com\u002Fdafthack\u002FDomainPasswordSpray\u002Fblob\u002Fmaster\u002FDomainPasswordSpray.ps1#L408\u003C\u002Fp>\u003Cp>Based on my test environment, the conclusion is that this value cannot be used for judgment. The correct method is to identify it through the badPwdCount attribute and lockoutTime attribute\u003C\u002Fp>\u003Ch2>0x04 Methods for brute-forcing domain user passwords from outside the domain\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>1. Brute-forcing domain user passwords using ldapsearch on Kali system\u003C\u002Fh3>\u003Cp>A previous article 'Penetration Basics - Obtaining Active Directory Information' introduced the method of connecting to an LDAP server using ldapsearch on Kali system\u003C\u002Fp>\u003Cp>Here, a simple loop can be added to achieve brute-forcing. The complete bash command is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>for i in $(cat test.txt); do echo -e \"\\n$i\";ldapsearch -x -H ldap:\u002F\u002F192.168.1.1:389 -D \"CN=\"$i\",CN=Users,DC=test,DC=com\" -w DomainUser123! -b \"DC=test,DC=com\" |grep \"# numEntrie\";done\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>test.txt stores all usernames. If the password is correct, it outputs the count of query results; if the password is wrong, it returns an authentication error: ldap_bind: Invalid credentials (49)\u003C\u002Fp>\u003Cp>The output result is shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770017517806_9_f15b5070a2.jpeg\">\u003C\u002Fp>\u003Cp>Successfully brute-forced the password for user testb\u003C\u002Fp>\u003Ch3>2. Brute-forcing domain user passwords from outside the domain using Invoke-DomainPasswordSprayOutsideTheDomain on Windows system\u003C\u002Fh3>\u003Cp>DomainPasswordSpray has relatively complete functionality but does not support usage outside the domain. Therefore, I made some modifications based on DomainPasswordSpray to enable its use outside the domain\u003C\u002Fp>\u003Cp>The specific modifications are as follows:\u003C\u002Fp>\u003Cp>Modify the LDAP query statement in the original version:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>$DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext(\"domain\",$Domain)\u003Cbr>$DomainObject = [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext)\u003Cbr>$CurrentDomain = \"LDAP:\u002F\u002F\" + ([ADSI]\"LDAP:\u002F\u002F$Domain\").distinguishedName\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Replace with LDAP query statement, example: \"192.168.1.1\u002FDC=test,DC=com\"\u003C\u002Fp>\u003Cp>The final complete query statement is: LDAP:\u002F\u002F192.168.1.1\u002FDC=test,DC=com\u003C\u002Fp>\u003Cp>Since brute-forcing is performed outside the domain and domain user password policies cannot be obtained, I removed the functionality to retrieve password policies from DomainPasswordSpray\u003C\u002Fp>\u003Cp>I have uploaded the modified code to GitHub, address as follows:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>Example command for use outside the domain:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Invoke-DomainPasswordSprayOutsideTheDomain -Domain \"192.168.1.1\u002FDC=test,DC=com\" -UserList .\\user.txt -Password DomainUser123! -Verbose\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Output result as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770017522149_10_75ae93dad9.jpeg\">\u003C\u002Fp>\u003Ch2>0x05 Exploitation Approach\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>1. Brute-force domain user passwords within the domain\u003C\u002Fh3>\u003Cp>Process as follows:\u003C\u002Fp>\u003Ch4>(1) Obtain the password policy for domain users\u003C\u002Fh4>\u003Cp>Determine the number of attempts based on the value of lockoutThreshold to avoid account lockout\u003C\u002Fp>\u003Ch4>(2) Obtain the domain user list\u003C\u002Fh4>\u003Cp>After listing all domain users, it is necessary to evaluate user attributes and exclude disabled and locked users\u003C\u002Fp>\u003Ch4>(3) Attempt to crack\u003C\u002Fh4>\u003Ch3>2. Brute-force cracking of domain user passwords from outside the domain\u003C\u002Fh3>\u003Cp>If a user's password has already been obtained, the domain user password policy and user list can first be retrieved using the same method as above\u003C\u002Fp>\u003Cp>If no user passwords are available, only blind attempts can be made\u003C\u002Fp>\u003Ch2>0x06 Detection Methods\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>The lastbadpasswordattempt attribute in domain user properties records the last login time with an incorrect password, which can serve as a basis for identifying brute-force attacks\u003C\u002Fp>\u003Cp>The badPwdCount attribute records the number of incorrect password attempts, but it resets to zero after the user enters the correct password, making it unreliable as a basis for judgment\u003C\u002Fp>\u003Cp>If the attacker launches the attack from within the domain, they have already obtained the domain user password policy and user list. From a defense perspective, it is essential to ensure that domain user passwords are not predictable and to prevent multiple users from using the same password\u003C\u002Fp>\u003Cp>Logs (4625 - An account failed to log on) can record login failure events, such as logs generated when a Kali system brute-forces domain user passwords via ldapsearch, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770017525029_11_724945dd58.jpeg\">\u003C\u002Fp>\u003Cp>Using kerbrute for brute force does not generate logs (4625 - An account failed to log on), but can be recorded via logs (4768 - A Kerberos authentication ticket (TGT) was requested and 4771 - Kerberos pre-authentication failed).\u003C\u002Fp>\u003Ch2>0x07 Summary\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article introduced common methods for brute-forcing domain user passwords both inside and outside the domain, discussed a bug I discovered while testing DomainPasswordSpray (which requires further testing in more environments), implemented out-of-domain brute force based on DomainPasswordSpray, and presented detection methods in combination with exploitation approaches.\u003C\u002Fp>\u003C\u002Fbody>\u003C\u002Fhtml>","text","ltr","\u003Chtml>\u003Chead>\u003C\u002Fhead>\u003Cbody>\u003Ch2>0x00 Introduction\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>In domain penetration, if some domain user passwords have been obtained, the common approach is to identify password patterns, generate dictionary files, and attempt brute-force attacks on other domain user passwords.\u003C\u002Fp>\u003Cp>From a defensive perspective, it is necessary to ensure that domain users do not use weak passwords with identifiable patterns and to detect brute-force attempts against domain user passwords.\u003C\u002Fp>\u003Cp>This article will introduce common methods for brute-forcing domain user passwords both inside and outside the domain, along with attack methodologies and detection techniques.\u003C\u002Fp>\u003Ch2>0x01 Overview\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article will cover the following topics:\u003C\u002Fp>\u003Cul>\u003Cli>Methods for brute-forcing domain user passwords within the domain\u003C\u002Fli>\u003Cli>Methods for brute-forcing domain user passwords from outside the domain\u003C\u002Fli>\u003Cli>Detection methods\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>0x02 Considerations for Brute-Forcing Domain User Passwords\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Multiple incorrect password attempts will result in user account lockout, with the default threshold set to 5 attempts\u003C\u002Fp>\u003Cp>After a user account is locked, it typically requires a 30-minute waiting period by default before it can be used again.\u003C\u002Fp>\u003Cp>The time of the last incorrect password entry is recorded and cannot be cleared by modifying LDAP data, with the following prompt:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Error 0x209A Access to the attribute is not permitted because the attribute is owned by the Security Accounts Manager (SAM).\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>After a user account is locked, even if the correct password is entered, a password error prompt will still appear.\u003C\u002Fp>\u003Ch2>0x03 Methods for brute-forcing domain user passwords within the domain.\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>1. Obtain the password policy for users within the domain to avoid account lockouts.\u003C\u002Fh3>\u003Cp>For detailed methods on obtaining password policies, refer to the previous article 'Penetration Basics - Obtaining Domain User Password Policies'.\u003C\u002Fp>\u003Ch3>2. Obtain a list of all domain users.\u003C\u002Fh3>\u003Cp>For detailed methods on obtaining this, refer to the earlier article 'Penetration Basics - Obtaining Active Directory Information'.\u003C\u002Fp>\u003Cp>Here, additional judgment on user attributes is required to filter out disabled and locked users.\u003C\u002Fp>\u003Ch4>(1) Identifying disabled users.\u003C\u002Fh4>\u003Cp>The flag indicating whether a user is disabled is located in the userAccountControl attribute, specifically at position 0x0002.\u003C\u002Fp>\u003Cp>As shown in the figure below.\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770017374896_0_d02ce7fd68-1.jpeg\">\u003C\u002Fp>\u003Cp>References:\u003C\u002Fp>\u003Cp>https:\u002F\u002Fsupport.microsoft.com\u002Fen-us\u002Fhelp\u002F305144\u002Fhow-to-use-useraccountcontrol-to-manipulate-user-account-properties\u003C\u002Fp>\u003Cp>Use PowerView to view the ACCOUNTDISABLE attribute for all users with the following command:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Get-NetUser | select name,useraccountcontrol\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The output is as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770017395828_1_16b15a0508-1.jpeg\">\u003C\u002Fp>\u003Cp>To view the specific value of the ACCOUNTDISABLE attribute for a specified user, use the following command:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Get-NetUser test2| select useraccountcontrol | ConvertFrom-UACValue -ShowAll\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The output is as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770017440553_2_b7a5c97b30-1.jpeg\">\u003C\u002Fp>\u003Cp>It can be determined that user test2 has the following attributes:\u003C\u002Fp>\u003Cul>\u003Cli>ACCOUNTDISABLE\u003C\u002Fli>\u003Cli>NORMAL_ACCOUNT\u003C\u002Fli>\u003Cli>DONT_EXPIRE_PASSWORD\u003C\u002Fli>\u003C\u002Ful>\u003Ch4>(2) Identify locked users\u003C\u002Fh4>\u003Cp>Although the user's ACCOUNTDISABLE attribute is marked as LOCKOUT at offset 0x0010, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770017466661_3_ec0e676913-1.jpeg\">\u003C\u002Fp>\u003Cp>However, the value at this location cannot be used to determine whether the current user is locked out\u003C\u002Fp>\u003Cp>We can determine by reading the user's badPwdCount attribute and lockoutTime attribute\u003C\u002Fp>\u003Cp>Use PowerView to view the badPwdCount and lockoutTime attributes of all users, with the following command:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Get-NetUser | select name,badPwdCount,lockoutTime\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The output result is shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770017480973_4_3ea5ca7a7c-1.jpeg\">\u003C\u002Fp>\u003Cp>Clearly, it can be seen that user testa is in a locked state\u003C\u002Fp>\u003Ch3>3. Use DomainPasswordSpray for password spraying\u003C\u002Fh3>\u003Cp>Address:\u003C\u002Fp>\u003Cp>https:\u002F\u002Fgithub.com\u002Fdafthack\u002FDomainPasswordSpray\u003C\u002Fp>\u003Cp>Principle: Attempt LDAP queries through ADSI (Active Directory Services Interface) to obtain results\u003C\u002Fp>\u003Cp>Example as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Invoke-DomainPasswordSpray -UserList .\\users.txt -Password DomainUser123! -Verbose\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The output result is as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770017490694_5_4e86bafc03-1.jpeg\">\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>DomainPasswordSpray supports the function of filtering users, obtaining a list of all users, and excluding disabled and locked-out users\u003C\u002Fp>\u003Cp>The command is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Get-DomainUserList -RemoveDisabled -RemovePotentialLockouts\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>In my test environment (dc: Server2012R2), this function encountered a bug and could not identify the locked-out user testa\u003C\u002Fp>\u003Cp>As shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770017500157_6_771c6d5063-1.jpeg\">\u003C\u002Fp>\u003Cp>In reality, the status of user testa is locked, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770017507160_7_49b94c99b3-1.jpeg\">\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770017512745_8_6439eaf29f-1.jpeg\">\u003C\u002Fp>\u003Cp>Personal speculation on the cause of the bug is as follows:\u003C\u002Fp>\u003Cp>DomainPasswordSpray determines whether a user is locked by checking the ACCOUNTDISABLE attribute at offset 0x0010 (marked as LOCKOUT). The corresponding code location is: https:\u002F\u002Fgithub.com\u002Fdafthack\u002FDomainPasswordSpray\u002Fblob\u002Fmaster\u002FDomainPasswordSpray.ps1#L408\u003C\u002Fp>\u003Cp>Based on my test environment, the conclusion is that this value cannot be used for judgment. The correct method is to identify it through the badPwdCount attribute and lockoutTime attribute\u003C\u002Fp>\u003Ch2>0x04 Methods for brute-forcing domain user passwords from outside the domain\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>1. Brute-forcing domain user passwords using ldapsearch on Kali system\u003C\u002Fh3>\u003Cp>A previous article 'Penetration Basics - Obtaining Active Directory Information' introduced the method of connecting to an LDAP server using ldapsearch on Kali system\u003C\u002Fp>\u003Cp>Here, a simple loop can be added to achieve brute-forcing. The complete bash command is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>for i in $(cat test.txt); do echo -e \"\\n$i\";ldapsearch -x -H ldap:\u002F\u002F192.168.1.1:389 -D \"CN=\"$i\",CN=Users,DC=test,DC=com\" -w DomainUser123! -b \"DC=test,DC=com\" |grep \"# numEntrie\";done\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>test.txt stores all usernames. If the password is correct, it outputs the count of query results; if the password is wrong, it returns an authentication error: ldap_bind: Invalid credentials (49)\u003C\u002Fp>\u003Cp>The output result is shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770017517806_9_f15b5070a2-1.jpeg\">\u003C\u002Fp>\u003Cp>Successfully brute-forced the password for user testb\u003C\u002Fp>\u003Ch3>2. Brute-forcing domain user passwords from outside the domain using Invoke-DomainPasswordSprayOutsideTheDomain on Windows system\u003C\u002Fh3>\u003Cp>DomainPasswordSpray has relatively complete functionality but does not support usage outside the domain. Therefore, I made some modifications based on DomainPasswordSpray to enable its use outside the domain\u003C\u002Fp>\u003Cp>The specific modifications are as follows:\u003C\u002Fp>\u003Cp>Modify the LDAP query statement in the original version:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>$DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext(\"domain\",$Domain)\u003Cbr>$DomainObject = [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext)\u003Cbr>$CurrentDomain = \"LDAP:\u002F\u002F\" + ([ADSI]\"LDAP:\u002F\u002F$Domain\").distinguishedName\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Replace with LDAP query statement, example: \"192.168.1.1\u002FDC=test,DC=com\"\u003C\u002Fp>\u003Cp>The final complete query statement is: LDAP:\u002F\u002F192.168.1.1\u002FDC=test,DC=com\u003C\u002Fp>\u003Cp>Since brute-forcing is performed outside the domain and domain user password policies cannot be obtained, I removed the functionality to retrieve password policies from DomainPasswordSpray\u003C\u002Fp>\u003Cp>I have uploaded the modified code to GitHub, address as follows:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>Example command for use outside the domain:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Invoke-DomainPasswordSprayOutsideTheDomain -Domain \"192.168.1.1\u002FDC=test,DC=com\" -UserList .\\user.txt -Password DomainUser123! -Verbose\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Output result as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770017522149_10_75ae93dad9-1.jpeg\">\u003C\u002Fp>\u003Ch2>0x05 Exploitation Approach\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>1. Brute-force domain user passwords within the domain\u003C\u002Fh3>\u003Cp>Process as follows:\u003C\u002Fp>\u003Ch4>(1) Obtain the password policy for domain users\u003C\u002Fh4>\u003Cp>Determine the number of attempts based on the value of lockoutThreshold to avoid account lockout\u003C\u002Fp>\u003Ch4>(2) Obtain the domain user list\u003C\u002Fh4>\u003Cp>After listing all domain users, it is necessary to evaluate user attributes and exclude disabled and locked users\u003C\u002Fp>\u003Ch4>(3) Attempt to crack\u003C\u002Fh4>\u003Ch3>2. Brute-force cracking of domain user passwords from outside the domain\u003C\u002Fh3>\u003Cp>If a user's password has already been obtained, the domain user password policy and user list can first be retrieved using the same method as above\u003C\u002Fp>\u003Cp>If no user passwords are available, only blind attempts can be made\u003C\u002Fp>\u003Ch2>0x06 Detection Methods\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>The lastbadpasswordattempt attribute in domain user properties records the last login time with an incorrect password, which can serve as a basis for identifying brute-force attacks\u003C\u002Fp>\u003Cp>The badPwdCount attribute records the number of incorrect password attempts, but it resets to zero after the user enters the correct password, making it unreliable as a basis for judgment\u003C\u002Fp>\u003Cp>If the attacker launches the attack from within the domain, they have already obtained the domain user password policy and user list. From a defense perspective, it is essential to ensure that domain user passwords are not predictable and to prevent multiple users from using the same password\u003C\u002Fp>\u003Cp>Logs (4625 - An account failed to log on) can record login failure events, such as logs generated when a Kali system brute-forces domain user passwords via ldapsearch, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770017525029_11_724945dd58-1.jpeg\">\u003C\u002Fp>\u003Cp>Using kerbrute for brute force does not generate logs (4625 - An account failed to log on), but can be recorded via logs (4768 - A Kerberos authentication ticket (TGT) was requested and 4771 - Kerberos pre-authentication failed).\u003C\u002Fp>\u003Ch2>0x07 Summary\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article introduced common methods for brute-forcing domain user passwords both inside and outside the domain, discussed a bug I discovered while testing DomainPasswordSpray (which requires further testing in more environments), implemented out-of-domain brute force based on DomainPasswordSpray, and presented detection methods in combination with exploitation approaches.\u003C\u002Fp>\u003C\u002Fbody>\u003C\u002Fhtml>",1219,"Onedaysec",7,"published","2026-02-02T07:51:00.264Z",{"title":37,"description":14,"keywords":38,"ogImage":39,"canonicalUrl":39,"noIndex":40},"Brute-Forcing Domain User Passwords via LDAP: Attack & Detection","domain penetration, brute-force attacks, LDAP protocol, password spraying, Active Directory security, user account lockout, detection techniques, DomainPasswordSpray, password policies, cybersecurity",null,false,[],{"docs":43,"hasNextPage":40},[44,4,45,46],415,413,412,{"title":39,"description":39,"image":39},"2026-07-24T15:37:13.515Z","2026-07-23T16:01:32.703Z","draft","2026-07-23T16:06:03.198Z"]