Good in study, attitude and health

渗透基础——域用户的密码永不过期属性

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属性,可以看到用户是否设置为密码永不过期,如下图

Alt text

下面介绍不同环境下的枚举方法

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

如下图

Alt text

筛选出符合条件的所有用户:

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]);

测试如下图

Alt text

(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

测试如下图

Alt text

获取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

测试如下图

Alt text

0x05 向指定用户删除密码永不过期属性的方法


有以下两种实现方法:

1.userAccountControl属性值同65536作按位异或运算(运算符^) 2.userAccountControl属性值直接减去65536

具体方法同0x04类似,不再重复介绍

0x06 小结


本文介绍了域用户具有密码永不过期属性的特征,分析枚举、添加和删除属性的原理,介绍不同条件下的多种实现方法,开源c#实现代码。


LEAVE A REPLY