0x00 前言
在域环境中,域用户的凭据是十分重要的信息。为了增强安全性,域组策略会设置所有域用户口令的最长有效时间,到达过期时间后强制用户更改口令。
在实际环境中,有些域用户需要设置为密码永不过期,这可以通过添加密码永不过期属性来实现。
在域渗透中,我们需要枚举出具有密码永不过期属性的域用户,也需要能够将某个域用户设置为密码永不过期。
相对的站在防御角度,我们需要尽可能减少具有密码永不过期属性的域用户,也需要能够实时掌握这个域用户列表。
所以本文将会介绍不同条件下多种枚举、添加和删除密码永不过期属性的方法,分析原理,开源代码。
0x01 简介
本文将要介绍以下内容:
- 实现原理
- 枚举密码设置为永不过期的用户
- 向指定用户添加密码永不过期属性的方法
- 向指定用户删除密码永不过期属性的方法
0x02 实现原理
域用户的密码永不过期属性保存在域用户的userAccountControl属性中,userAccountControl属性使用数字表示,数值是多个具体属性数值的总和,每个具体属性对应一个不同的数值,具体的数值可参考:https://support.microsoft.com/en-us/help/305144/how-to-use-useraccountcontrol-to-manipulate-user-account-properties
下面举例进行说明:
用户test1的userAccountControl属性值为514,那么这个用户的具体属性如下:
- ACCOUNTDISABLE,2
- NORMAL_ACCOUNT,512
计算方法为2+512=514
添加密码永不过期属性的方法:
密码永不过期属性对应的值为65536(DONT_EXPIRE_PASSWORD),将userAccountControl属性值514再加上65536,设置为66048即可
注:
在程序设计上,为了可重复使用,采用的方法是同65536作按位或运算(`运算符|`)
按位或运算的运算规则:参加运算的两个数,按二进制位进行或运算,只要对应的二进位有一个为1时,结果位就为1,否则为0。
删除密码永不过期属性的方法:
将userAccountControl属性值减去65536即可
注:
在程序设计上,为了可重复使用,采用的方法是同65536作按位异或运算(`运算符^`)
按位异或运算的运算规则:参加运算的两个数,按二进制位进行"异或"运算,如果两个相应位相同,则结果为0,否则为1。
查看密码永不过期属性的方法:
userAccountControl属性值是各个数值的总和,我们无法通过简单的加减法计算出userAccountControl属性值是否包括65536这个被加数。
这里可以通过按位与运算(`运算符&`)来实现
按位与运算的运算规则:参加运算的两个数,按二进制位进行"与"运算,只有两个数的二进制同时为1,结果才为1,否则为0。
查看密码永不过期属性的计算方法:
将userAccountControl属性值同65536做按位与运算,如果结果为65536,那么代表具有密码永不过期的属性
0x03 枚举密码设置为永不过期的用户
我们在域控制器上,通过`Active Directory Users and Computers`查看每个域用户的`Account`属性,可以看到用户是否设置为密码永不过期,如下图:
下面介绍不同环境下的枚举方法
1.从域内进行枚举的方法
(1)Windows系统使用Powershell ActiveDirectory模块
命令示例:
Import-Module ActiveDirectory Search-ADAccount -PasswordNeverExpires | FT Name
或者:
Import-Module ActiveDirectory Get-ADUser -filter * -properties Name, PasswordNeverExpires | where {$_.passwordNeverExpires -eq "true" }| FT Name
(2)Windows系统使用PowerView
https://github.com/PowerShellMafia/PowerSploit/blob/master/Recon/PowerView.ps1
命令示例:
显示出指定用户的属性:
import-module .\PowerView.ps1 Get-NetUser test1| select useraccountcontrol | ConvertFrom-UACValue
如下图:
筛选出符合条件的所有用户:
import-module .\PowerView.ps1 ForEach($User in (Get-NetUser)) { if(($User.useraccountcontrol -band 65536) -eq 65536) { Write-Output $User.samaccountname } }
(3)Windows系统使用C#实现
使用命名空间`System.DirectoryServices`,详细代码已上传至github,地址如下:
https://github.com/3gstudent/Homework-of-C-Sharp/blob/master/List_passwordneverexpires_user_byLDAP.cs
如果使用当前用户的凭据,需要将代码`DirectoryEntry de = new DirectoryEntry("LDAP://" + args[0],args[1],args[2]);`替换为`DirectoryEntry de = new DirectoryEntry("LDAP://" + args[0]);`
测试如下图:
(4)Kali系统通过ldapsearch枚举
命令示例:
ldapsearch -x -H ldap://192.168.1.1:389 -D "CN=testa,CN=Users,DC=test,DC=com" -w DomainPassword123! -b "DC=test,DC=com" "(&(objectClass=user)(objectCategory=person))" grep userAccountControl
测试如下图:
获取userAccountControl属性值后再同65536做按位与运算,获得最终结果
2.从域外进行枚举的方法
(1)Windows系统使用Powershell ActiveDirectory模块
命令示例:
import-module .\Microsoft.ActiveDirectory.Management.dll $uname="test1" $pwd=ConvertTo-SecureString "DomainPassword123!" -AsPlainText –Force $cred=New-Object System.Management.Automation.PSCredential($uname,$pwd) Search-ADAccount -Server 192.168.1.1 -Credential $cred -Verbose -PasswordNeverExpires | FT Name
或者:
import-module .\Microsoft.ActiveDirectory.Management.dll $uname="test1" $pwd=ConvertTo-SecureString "DomainPassword123!" -AsPlainText –Force $cred=New-Object System.Management.Automation.PSCredential($uname,$pwd) Get-ADUser -Server 192.168.1.1 -Credential $cred -filter * -properties Name, PasswordNeverExpires | where {$_.passwordNeverExpires -eq "true" }| FT Name
注:
域控制器默认安装ActiveDirectory模块,Microsoft.ActiveDirectory.Management.dll在安装powershell模块Active Directory后生成,我已经提取出来并上传至github:
https://github.com/3gstudent/test/blob/master/Microsoft.ActiveDirectory.Management.dll
对于未安装Active Directory模块的系统,可以通过如下命令导入Active Directory模块:
import-module .\Microsoft.ActiveDirectory.Management.dll
(2)Windows系统使用PowerView
https://github.com/PowerShellMafia/PowerSploit/blob/master/Recon/PowerView.ps1
命令示例:
import-module .\PowerView.ps1 $uname="test1" $pwd=ConvertTo-SecureString "DomainPassword123!" -AsPlainText –Force $cred=New-Object System.Management.Automation.PSCredential($uname,$pwd) $Users=Get-NetUser -Domain "test.com" -DomainController 192.168.1.1 -Credential $cred ForEach($User in $Users) { if(($User.useraccountcontrol -band 65536) -eq 65536) { Write-Output $User.samaccountname } }
(3)Windows系统使用C#实现
使用命名空间System.DirectoryServices,详细代码已上传至github,地址如下:
https://github.com/3gstudent/Homework-of-C-Sharp/blob/master/List_passwordneverexpires_user_byLDAP.cs
0x04 向指定用户添加密码永不过期属性的方法
有以下两种实现方法:
1.userAccountControl属性值同65536作按位或运算(`运算符|`)
2.userAccountControl属性值直接加上65536
为了能够重复使用,以下方法均使用同65536作按位或运算的方法实现
1.从域内实现
(1)使用dsmod命令
命令实例:
dsmod user "CN=testc,CN=Users,DC=test,DC=com" -pwdneverexpires yes
(2)使用Powershell ActiveDirectory模块
命令实例:
Set-ADUser -Identity testc -PasswordNeverExpires $true
(3)使用PowerView
命令实例:
Set-ADObject -SamAccountName testc -PropertyName useraccountcontrol -PropertyXorValue 65536
(4)C#实现
使用命名空间System.DirectoryServices,详细代码已上传至github,地址如下:
https://github.com/3gstudent/Homework-of-C-Sharp/blob/master/Add_passwordneverexpires_user_byLDAP.cs
2.从域外实现
(1)使用Powershell ActiveDirectory模块
命令实例:
import-module .\Microsoft.ActiveDirectory.Management.dll
$uname="administrator"
$pwd=ConvertTo-SecureString "DomainPassword123!" -AsPlainText –Force
$cred=New-Object System.Management.Automation.PSCredential($uname,$pwd)
Set-ADUser -Server 192.168.1.1 -Credential $cred -Identity testc -PasswordNeverExpires $true
(2)使用PowerView
命令实例:
$uname="administrator" $pwd=ConvertTo-SecureString "DomainPassword123!" -AsPlainText –Force $cred=New-Object System.Management.Automation.PSCredential($uname,$pwd) $Users=Get-NetUser -Domain "test.com" -DomainController 192.168.1.1 -Credential $cred Set-ADObject -Domain "test.com" -DomainController 192.168.1.1 -Credential $cred -SamAccountName testc -PropertyName useraccountcontrol -PropertyXorValue 65536
(3)C#实现
使用命名空间`System.DirectoryServices`,详细代码已上传至github,地址如下:
https://github.com/3gstudent/Homework-of-C-Sharp/blob/master/Add_passwordneverexpires_user_byLDAP.cs
测试如下图:
0x05 向指定用户删除密码永不过期属性的方法
有以下两种实现方法:
1.userAccountControl属性值同65536作按位异或运算(`运算符^`)
2.userAccountControl属性值直接减去65536
具体方法同0x04类似,不再重复介绍
0x06 小结
本文介绍了域用户具有密码永不过期属性的特征,分析枚举、添加和删除属性的原理,介绍不同条件下的多种实现方法,开源c#实现代码。
本文为 3gstudent 原创稿件,授权嘶吼独家发布,如若转载,请注明原文地址: