Tag Archives: Active Directory

Reset passwords for Active Directory Users

Reset and manage your Active Directory users' Passwords

Active Directory is one of the most esential and important tool in any company whether small or big. In most cases big companies have uncountable amount of tools to maintain and protect users and their credentials however almost most of those companies are not prepared to the time when their systems have been compromised or to say the least their servers have been hacked or encrypted by ransomware which is something we hear very often nowadays like the case with Louisiana Hospital that was attacked by Ransomware exposing the data of 270000 patients. 

Realistic scenario

What if your users passwords were compromised and you’re not sure who is still safe or not but you need to act as fast as possible? 

To act fast, I created a script that would generate a complex 32 Char long password with 4 different Non Alphanumeric Characters using the System.Web.Security.Membership  class. here’s an example of this password:

81Q:#_#E-QVZ-(1m&VS1LKpbzwR+8Em%

The script details

The script will first check if you have the Powershell Get and ImportExcel Module installed, if not it’ll ask you to install it or not. 

You will need to amend few things

1- The path to reflect where you want to save the Logs, CSV and Excel sheet. as of now it’s in c:\SyncReports. 

2- Importing users, In the script I am grabbing users directly from a specific OU in AD. so you’ll need to decide how you want to do it. I have added another line in case you’re planning to 

3- The password reset command is setup with -whatif parameter for you to test this before you run it. so just remember to remove it when you’re done with the changing and testing.

I have added mailbody and send-message command to send the excel as an attachment along with the excel password protection. 

Running the script will result in the following

Once you get the Excel sheet and try to open it, you will realize that it’s password protected. The password should be in the email body that’s sent in the script.

Excel sheet result will be looking as follows:

The script
The script 90%
#This script will generate randdom complex passwords for all AD users

#Using Time class and start reporting
$TimeStamp = [datetime]::Now.ToString(“MM-dd-yyyy-HH-mm”)
Start-Transcript -Path C:\SyncReports\Logs\Logs_$TimeStamp.txt -IncludeInvocationHeader

#Generate report
$Report = [System.Collections.Generic.List[Object]]::new()

#Check if Excel Module is installed, if not it’ll ask to install it

##Check Protocol and Setting Secure Connectivity

[Net.ServicePointManager]::SecurityProtocol
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls, [System.Net.SecurityProtocolType]::Tls11,[System.Net.SecurityProtocolType]::Tls12

#Install PowershellGet and ImportExcel Modules
if (Get-Module -ListAvailable -Name PowershellGet) {
    Write-Host “PowershellGet exists”
} else {Install-Module PowershellGet -Force}
if (Get-Module -ListAvailable -Name ImportExcel) {
    Write-Host “ImportExcel exists”
}
else {
    Write-host “Module does not exist, Would you like to install it?”
    $options = [System.Management.Automation.Host.ChoiceDescription[]] @(‘&Yes’, ‘&No’)
    if(0 -eq $host.UI.PromptForChoice(‘Install?’ , ‘Would you like to install ImportExcel’ , $Options,0)){
        Write-Host “Installing Excel Module”… -fore green
        Install-Module -Name ImportExcel
        return
    }
}

# Import System.Web assembly
Add-Type -AssemblyName System.Web

#Defining where to get users from:
$Users = Get-ADUser -SearchBase “OU=Moh10ly_Users,DC=moh10ly,DC=local” -Filter * -Properties *
#$Users = Import-Csv “C:\SyncReports\Users.csv”
foreach ($User in $Users){
       
        $UID = $User.UserPrincipalName
        $ObjectProp = Get-ADUser -Filter {(Mail -like $UID) -or (UserPrincipalName -like $UID)} -Properties *

        #Generate New Password
        $NewPassword=[System.Web.Security.Membership]::GeneratePassword(32,4)
        $Password= ConvertTo-SecureString $newPassword -AsPlainText -Force
        $TEXTO = “$newPassword”
        $ENCODED1 = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($TEXTO))
       
        $Name = $ObjectProp.Name
        $SAM = $ObjectProp.SamAccountName

        if($SAM){
 
                   
                         $ReportLine = [PSCustomObject][Ordered]@{
                            DateandTime                 = $TimeStamp
                            UPN                         = $ObjectProp.UserPrincipalName
                            DisplayName                 = $ObjectProp.Displayname
                            Email                       = $ObjectProp.Mail
                            Encoded                     = $ENCODED1
                            Password                    = $newPassword
                            Error                       = $ObjectProp.Exception.Message
                            }
                           
                            $Report.Add($ReportLine)
           
            #Wait for Email to send
            #Start-Sleep -Seconds 15

            #Resetting user’s password
            Set-ADAccountPassword -Identity $User.SamAccountName -NewPassword $Password -WhatIf

        }
    else {$Error = Write-Host -f Red “$($User) Couldn’t be found”    
    #send-mailmessage -from “admin@skybirdtravel.com” -to “admin@skybirdtravel.com” -subject “Password reset didn’t work for $($User.UserprincipalName) on $TimeStamp” -body “$Error” -Priority High -smtpServer mailcleaner.cloudapphost.net}
    }
}
Stop-Transcript
Write-Host (“{0} Users processed” -f $Users.count)
#$Report | Out-GridView
$ExcelPassword =[System.Web.Security.Membership]::GeneratePassword(32,4)
$Report | Select-Object UPN,Displayname,Email,Encoded,Password | Export-Csv -NoTypeInformation “C:\SyncReports\UserReset_$TimeStamp.csv”
$Report | Export-Excel “C:\SyncReports\UserReset_$TimeStamp.xlsx” -WorksheetName Users -TableName Users -AutoSize -Password “$ExcelPassword”
$Exported = “C:\SyncReports\UserReset_$TimeStamp.xlsx”
$MailBody = “
            <html><body>
            <font color=’006400′> Dear Team, Please find attached the list of users and their passwords encoded … `
            The file is protected with password // $ExelPassword // If any issue you can send an email to support@domain.com .</font>
            <body><html>
            “
$CC = @(‘info@moh10ly.com’)

#Get-ChildItem $Exported | send-mailmessage -from “admin@domain.com” -to “report@domain.com” -Cc $CC -subject ” User Passwords List for the date $date” -body “$MailBody” -Priority High -smtpServer relay.domain.com -BodyAsHtml

Finally:

I have added this script to github, so feel free to comment or add your contribution if needed.

https://github.com/moh30ly/powershell/blob/main/ADPasswordChange

Get Report of Active Directory Locked Accounts and Machine they logged in from

Story:

I got some clients  that have reported some of their users being locked out and not able to discover how is this happening or which device its getting locked on.

Symptoms:

The user lock happens after you setup your GPO policy to get user locked after failing to login for X times with the correct password.

When user gets locked, they either can’t login or get prompted to re-enter their password in Outlook for example not knowing they have been locked. 

Hard to Find Out:

There’s no easy way to figure out what’s really happening and why the user got locked out specially if the account is being used on multiple devices e.g. (Phone, iPad, Desktop ..etc). Unless you have an auditing or an AD monitoring software that will log all auditing attempts to an external party and tell you where exactly the user is coming from, it’s a not an easy task to find out where is this taking place.  

Solution: 

1- Enabling Relevant Logs

In order for this to work, you’ll need to enable some Auditing logs on the Default Domain Controller Group Policy

Go to  >> Computer Configuration >> Windows Settings >> Security Settings >> Advanced Audit Policy Configuration >> Audit Policies >> Account Management >> Double Click on Audit User Account and enable both Success and Failure.

Once you applied this policy, you’ll need to force update your DCs , Sign out and back in and you’ll start noticing that in Event Viewer / Security the event 4740 and 4625 will start appearing .

The event 4740 will show you the locked user and the machine it tried to login from. 

The event 4625 will show you the path to the process/application that tried to login with your account. 

So to make this more benefitial I ended up writing a script that will get triggered by Task Scheduler in the case of Event 4740 being reported.

The script will search AD for any locked account. will scan the Logs for the user’s event and find the machine the user tried to login from and generate a report with all these details then send it to a target email in Excel forma after converting it using ImportExcel module.

Note that you must have a local SMTP Server for the email to be sent. If not you can just get the CSV and send it manually. 

 

2- Finding the relevant event

3- Finally The script

The script is simple so feel free to modify it, improve it or share it with others. 

Almost done
Script below 80%

#Report NTLM Authentication Failure for users
$ReportTime = ([datetime]::Today).ToString(“MM-dd-yyyy”)

#Generate report
$Report = [System.Collections.Generic.List[Object]]::new()

$LockedAccount = (Search-ADAccount -LockedOut -UsersOnly)
$i = 0
foreach ($User in $LockedAccount){

$i ++
Write-Progress -Activity “Gathering Logon info” -Status “Checking Login info for: $($User.Name)” -PercentComplete (($i / ($LockedAccount | Measure-Object).Count) * 100)
if($User.LockedOut){

$Event = Get-WinEvent -FilterHashtable @{ logname = ‘Security’; id = 4740 } -MaxEvents 500 | Select-Object TimeCreated,
@{ Name=’TargetUserName’; Expression={$_.Properties[0].value}},
@{ Name=’LogonMachine’; Expression={$_.Properties[1].value}} | Where {$_.TargetUserName -eq $User.SamAccountName}
}

$ReportLine = [PSCustomObject][Ordered]@{
Count = $i
ReportedUser = $User.Name
UPN = $User.UserPrincipalName
UserIsLocked = $User.LockedOut
LastLogonDate = $user.Lastlogondate
MachineName = $Event.LogonMachine -join ‘,’
‘Access Failure Time’ = $Event.TimeCreated -join ‘,’
‘Report Date’ = $ReportTime
}
$Report.Add($ReportLine)
}

$MailBody = “
<html><body>
<font color=’006400′> Dear Team, `
Please find attached a report of all locked out users including machine used for the login … `
If any issue you can report it via the ticketing system.</font>
<body><html>

#Eexport in CSV
$Report | Export-csv “C:\Reports\LockOutReport_$ReportTime.cscv” -NoTypeInformation

#Eexport in Excel Format
$Report | Export-Excel “C:\Reports\LockOutReport_$ReportTime.xlsx” -WorksheetName LogonFailure -TableName LogonFailure -AutoSize

$Exported = “C:\Reports\LockOutReport_$ReportTime.xlsx”

$CC = @(‘User2@domain.com’)
#
Get-ChildItem $Exported | send-mailmessage -from “system@domain.com” -to “user1@domain.com” -cc $cc -subject “Users LockOut Report $ReportTime” -body “$MailBody” -Priority High -smtpServer relay.domain.com -BodyAsHtml

Link to Github:

 

https://github.com/moh30ly/powershell/blob/main/ActiveDirectoryLockOutNotification

4- Attach Task to an Event

5- Get The Report

Upgrade FRS (File Replication Service) to DFSR (Distributed File System Replication) Guide through

Upgrade FRS to DFSR:

You might be searching on how to do this due to many reasons, Migrating your DCs to Windows 2016 or Windows 2019, The steps to do this type of migration is pretty easy and straightforward.

First Let’s explain a bit about what does FRS and DFSR do and what is the difference?

Windows Server 2003 and 2003 R2 uses File Replication Service (FRS) to replicate SYSVOL folder content to other domain controllers.

SYSVOL is a folder shared by domain controller to hold its logon scripts, group policies and other items related to AD.

All the domain controllers in the network will replicate the content of SYSVOL folder. The default path for SYSVOL folder is %SystemRoot%\SYSVOL. This folder path can be defined when you install the active directory.

How does DFS Works?

In Windows server 2008 and later Active Directory uses Distributed File System (DFS) for the replication.  DFS Replication uses a compression algorithm known as remote differential compression (RDC). RDC detects changes to the data in a file and enables DFS Replication to replicate only the changed file blocks instead of the entire file.

Although FRS has been deprecated Since Windows server 2008 most people still looking to migrate to latest version.

Migration Starts Here

In this guide, I am going to explain how to do this kind of migration step by step.

I am going to run the migration on Windows 2008 R2 Servers. however the process is exactly the same on Windows 2012 R2.

To start, I need to check the service console to see which services are running the replication. From run type services.msc and enter

As you can see there, File Replication Service is running

clip_image001

In the same manner DFS service is also started and functioning, But that doesn’t mean that RFS is not being used.

clip_image002

Health Check

Before starting any migration, I prefer to do a check on Eventviewer just to make sure nothing critical is being reported. In the same way I would like to see if there any warning being reported.
Below you can see errors are being reported from File Replication Service by the Domain Controller SRV01, So the time is convenient to start this kind of migration as this would fix the errors being reported.

clip_image003

Prerequirements:

The first part of the process for migrating SYSVOL replication from File Replication Service (FRS) to Distributed File System (DFS) Replication is to raise the functional level of the domain to Windows Server 2008 and to set the global migration state to Prepared.

Make sure your Domain Function Level is raised to 2008 at least for this process to work.

Migration:

To start migration, Run Powershell as an administrator from the DC And type the following command to prepare DCs for the migration.

dfsrmig /getglobalstate

clip_image004

Preparing to migrate

dfsrmig /setglobalstate 1

When this is done, you might have to wait sometime (5 mins or less for small environments). When done waiting type dfsrmig /getglobalstate to verify that the global migration state is Prepared. The following output appears if the global migration state is Prepared.

clip_image005

clip_image006

You will be able to see an event ID 8014 showing you the success of this command.  Which means you can move to the next stage.

clip_image007

clip_image008

Migrate the domain to the Redirected state

From a command prompt or PowerShell window on a writeable domain controller (not a read-only domain controller) in the domain that you want to migrate, type dfsrmig /setglobalstate 2 to set the global migration state to Redirected.

clip_image009

2. Type dfsrmig /getglobalstate to verify that the global migration state is Redirected. The following output appears if the global migration state is Redirected.

clip_image010

After doing this, Checking event viewer you can see event ID 8017 showing you the current state, in my case it’s showing DFSR has successfully Migrated the DC to “Redirected” state. so it means we are good to go to the next step.

clip_image011

clip_image012

Migrating to the Eliminated State

Log on to a writeable domain controller (if you are not logged on already).

Open a command prompt window and then type dfsrmig /setglobalstate 3 to set the global migration state to Eliminated.

clip_image013

2. At a command prompt, type dfsrmig /getmigrationstate to verify that all the domain controllers are at the Redirected state. The following output appears when all domain controllers are at the Redirected state.

clip_image014

In the event viewer you can see the state of the DCs reporting that DC will now migrate to the “Eliminated” state. with event ID 8018

clip_image015

clip_image016

Once everything is finished, You will be able to confirm by two things, First on the Service console the File Replication Service should be disabled since it’s no longer going to be used.

clip_image017

Second thing is by using Command line or Powershel, Type Net Share an you can see the new Shares being published with new names “Sysvol_DFSR”.

clip_image018

Ref:

https://docs.microsoft.com/en-us/windows-server/storage/dfs-replication/migrate-sysvol-to-dfsr

https://docs.microsoft.com/en-us/windows/win32/win7appqual/file-replication-service–frs–is-deprecated-in-windows-server-2008-r2

Powershell script to audit users who authenticated against DC servers

The story:

I have got a request from a client asking to find out which server(s) is using which domain admin or a highly privileged account as a service.

To find this I already wrote a powershell script that does this, Search the non standard/(Domain only users) and show the services and name of the servers where those accounts are configured on utilizing Remote powershell to do so and the use of a Domain Admin user.

You can refer to this link to see this article by clicking here

Creating the script process:

The same client wanted to also know which of those accounts did authenticate and wanted to know from which server/Computer did the request originate from and to which DC did it go.

I have started thinking of the process of doing so by again utilizing remote PowerShell to check against certain security events on AD to check which user among the Domain admin members did authenticate.

After sometime and with the help of some forums I managed to get script ready which looks in all Domain Controllers for users that are members of the Domain Admin groups who triggered an event ID 4624 and from which Computer did this request came from.

The Script :

# Get domain admin user list
$DomainAdminList = Get-ADGroupMember -Identity 'Domain Admins'
# Get all Domain Controller names
$DomainControllers = Get-ADDomainController -Filter * | Sort-Object HostName
# EventID
$EventID = '4624'
#
# Get only last 24hrs
$Date = (Get-Date).AddDays(-3)
# Limit log event search for testing as this will take a LONG time on most domains
# For normal running, this will have to be set to zero
$MaxEvent = 100

# Loop through Dcs
$DALogEvents = $DomainControllers | ForEach-Object {
    $CurDC = $_.HostName
    Write-Host "`nSearching $CurDC logs..."
    Get-WinEvent  -ComputerName $CurDC -FilterHashtable @{Logname='Security';ID=$EventID;StartTime = $Date} -MaxEvents $MaxEvent |`
    Where-Object { $_.Properties[5].Value -in $DomainAdminList.SamAccountName } |`
    ForEach-Object {
        [pscustomobject]@{SourceIP = $_.Properties[18].Value; SamAccountName = $_.Properties[5].Value;Time = $_.TimeCreated;LogonEventLocation = $CurDC}
    }
}
$DALogEvents

How to run:

The Script must be run on DC with a privileged account in order to get the write results, The default time interval is set to 3 days but you can choose to increase that.

You can also change the default group where you want to search for members by changing Domain Admin groups to something else.

Screenshot of the result

HOW TO GET ALL DOMAIN JOINED SERVER SERVICES THAT USING A UNIQUE OR DOMAIN USER

The Story (Finding Domain Joined Servers Services users)

If you’re wondering which of your servers are using domain joined account or a non regular account like network service or system. You will need to go through every server’s service console and check that one by one but thanks to PowerShell this job was made like a piece of cake.

Requirement

The requirement to run this script is a domain admin account since the PowerShell will require access to other servers using Remote PowerShell using Invoke command and run a Get-WMIObject script to find out those details. So in short I will write the required things for this to work

1- Logged in to Active Directory (In order for AD PowerShell module to run and find computers).

2- Domain admin account (To run the remote PowerShell on other servers and get service details)

3- Firewall for domain joined computers is open (To allow remote PowerShell to work) or have remote PowerShell enabled via GPO.

The Script will also show you the offline (inaccessible servers) and will state those servers as down as you can see in the screenshot below.

The script will also prompt you for a path to save the output. You can enter something like C:\Services.csv  as soon as you type the file path and extension it’ll be opened using Notepad.

image

#Check servers down and get services from the responsive servers

$Computers = Get-ADComputer -Filter { OperatingSystem -Like ‘*Windows Server*’}

$Input = ForEach ($computer in $computers){

$comp = $Computer.DNSHostName

$dist = $Computer.DistinguishedName

if (Test-Connection -Computername $comp -count 2 -Quiet )

{

Invoke-Command -ComputerName $comp -ScriptBlock {Get-WmiObject win32_service | where {$_.StartName -notlike “*LocalSystem*” -and $_.StartName -notlike “*LocalService*” -and $_.StartName -notlike “*NetworkService*” -and $_.StartName -notlike “*System*”} | select DisplayName,StartName,State }}

else{ Write-host $comp is down -foregroundColor red -BackGroundColor black

}

}

$Output = Read-Host “Enter File path and Name to save output to”

Out-File -FilePath $Output -InputObject $Input -Encoding ascii

Notepad $Output


image

image