Skip to the main content.

ScriptRunner Blog

The Hidden, The Obfuscated

Table of Contents

 

 

Post Featured Image

In this article, we will explore the not so obvious in PowerShell, the information that is hidden from direct view and requires additional steps to reveal. For example, did you know that even with using Format List, that not all details are revealed? For the longest time, I thought this was true, but in Microsoft 365 for example, there are cmdlets which have hidden object properties. Also, some cmdlets require extra switches to reveal additional detail in their output. This text will cover these and provide tips on how to find out if you are missing those details, so you can get the most out of PowerShell.

Special Switches

The two switches that we need to cover are -Status and -IncludeReport. These two switches can reveal a bit more detail when it comes to certain commands and are available on a few cmdlets to retrieve additional information. These values are hidden to increase performance of the cmdlets as the information revealed is not needed by every script. Here are some examples:

-Status

This switch, when used with the Get-MailboxDatabase cmdlet reveals information about the mailbox databases on the server or servers that are running Exchange Server 2019. The above command produces a useful table like this:

01_Get-MailboxDatabase

If we run the same command with Format-List like this...

Get-MailboxDatabase | Fl

…what we notice is that some values are not populated. This could mean that there really isn't anything stored and thus the property is truly empty. However, this is not the case for some of these properties. For a Mailbox Database, this is true for the ‘Mounted’ field:

02_Get-MailboxDatabase Fl

Notice that this is blank. Why would this be blank? This would seem to be a rather important value. This is where the ‘-Status’ switch comes into play:

Get-MailboxDatabase -Status

Now we have an idea if the database is mounted or not:

03_Get-MailboxDatabase Status

Now there are some PowerShell cmdlets where the ‘-Status’ actually looks for the status of an object versus the switch revealing more information about something in Exchange. Another example is:

Get-ExchangeServer | fl

Without the -Status switch, there are many properties that are not populated:


ErrorReportingEnabled
CurrentDomainControllers
CurrentGlobalCatalogs
CurrentConfigDomainController

No ‘-Status’

04_no-Status

With ‘-Status’

05_with-Status


We see which one of the commands have an option for ‘-Status’ and found that there are quite a few that do. If we were to explore each one by simply typing the cmdlet name followed by the ‘-Status’ parameter, we can see which cmdlets use the ‘-Status’ switch to reveal more information and which cmdlets use the switch for filtering results/output.

‘-Status’ Used for Filtering

Get-MailboxRestoreRequest -Status

06_-Status error message

Notice the red error message, this means that a word or 'argument' is missing after the '-Status' parameter. The same results can be seen for these cmdlets:


Get-MessageTrackingReport -Status
Get-MigrationBatch -Status
Get-MigrationUser -Status
Get-PublicFolderMailboxMigrationRequest -Status
Get-PublicFolderMigrationRequest -Status
Get-PublicFolderMoveRequest -Status
New-UMAutoAttendant
New-UMIPGateway
Set-UMIPGateway
Set-UMService

 

-IncludeReport

The -IncludeReport switch could be considered a verbose switch for certain PowerShell cmdlets. The cmdlets most frequently used with the -IncludeReport switch are move request commands because they pertain to migration reports generated by Exchange. Examples of this are Get-MigrationBatch, Get-MoveRequestStatistics, and Get-PublicFolderMigrationRequestStatistics.

To see what the -IncludeReport switch brings to the table, the Get-MigrationBatch is a good example. Make sure to use the Format-List option to provide the full extent of the command. Without the -IncludeReport switch, the resulting output would be the base set of information on the migration that is being reported by the Get-MigrationBatch. Indeed, we notice that some values are empty, see this example:

07_Get-MigrationBatch Fl Report empty

Notice that two fields, one field called ‘Report’, and another called ‘Reports’, both of which are empty. If we run this one-liner:

Get-MigrationBatch -IncludeReport | Fl Report*

The Report/Reports fields will be populated and include information like this:

08_Get-MigrationBatch -IncludeReport

While that information is good for migrations, we can reveal even more information when applying this switch to the Get-MoveRequestStatistics cmdlet:

Get-MoveRequestStatistics -IncludeReport | Fl Report*

09_Get-MigrationBatch -Get-MoveRequestStatistics

As you can see, for this cmdlet, -IncludeReport is like verbose for mailbox move requests.

 

FL *

Microsoft recently added a new Reply All Storm protection feature in Exchange Online which is a boon to organizations that have had issues with ReplyAlls that result in hundreds or thousands of emails causing all sorts of issues. In Exchange Online this is a global feature that should be visible with the Get-TransportConfig. However, the settings are not actually visible if we run that cmdlet like this:


Get-TransportConfig
Get-TransportConfig | Ft
Get-TransportConfig | Fl

Why? I believe this is one of several hidden properties for Exchange Online. How can we reveal the Reply All Storm protection properties? Well, there are two options to show this:


Get-TransportConfig | Fl *

And


Get-TransportConfig | Fl Reply*

10_Get-TransportConfig

Now using 'Fl *' is not something I would have expected. As a user of PowerShell since 2007, the use of ‘Fl’ from my experience has typically exposed all properties of an object with PowerShell. However, adding the asterisk with the ‘Fl’ is something new … In fact, using the 'Fl *' on this cmdlet reveals 28 extra properties of Exchange Online’ s Transport Config:


AgentGeneratedMessageLoopDetectionInSmtpEnabled
AgentGeneratedMessageLoopDetectionInSubmissionEnabled
AllowLegacyTLSClients
AttributionRejectBeforeMServRequest
AttributionRejectConsumerMessages
ConvertReportToMessage
CurrentTransportSystemState
DiagnosticsAggregationServicePort
JournalReportDLMemberSubstitutionEnabled
MaxAllowedAgentGeneratedMessageDepth
MaxAllowedAgentGeneratedMessageDepthPerAgent
OrganizationFederatedMailbox
OtherWellKnownObjects
PreserveReportBodypart
QueueDiagnosticsAggregationInterval
ReplyAllStormBlockDurationHours
ReplyAllStormDetectionMinimumRecipients
ReplyAllStormDetectionMinimumReplies
ReplyAllStormProtectionEnabled
TransportRuleAttachmentTextScanLimit
TransportRuleCollectionAddedRecipientsLimit
TransportRuleCollectionRegexCharsLimit
TransportRuleConfig
TransportRuleLimit
TransportRuleMinProductVersion
TransportRuleRegexValidationTimeout
TransportRuleSizeLimit
TransportSystemState

Last example is DLP Sensitive Information Types that are present in the Security and Compliance Center PowerShell module. If we were to list a specific one within PowerShell, using '| Fl' we see these results:

11_Fl results

While there is some detail, we are missing details that would be nice to have. What if we tried the '| Fl *' trick with the asterisk once more?

12_Fl results with asterisk

When the ‘Fl *’ is used with Get-DLPSensitiveInformationType, more properties of the Sensitive Information Type are revealed: RecommendedConfidenceLevel, HighConfidenceLevelEntityDetails, MediumConfidenceLevelEntityDetails, LowConfidenceLevelEntityDetails, PrimitiveElementDetails, Classifier, Fingerprints and more.

 

Exchange Online V2

In a different vein, but still consisting of hidden values, the new Exchange Online V2 (EXO V2) cmdlets purposely hide information to generate faster results for an Exchange Online Administrator. How is this done? By limiting properties returned on via a select number of commonly used cmdlets.

Reducing Data

In order to get this performance, Microsoft needed to reduce the data returned (compare Microsoft documentation). The data returned can be quite pared down and in fact can be pared down too far. Two different settings help with this reduction and those are Properties and Property Sets. These two different methods will help determine how much data is pulled when one of these new cmdlets is run. Getting to know these will help us get to know how to use them properly and efficiently. Let’s review these items.

Property Sets

A Property Set is a predefined group of object properties that Microsoft has thought to be a logical grouping. These sets reveal properties that can then be revealed by the new EXO V2 cmdlets. We won’t be able to simply list all the properties of an object and filter them on output. We need to decide what we want, and pick the Properties Sets available to us. Let’s take the example of Get-Mailbox:

Scenario – need to check quotas on all resource mailboxes, while listing basic information about the mailbox itself.

Old Method

Get-Mailbox | Where {$_.IsResource -eq 'True'} | Ft Name, Alias, PrimarySMTPAddress, *quota

New EXO V2 Method

With the new cmdlets, we need to rely on either Property Sets like this:

Get-EXOMailbox -PropertySets Minimum, Resource, Quota | Where {$_.IsResource -eq 'True'} | ft

If we did not add the 'PropertySets' parameter, the cmdlet would just return an empty result set as no properties for the objects would have been returned for PowerShell to filter, let alone display to the screen. Now, we do not have to filter the results from a cmdlet using the PropertySets parameter and instead just have PowerShell return all values for a Property Set. For example, if we chose the Quota Property Set, but did not filter the results, we would get all of these properties for each object:

Properties


ArchiveQuota
ArchiveWarningQuota
CalendarLoggingQuota
xternalDirectoryObjectId
IssueWarningQuota
ProhibitSendQuota
ProhibitSendReceiveQuota
RecoverableItemsQuota
RecoverableItemsWarningQuota
RulesQuota
DatabaseQuotaDefaults

There is one common property in all Property Sets and this is ExternalDirectoryObjectId. According to MSDN ' This attribute specifies the unique identifier for users and groups and is populated when applicable Windows Server releases of Active Directory are federated with Azure Active Directory.'

Properties are the single values that make up the various Property Sets for the new cmdlets. We can use Properties to reveal singular values for an object instead of relying on a full set of properties. While this allows for targeted value pulls, it can quickly grow out of hand depending on the number of properties needed. For example, if we rely on choosing our Properties for the previous Get-Mailbox cmdlet above, we will get something like this:

Get-EXOMailbox -properties Name,Alias,PrimarySMTPAddress, IsResource, IssueWarningQuota, ProhibitSendQuota,ProhibitSendReceiveQuota | Where {$_.IsResource -eq 'True'} | ft

While this provides the same results, it is already becoming quite unwieldy. Thus, choosing between the two options (Properties or Property Sets) can be important for your scripts. My advice would be to review the source post for list above and get familiar with all the Properties and Property Sets.

 

Conclusion

Hidden information as revealed in these examples can be crucial to working with PowerShell. For most of the examples, it makes sense for these items to be hidden from most initial queries with PowerShell. However, if we are expecting more to be revealed from the get-go, then this obfuscation may prove to be more frustrating than expected. A technique that can be used when empty properties are found is to see if there are additional parameters (-Status or -Includereport for example) or using FL*. Looking at the help for a cmdlet or revealing all the switches for the cmdlet, may help lead to the discovery of other examples of hidden data. So, if the information you are looking for is not revealed, dig a little deeper and you may still find it.

 

 


Related Links

 

Related posts

3 min read

ScriptRunner now available in the Microsoft Azure Marketplace

6 min read

Managing Microsoft Exchange with PowerShell

2 min read

VMUG Webcast: Mastering VMware Management with PowerCLI

About the author: