February 6, 2017

With the widespread usage of devices such as iPhones and Androids in the business world, it pretty much goes without saying that E-Mail access is literally at everyone's fingertips. For an IT Professional, this can turn into a nightmare to manage as everyone with an E-Mail address will want E-Mail onto their mobile device, whether it be a company-provided device or a personal one. By default, Microsoft Exchange makes it trivial for a user with an E-Mail account to configure it onto their mobile device without needing assistance from IT. Even if you are a business that doesn't allow employees to use their own mobile devices for business-related work, you still cannot prevent them from adding corporate E-Mail onto their own device by default in Microsoft Exchange.

Thankfully, Microsoft provides an ActiveSync Quarantine feature that can be enabled that will allow you to manage all new ActiveSync connections within your Microsoft Exchange server. With this enabled, any new devices that are configured for E-Mail access will be quarantined until an administrator approves the device. Both the employee who is attempting to add E-Mail to their device, and the administrator will receive a notification of this.

In order to first verify that you do not currently have this feature enabled, you can run the following PowerShell command from within the Exchange Management Shell.

Get-ActiveSyncOrganizationSettings

If you do not currently have this feature enabled, then you should see the following for DefaultAccessLevel, UserMailInsert, and AdminMailRecipients.


Once it has been confirmed that this feature doesn't happen to already be enabled, we will need to run a script that will pre-approve all devices that are currently syncing with Microsoft Exchange. Were you to move forward with enabling the Exchange ActiveSync Quarantine without first doing this step, you would end up quarantining every single mobile device that is currently connected to your Exchange server. Chances are, this could end up fairly chaotic, as you probably have more than just a handful of employees with E-Mail on their mobile device. In order to pre-approve all existing devices, we can run a script that will determine the DeviceIDs for each device connected to every employee's E-Mail account, and then add those DeviceIDs to the ActiveSyncAllowedDeviceIDs object on each mailbox.

The script is as follows, and should be ran from the Exchange Management Shell:

# Retrieve mailboxes of users who have a connected ActiveSync Device
$CASMailboxes = Get-CASMailbox -Filter {hasactivesyncdevicepartnership -eq $true -and -not displayname -like "CAS_{*"} -ResultSize Unlimited;
# Approve each device
foreach ($CASMailbox in $CASMailboxes)
{
# Array to store devices 
$DeviceIDs = @();
# Retrieve the ActiveSync Device Statistics for the associated user mailbox 
[array]$ActiveSyncDeviceStatistics = Get-ActiveSyncDeviceStatistics -Mailbox $CASMailbox.Identity;
# Use the information retrieved above to store information one by one about each ActiveSync Device
foreach ($Device in $ActiveSyncDeviceStatistics)
{
$DeviceIDs += $Device.DeviceID
}
Set-CasMailbox $CASMailbox.Identity -ActiveSyncAllowedDeviceIDs $DeviceIDs
} 

After running this script, you can verify if it was successful by running the following PowerShell command against one of your employee mailboxes.

Get-CASMailbox -Identity mail@domain.com | fl *ActiveSync*

If they had a mobile device connected to Exchange, then its corresponding DeviceID should now be within the ActiveSyncAllowedDeviceIDs object. The images below show the output of this command before running the pre-approval script, and afterwards.

Before ActiveSync DeviceID approval.

After ActiveSync DeviceID approval. This employee has one device approved.

Now that all of the currently connected devices have been added to the ActiveSyncAllowedDeviceIDs object on each mailbox, you can move forward with enabling the ActiveSync Quarantine. In order to do this, you will need to determine what E-Mail address will be setup to receive the quarantine messages whenever a device has E-Mail configured onto it. It is recommended to use something like a Distribution Group, so that multiple individuals within your IT department will receive the E-Mail alerts. You also have the option of adding your own custom text to the E-Mail that employees will see in the event that they attempt to add E-Mail to a device themselves. Once you have determine those two details, you can move forward by running the following script (this example contains the optional custom text).

Set-ActiveSyncOrganizationSettings -DefaultAccessLevel Quarantine -AdminMailRecipients mail@domain.com -UserMailInsert "Your mobile device has not yet been approved for E-Mail use. If you have any questions or concerns, please contact the IT Department of [Business Name] for further assistance."

