function Get-OldBrowserUsage { <# .SYNOPSIS Gets data for web browser usage in the specified period where the browser was released more than 30 days prior to the usage date. .DESCRIPTION Gets data for web browser usage in the specified period where the browser was released more than 30 days prior to the usage date. .PARAMETER Path The Path to the xml data file containing the browser release information. .PARAMETER After The cutoff datetime after which the browser activity must have occurred to be included in the result set. .PARAMETER MinBrowserAge The minimum age of the browser version at the last activity date to be included in this result set. .INPUTS none .OUTPUTS PSCustomObject[] .NOTES Version: 1.0 Author: Robert Thomson Creation Date: 2025-01-03 Purpose/Change: Initial script development Dependencies: Requires the PSFalcon Module available at https://github.com/CrowdStrike/psfalcon. References [1] CrowdStrike API Specification. Retrieved January 3, 2025, from https://assets.falcon.crowdstrike.com/support/api/swagger.html#/discover/combined-applications .EXAMPLE Get-OldBrowserUsage Retrieves information on browsers and hosts where the activity occurred in the last 30 days and, at the time of the activity, the browser version was more than 30 days old. .EXAMPLE Get-OldBrowserUsage -After [Datetime]::now.AddDays(-7) -MinBrowserAge 35 Retrieves information on browsers and hosts where the activity occurred in the last 7 days and, at the time of the activity, the browser version was more than 35 days old. #> [cmdletBinding()] Param( [parameter()] [validateScript({Test-Path -path $_})] [ValidateNotNullOrEmpty()] [string]$Path, [parameter()] [datetime]$After = [datetime]::Now.AddDays(-30), [parameter()] [ValidateRange(0,5000)] [string]$MinBrowserAge = 30 ) $FalconSplat = @{ 'Filter' = "(last_used_file_name:'msedge.exe',last_used_file_name:'chrome.exe')+last_used_timestamp: >= '$($After.ToString('o'))'" 'Include' = 'install_usage', 'host_info' 'Application' = $true 'Detailed' = $true 'All' = $true } <# # The CS API will return activity for more than one version on a host. # We only want the latest so we dedupe by activity date #> $BrowserUsage = Get-FalconAsset @FalconSplat $deduped = @{} $BrowserUsage | ForEach-Object { if ($_.last_used_timestamp -gt $deduped[$_.host.hostname].last_used_timestamp ) { $deduped[$_.host.hostname] = $_ } } $xml = [xml]::new() $Path = (Resolve-Path -Path $Path).Path $xml.Load($Path) $XPath = '/browserReleaseInfo/apps/application[@name="{0}"]/channel[@name="Stable"]/release[@version="{1}"]' <# # We are finding the same node 3 or 4 times to take advantage of having # all of our properties fixed up in Select_Object. # Since the xml file is already in memory we don't care, but if # performance is an issue we could run the deduped values into a # ForEach-Object loop and select it once at the begining of the loop # and assigning it to a variable. Then we could just change the properties # array to just reference the assigned variable rather than the call to # SelectSingleNode. #> $Props = @( '*' @{'Name' = 'hostname'; 'Expression' = {$_.host.hostname}} @{'Name' = 'aid'; 'Expression' = {$_.host.aid}} @{ 'Name' = 'published' 'Expression' = { $xml.SelectSingleNode(($xpath -f $_.name, $_.version)).published } } @{ 'Name' = 'pubTimestamp' 'Expression' = { $xml.SelectSingleNode(($xpath -f $_.name, $_.version)).pubTimestamp } } @{ 'Name' = 'BrowserAgeAtLastUse' 'Expression' = { if ($null -eq $xml.SelectSingleNode(($xpath -f $_.name, $_.version))) { $null } else { $lu = [datetimeoffset]::Parse($_.last_used_timestamp) $pubdate = [datetimeoffset]::Parse($xml.SelectSingleNode(($xpath -f $_.name, $_.version)).published) $lu.subtract($pubdate).TotalDays } } } ) $ExcludeProps = @( 'id', 'cid', 'host', 'name_vendor', 'name_vendor_version' 'is_suspicious', 'is_normalized', 'versioning_scheme' ) $BrowserUsageInfo = $deduped.Values | Select-Object -Property $Props -ExcludeProperty $ExcludeProps $Suspect = $BrowserUsageInfo | where-object { [string]::IsNullOrEmpty($_.BrowserAgeAtLastUse) -or ($_.BrowserAgeAtLastUse -ge $MinBrowserAge) } Write-Output -NoEnumerate $Suspect }