Once this has ran, you will now have the ActiveSync Quarantine enabled within your Exchange server. Any new devices that are configured for E-Mail access will now be put into this quarantine, pending an Administrator's approval.

Stay tuned for Part II, where we go over the quarantine approval process, along with how to delegate access to this feature for your team.

October 14, 2016

In the past, I had found myself needing to do an audit on some network shares for any files that might contain passwords. Instead of doing manual searches on these shares, I decided that it might be more beneficial to create a PowerShell script that would provide a more automated approach. What I needed was a script that could be easily ran against various network share locations, searching for a particular string (e.g. "password"). Any file that was found to have this string within either its filename or the contents of the file would then have its full path added to the chosen output text file. For my audit, I was not interested in the passwords themselves, but more concerned with the existence of such password files.

For this particular script, we will be configuring it to accept input directly from the user while executing it via a command-line. By configuring these parameters, found in the following code snippet, you will be able to pass the Directory that you want to run a recursive search under, the text that you wish to search for, and the output file you wish to save your results to directly into the PowerShell script. This is extremely useful for scripts that you may run often, and with different parameters, as you will not have to directly modify the source code each time you wish to run it.

[CmdletBinding()]
Param (
    [Parameter(Mandatory=$True,Position=0)]
    [string]$Directory,

    [Parameter(Mandatory=$True,Position=1)]
    [string]$Text,

    [Parameter(Position=2)]
    [string]$Output
)

The next part of this script will be to define what file extensions we wish to perform our text search against into an Array. Feel free to add any additional file extensions that you might want to try and search against, but know that not all extensions work well with this method of searching.

$Extensions=@("TXT","XLS","CSV","DOC","RTF")

Now that we have the extensions that we wish to search for declared in an Array, with will need to loop through each of these extensions, prepending "*." so that we can search for any possible file with that particular file extension. The beginning of this loop will look like so.

ForEach ($Extension in $Extensions) {
    $File = "*." + $Extension

The next part of this loop will be to recursively get a list of all of the files located within the directory given as part of this script's parameters. The results of this code snippet will need to be piped over to the next step.
Get-ChildItem $Directory -Filter $File -Recurse -Force |

The previously obtained list of files will be piped into another loop. For this, we will utilize the ForEach-Object cmdlet, looping through each file. For ease of use, the beginning of this loop will create a progress bar that will show what file is currently being scanned. This will be most useful whenever you are running this script against a directory with numerous files and sub-directories.

Write-Progress -Activity "Scanning Files..." `
$_

The first search we will perform against the current file (via the loop) is to determine if the specified search string is contained within the contents of said file. If so, then the current file's path and filename will be added to the output file (specified in the script's parameters).

If (Get-Content $_.FullName | Select-String -Pattern $Text)
{
        Add-Content -path $Output -value $_.FullName
}

Next, we will scan the current file's filename and determine if the specified search string resides within it. For example, if you are running this script to search for the string "password," it will not only provide you with files that contain the string "password" within their contents, but also any files with "password" in their filename (e.g. MySecretPasswords.txt).

$WildCardText = "*" + $Text + "*"
If ($_.FullName -like $WildCardText)
{
       Add-Content -path $Output -value $_.FullName
}

When this script is all together, it will be the following.

#SearchForString $Directory $Text $Output
#Example:
#SearchForString "\\FileServer\Accounting" "password" "C:\PasswordFiles.txt"


#Define Parameters
[CmdletBinding()]
Param (
    [Parameter(Mandatory=$True,Position=0)]
    [string]$Directory,

    [Parameter(Mandatory=$True,Position=1)]
    [string]$Text,

    [Parameter(Position=2)]
    [string]$Output
)


#Define File Extensions to Audit
$Extensions=@("TXT","XLS","CSV","DOC","RTF")


#Loop through each Extension in our $Extensions Array
ForEach ($Extension in $Extensions) {
    $File = "*." + $Extension

    #Get all files in $Directory
    Get-ChildItem $Directory -Filter $File -Recurse -Force |
            
            #Loop through all files
            ForEach-Object {
                #Write our scan's progress to the progress bar (what file we're currently on)
                Write-Progress -Activity "Scanning Files..." `
                $_

                #If content of file contains $Text, write to $Output file
                If (Get-Content $_.FullName | Select-String -Pattern $Text)
                {
                Add-Content -path $Output -value $_.FullName
                }

                #If filename contains $Text, write to $Output file as well
                $WildCardText = "*" + $Text + "*"
                If ($_.FullName -like $WildCardText)
                {
                    Add-Content -path $Output -value $_.FullName
                }
            }
}

Running this script is very simple, as we have specified parameters which we can utilize in order to avoid having to modify the original PowerShell script each time we wish to run it. The following screenshot shows an example of what the command for running this script might look like.

Example of script execution.

As the script is being executed, you should see a progress bar that will display what file is currently being scanned.

The script's progress bar in action.

Once the script has finished, you should have all of your results stored within the specified output file. The contents of which might look like the following.

The results of your scan.

September 30, 2016

In the previous post, IT Admin Tips: Create Personal Folders for All Active Directory Users With PowerShell, we went through the steps to create a PowerShell script that would go through your list of Domain Accounts and create a Personal Folder for each active account. This is very useful when you are first implementing Personal Folders, but what about creating Personal Folders for newly created Domain Accounts? Wouldn't it be helpful to have something in-place that automatically creates a properly configured Personal Folder for newly created Domain Accounts within minutes of the account being created? In this post, that is precisely what we will go through creating.

Just like in the previous post, we will begin by importing the ActiveDirectory module for use and setting a variable to be the UNC path for the shared folder.

import-module ActiveDirectory

$Directory = "\\UNCPATHTOSHAREDFOLDER"

Next, we will be doing something similar to what we did within the post IT Admin Tips: Creating AD User Account Alerts, with regards to the "Account Created Alert" that was created. Just like in that post, we will begin by storing the contents of the most recent Event ID 4720, which is generated whenever a new Domain Account is created, into a variable for use.

$Event = Get-EventLog -LogName Security -InstanceId 4720 -Newest 1

Next, we will need to parse out the Domain Account's username from the Event ID. This can be accomplished via the following code.

[String]$String = $Event.ReplacementStrings
$UserName = ($String).split()[0]

Now that we have the username for the newly created user, we can obtain information on this account from Active Directory, which we will use when creating the Personal Folder.

$ADUserData = Get-ADUser $UserName
$Name = $ADUserData.Name
$UserID = $ADUserData.SamAccountName[String]$String = $Event.ReplacementStrings
$UserName = ($String).split()[0]

Just like with the previous post, we will now create a Personal Folder for this newly created Domain Account, along with assigning the Full Control permission to this folder for the account.

New-Item -type directory -Path "$Directory\$Name"

$ACL = Get-Acl "$Directory\$Name"
$AccessRule = New-Object  system.security.accesscontrol.filesystemaccessrule($UserID,"FullControl","ContainerInherit,ObjectInherit","None","Allow")
$ACL.SetAccessRule($AccessRule)
Set-Acl "$Directory\$Name." $ACL

When this code is put all together, we end up with something like the following.

#Import the ActiveDirectory module in order to access AD via PowerShell
import-module ActiveDirectory

#The UNC path for the shared folder
$Directory = "\\UNCPATHTOSHAREDFOLDER"

#Get the contents of the most recent Event ID 4720 (generated when an account is created)
$Event = Get-EventLog -LogName Security -InstanceId 4720 -Newest 1

#Parse out the UserName
[String]$String = $Event.ReplacementStrings
$UserName = ($String).split()[0]

#Get User's Active Directory Object Data
$ADUserData = Get-ADUser $UserName
$Name = $ADUserData.Name
$UserID = $ADUserData.SamAccountName

#Create the new user's Personal Folder
New-Item -type directory -Path "$Directory\$Name"

#Give the user Full Control permissions to their Personal Folder
$ACL = Get-Acl "$Directory\$Name"
$AccessRule = New-Object  system.security.accesscontrol.filesystemaccessrule($UserID,"FullControl","ContainerInherit,ObjectInherit","None","Allow")
$ACL.SetAccessRule($AccessRule)
Set-Acl "$Directory\$Name." $ACL

Once this script has been created, you can schedule it within Task Scheduler on your Active Directory server using a Domain Account with the appropriate access. Ideally, this account would be some sort of "service" account and not associated with a particular IT Admin. In order for the new Domain Account's Personal Folder to be created immediately, you will need to configure the task to be triggered whenever Security Event ID 4720 occurs.
Subscribe to RSS Feed Follow me on Twitter!